ELEMANIA
Z80 - Sottoprogrammi: chiamata e ritorno
Sottoprogrammi: CALL e RET

In informatica si dice sottoprogramma (o anche funzione, subroutine, routine, procedura) una sequenza di istruzioni utilizzabile come se si trattasse di un programma autonomo, ma la cui esecuzione è subordinata a quella di un programma principale. I sottoprogrammi sono molto utili per svolgere compiti ripetitivi senza essere obbligati ogni volta a riscrivere lo stesso codice.

Vediamo subito un esempio di sottoprogramma in assembly Z80:

            LD SP,00000h     ; inizializza il fondo dello stack a 0000h
            LD B, 2              ; carica in B il numero 2
            LD C, 5              ; carica in C il numero 5
            CALL SOMMA      ; chiama il sottoprogramma di nome SOMMA
            LD B, D              ; carica D in B
            LD C, 7              ; carica in C il numero 7
            CALL SOMMA      ; chiama il sottoprogramma di nome SOMMA
            LD E, D              ; carica D in E

            .....                  ; il programma prosegue con altre istruzioni

SOMMA: LD A,B             ; carica B in A (inizio del sottoprogramma)
            ADD A,C           ; somma A e C e mette il risultato in A
            LD D, A            ; sposta il risultato della somma in D
            RET                 ; ritorna al punto di chiamata (fine del sottoprogramma) 

Il sottoprogramma dell'esempio si chiama SOMMA e, come suggerisce il nome, effettua la somma fra due numeri contenuti nei registri B e C e mette il risultato della somma nel registro D. L'inizio del sottoprogramma è segnalato dall'etichetta SOMMA e la fine dall'istruzione RET.

Si osservi che lo stack viene inizializzato con l'indirizzo 0000h, cioè con il primo indirizzo in memoria. Tale inizializzazione è abbastanza frequente quando la memoria RAM (cioè contenente lo stack) occupa la parte alta dello spazio degli indirizzi dello Z80. In questo modo al primo decremento dello stack (cioè all'esecuzione della prima PUSH), lo stack punta all'ultima locazione in memoria (infatti sottraendo 1 dall'indirizzo 0 si ottiene l'ultimo indirizzo FFFFh in RAM).

Questo "trucco" consente anche di non inizializzare esplicitamente SP in un programma, confidando sul fatto che al reset del microprocessore lo SP venga inizializzato automaticamente col valore zero. Tuttavia il manuale ufficiale dello Z80 non prevede esplicitamente l'azzeramento dello SP al RESET del microprocessore e dunque è sempre meglio azzerarlo esplicitamente all'inizio di ogni programma.

L'istruzione CALL avvia l'esecuzione del sottoprogramma (chiamata) ed è simile a un'istruzione di salto (JP) in quanto provoca un salto nella sequenza di esecuzione del programma all'etichetta SOMMA (naturalmente, volendo complicarsi la vita, invece dell'etichetta sarebbe possibile scrivere direttamente l'indirizzo della locazione di memoria di inizio del sottoprogramma):

Il sottoprogramma viene quindi eseguito fino all'istruzione RET (ritorno). Questa istruzione obbliga il µP ad effettuare un altro "salto speciale" fino alla locazione di memoria immediatamente successiva a quella della CALL che ha "chiamato" il sottoprogramma:

Osserviamo che nel nostro programma è presente anche una seconda chiamata a SOMMA. Il meccanismo è simile al precedente però stavolta l'istruzione RET ritorna all'istruzione LD E,D (cioè l'istruzione immediatamente successiva alla seconda chiamata):

Osserviamo la particolarità del meccanismo di chiamata e ritorno. Volendo la chiamata al sottoprogramma potrebbe essere effettuata anche con un semplice salto (p.es. con una JP SOMMA), dato che ne conosciamo l'indirizzo (identificato dall'etichetta SOMMA); ma la stessa cosa non si può fare per il ritorno, perché non è lo stesso nei due casi. Infatti, il sottoprogramma dovrebbe tornare al chiamante, nel primo e nel secondo caso, con due istruzioni di salto diverse, perché diversi sarebbero gli indirizzi di ritorno.

Evidentemente il µP deve memorizzare da qualche parte l'indirizzo di ritorno al momento dell'esecuzione dell'istruzione CALL, in modo da poter usare tale indirizzo al momento dell'esecuzione dell'istruzione RET. L'area in cui vengono salvati gli indirizzi di ritorno dei sottoprogrammi è lo stack, come vedremo meglio nella prossima lezione.

Istruzioni CALL e RET condizionate

Come per le istruzioni di salto, lo Z80 possiede anche un'istruzione di CALL condizionata in base al contenuto del flag register. Abbiamo per esempio:

            CALL C, SOMMA      ; chiama SOMMA se Carry = 1
            CALL NC,SOMMA     ; chiama SOMMA se Carry = 0
            CALL Z, SOMMA      ; chiama SOMMA se il Flag di Zero = 1
                                       ;(cioè se il risultato precedente e` stato ZERO)
            CALL NZ,SOMMA     ; chiama SOMMA se il Flag di Zero = 0
                                       ;(cioè se il ris. prec. e` stato NON ZERO)

In modo simile anche la RET può essere eseguita o meno in dipendenza di una certa condizione:

            RET C      ; torna al chiamante se Carry = 1
            RET NC     ; torna al chiamante se Carry = 0
            RET Z      ; torna al chiamante se il Flag di Zero = 1
            RET NZ     ; torna al chiamante se il Flag di Zero = 0

Per un elenco completo delle condizioni possibili si rimanda alla tabella riassuntiva delle istruzioni.

 

precedente - successiva

Sito realizzato in base al template offerto da

http://www.graphixmania.it