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:
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.
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:
In modo simile anche la RET può essere eseguita o meno in dipendenza di una certa condizione:
Per un elenco completo delle condizioni possibili si rimanda alla tabella riassuntiva delle istruzioni.
Sito realizzato in base al
template offerto da
http://www.graphixmania.it