ELEMANIA
PIC16F690 - Chiamata a subroutine
Chiamata e ritorno da subroutine

Una subroutine è un sottoprogramma, cioè un piccolo programma scritto per svolgere una determinata funzione. Ad esempio si potrebbe voler scrivere una subroutine di nome ritardo per generare un ciclo di ritardo con una certa durata.

Le subroutine vengono chiamate, cioè mandate in esecuzione, dal programma principale. La chiamata a subroutine è simile ad una istruzione GOTO con ritorno, cioè si salta in un altro punto della memoria di programma, si esegue un certo pezzo di codice e poi si ritorna all'istruzione immediatamente successiva a quella da cui abbiamo saltato.

L'istruzione che effettua il salto (chiamata a subroutine) nell'assembly del PIC è la CALL, mentre l'istruzione di ritorno può essere o RETURN, oppure RETLW. In pratica per chiamare una subroutine è sufficiente invocare la CALL specificando l'indirizzo della prima istruzione di tale subroutine (tale indirizzo viene per lo più indicato con un'etichetta, come già visto per le istruzioni di salto).

Il codice viene quindi eseguito dal punto specificato dall'etichetta in poi sino a che non si giunge ad una istruzione di RETURN o RETLW. Giunti a questo punto si ritorna ad eseguire il programma dall'istruzione immediatamente successiva alla CALL.

L'ultima istruzione di una data subroutine deve sempre essere o RETURN o RETLW (ovviamente se tali istruzioni non sono presenti il ritorno non avrà luogo). La figura seguente mostra il sistema di chiamata a subroutine:

La subroutine è in rosso e vengono messe in evidenza la prima istruzione e l'ultima (RETURN). Il programma principale non è mostrato per intero ma può trovarsi ovunque, prima della subroutine, dopo, oppure tutt'attorno alla subroutine stessa.

Quando nel programma principale si incontra una CALL viene eseguito il salto verso la locazione specificata (cioè alla prima istruzione della subroutine), si esegue il corpo della subroutine e poi si ritorna verso l'istruzione immediatamente successiva alla CALL grazie a RETURN (o RETLW). Notiamo infine che, come l'istruzione di salto GOTO, anche la CALL richiede sempre due cicli macchina per la sua esecuzione.

Lo stack

In che modo il microcontrollore riesce a "ricordarsi" il punto al quale tornare indietro? Esiste una piccola memoria ausiliaria, detta stack, in grado di memorizzare l'indirizzo di ritorno (l'indirizzo della istruzione immediatamente successiva alla CALL). Quando si esegue un RETURN tale indirizzo viene ripescato dallo stack.

Lo stack è una memoria di tipo LIFO (Last In, First Out) che nel PIC può contenere sino ad un massimo di otto indirizzi di programma. Si tratta di una piccola area di memoria autonoma, separata dalla RAM del PIC e non diversamente indirizzabile. L'uso dello stack consente di effettuare una CALL anche dentro una subroutine e ripetere tale processo ricorsivamente sino ad un massimo di otto volte (cioè otto CALL consecutive).

In pratica, dal momento che il PIC gestisce autonomamente lo stack, possiamo tranquillamente dimenticarci della sua esistenza, a patto di non utilizzare più di otto CALL annidate (cioè otto subroutine che si chiamano l'una dentro l'altra). In caso contrario si viene a verificare un cosiddetto stack overflow, il quale provoca funzionamenti anomali e non prevedibili del programma.

Sullo stack, le subroutine e le istruzioni di chiamata, vedi anche le lezioni sul µP Z80

CALL, RETURN e RETLW

L'uso delle istruzioni CALL e RETURN e abbastanza semplice e l'esempio seguente dovrebbe bastare per chiarirlo:

; Chiamare una subroutine che azzera il contenuto del registro 30 esadecimale
; Poi incrementare di una unità tale registro

            CALL azzera    ;vai alla subroutine "azzera"
            INCF 30         ; il programma prosegue con altre istruzioni
            ......

azzera:                     ;label di inizio della subroutine "azzera"
            CLRF 30        ;azzera il registro di indirizzo 30
            RETURN        ;ritorna indietro al programma principale

L'istruzione RETLW è simile alla RETURN ma in più consente di trasferire un valore al chiamante copiandolo nel registro W:

rtc    EQU 120            ; dichiara una locazione di memoria con nome rtc

        CALL mySub

        BANKSEL rtc
        MOVWF rtc    ; copia in rtc il registro W
        ...

mySub:
        ...
        RETLW 10    ; torna al chiamante il valore 10 (esadecimale) copiandolo in W

 

 

precedente - successiva

Sito realizzato in base al template offerto da

http://www.graphixmania.it