In questo passo analizzeremo il
funzionamento del Program Counter e dello Stack due
componenti importanti per la comprensione delle istruzioni di salto e chiamata a
subroutine.

Come visto nei passi precedenti, il PIC16F84
inizia l'esecuzione del programma a partire dal Reset Vector ovvero dalla
locazione di memoria 0000H. Dopo aver eseguito questa istruzione passa
all'istruzione successiva memorizzata nella locazione 0001H e così via.
Se non ci fossero istruzioni in grado di influenzare l'esecuzione progressiva del
programma, il PIC arriverebbe presto ad eseguire l'istruzione memorizzata nell'ultima
locazione e non saprebbe più come continuare.
Sappiamo ovviamente che non è così e che qualsiasi
sistema a microprocessore o linguaggio di programmazione dispone di istruzioni di salto,
ovvero istruzioni in grado di modificare il flusso di esecuzione del programma.
Una di queste istruzioni è il goto (dall'inglese go
to, vai a). Quando il PIC incontra una goto non esegue più
l'istruzione immediatamente successiva ma salta direttamente alla locazione di memoria
specificata nell'istruzione.
Facciamo un esempio:
ORG 00H
Point1
movlw 10
goto Point1
Al reset il PIC eseguirà l'istruzione movlw 10
memorizzata alla locazione 0000H che inserirà nell'accumulatore il
valore decimale 10. Quindi passerà all'istruzione successiva goto Point1.
Questa istruzione determinerà un salto incondizionato alla locazione di memoria puntata
dalla label Point1 ovvero di nuovo alla locazione 0000H.
Il programma non farà altro che eseguire un ciclo infinito
eseguendo continuamente le due istruzioni elencate.
Durante questo ciclo, per determinare quale è la
successiva istruzione da eseguire, il PIC utilizza uno speciale registro denominato Program
Counter ovvero contatore di programma. Questo viene sempre aggiornato con
l'indirizzo della prossima istruzione da eseguire. Al reset
esso viene azzerato, determinando l'inizio dell'esecuzione dall'indirizzo 0000H, ad ogni
istruzione viene invece incrementato di uno per consentire il passaggio all'istruzione
successiva.
L'istruzione goto consente l'inserimento
di un nuovo valore nel Program Counter ed il di conseguente salto ad una
locazione qualsiasi dell'area programma del PIC.

Un'altra istruzione molto interessante è la call
ovvero la chiamata a subroutine.
Questa istruzione funziona in maniera molto simile alla goto
con l'unica differenza che prima di eseguire il salto memorizza, in una locazione di
memoria particolare denominata Stack, l'indirizzo di quella che sarebbe
dovuta essere la prossima istruzione da eseguire se non ci fosse stata la call.
Vediamo meglio con un esempio:
ORG 00H
Point1
movlw 10
call Point2
goto Point1
Point2
movlw 11
return
In questo caso il PIC, dopo aver eseguito la movlw 10 passa ad eseguire la call
Point2. Prima di saltare memorizza nello Stack
l'indirizzo 0002H, ovvero l'indirizzo della locazione successiva alla
call. Passa quindi ad eseguire l'istruzione movlw 11, memorizzata in
corrispondenza della label Point2. A questo punto incontra una nuova
istruzione la return che, come di deduce dal suo nome, consente di
"ritornare", ovvero di tornare ad eseguire l'istruzione successiva alla call.
L'operazione appena effettuata viene denominata: "chiamata
a subroutine", ovvero interruzione momentanea del normale flusso del
programma per "chiamare" in esecuzione una serie di istruzioni, per poi tornare
al normale flusso di esecuzione.
Per poter riprendere da dove aveva interrotto, il PIC
utilizza l'ultimo valore inserito nello Stack e lo inserisce di nuovo nel
Program Counter.
La parola stack in inglese significa
"catasta" ed infatti su di esso è possibile accatastare l'uno
sull'altro gli indirizzi per recuperarli quando servono. Questo tipo di memorizzazione
viene anche denominata LIFO dall'inglese Last In
First Out, in cui l'ultimo elemento inserito (last in)
deve necessariamente essere il primo ad uscire (last out).
Grazie allo stack è possibile effettuare più call,
l'una dentro l'altra e mantenere sempre traccia del punto in cui riprendere il flusso al
momento che si incontra una istruzione return.
Vediamo un altro esempio:
ORG 00H
Point1
movlw 10
call Point2
goto Point1
Point2
movlw 11
call Point3
return
Point3
movlw 12
return
In questo caso nella subroutine Point2
viene effettuata un'ulteriore call alla subroutine Point3. Al ritorno da quest'ultima
il programma dovrà rientrare nella subroutine Point2 eseguire la return e quindi tornare nel flusso principale.
Gli indirizzi da memorizzare nello stack sono due in quanto
viene incontrata una seconda call prima ancora di incontrare la return corrispondente
alla prima. Si dice quindi che le call sono "nidificate" ovvero l'una dentro
l'altra.
Il PIC16F84 dispone di uno stack a
8 livelli, ovvero uno stack che consente fino ad 8 chiamate nidificate.
E' importante assicurasi, durante la stesura di un
programma, che ci sia sempre una istruzione return in corrispondenza
ad una call per evitare pericolosi disallineamenti dello stack che in
esecuzione possono dar adito a errori difficilmente rilevabili.
Nel passo successivo modificheremo
il nostro source LED.ASM per fissare meglio quanto
finora appreso. |