Se non esistessero le istruzioni di salto (jump), i programmi sarebbero sempre eseguiti nello stesso modo, sequenzialmente, e non sarebbero molto utili. Questo tipo di istruzioni è infatti importantissimo, dal momento che consente al programmatore di alterare in maniera controllata ed esplicita la sequenza di esecuzione del programma, come si può fare nei linguaggi ad alto livello (con l'istruzione GOTO). Il controllo dell'esecuzione può, grazie ad una istruzione di salto, essere passato da una parte all'altra del programma.
Le istruzioni di salto agiscono sul contenuto del Program Counter (PC), registro interno che, come si è visto in precedenza, è responsabile della sequenza di esecuzione delle istruzioni (contiene al proprio interno l'indirizzo in memoria della successiva istruzione da eseguire).
Il salto è detto incondizionato quando avviene sempre e non dipende dal verificarsi o meno di una certa condizione. Vediamo subito un esempio:
L'esecuzione di questa istruzione produce l'assegnazione del valore dell'indirizzo (2000h nell'esempio) al Program Counter, e quindi il prelievo della successiva istruzione sarà eseguito non più dalla locazione successiva a quella della istruzione corrente, ma dalla locazione all'indirizzo specificato. Vediamo tutto questo più concretamente considerando il seguente spezzone di programma in assembly:
Indirizzo | Istruzione | Commento |
10FFh | LD A,B | ;istruzione precedente (qualsiasi istruzione) |
1100h | JP 2000h | ;salta alla locazione 2000h |
1103h | NOP | ;non viene eseguita (il µP salta a 2000h) |
... | ... | |
2000h | CP B | ;l'esecuzione prosegue da questa istruzione |
In pratica, nell'esempio precedente, tutte le istruzioni comprese fra 1103h e 2000h vengono ignorate dal µP. Si noti che l'indirizzo dell'istruzione JP è 1100h, mentre l'indirizzo dell'istruzione successiva è 11003h. La ragione è che l'istruzione JP occura 3 byte, uno per il codice operativo (C3) e due per l'operando a 16 bit (in ordine inverso come al solito, JP 2000h corrisponde a C30020h).
Quando si usano istruzioni di salto risulta particolarmente comodo l'utilizzo di etichette, per evitare di doversi calcolare gli indirizzi (in questo modo il calcolo viene fatto automaticamente dall'assemblatore, che si occupa di sostituire le etichette con gli indirizzi corrispondenti). Per esempio il programma precedente, scritto usando le etichette diventa:
Quando il salto avviene a un indirizzo di memoria successivo (più alto) si parla di salto in avanti; viceversa si ha il salto all'indietro. Come esempio di salto all'indietro si consideri questo spezzone di programma:
Questo è un esempio di ciclo infinito: a causa del salto all'indietro alla locazione CICLO, verranno ripetute all'infinito le istruzioni comprese tra l'etichetta CICLO ed il salto JP CICLO.
Un ciclo infinito ha generalmente scarsa rilevanza pratica, eccetto che in pochi casi: per esempio quando si vuole che un programma ripeta sempre uno stesso gruppo di operazioni, fino allo spegnimento fisico del sistema. Vedremo più avanti come una Interruzione (Interrupt) permetterà al microprocessore di uscire da un ciclo infinito, e andare ad eseguire un altro programma.
I tipi di salto più importanti dal punto di vista computazionale sono quelli condizionati. Questi salti sono eseguiti o no dal processore a seconda dello stato di una ben precisa condizione e permettono al µP di prendere "decisioni". La sintassi generale di un'istruzione di salto condizionato è:
JP <condizione>,<indirizzo>
ome nei salti incondizionati, anche qui l'indirizzo indica la locazione a cui saltare, mentre la <condizione> determina se il salto può essere effettuato o no. Scopriamo finalmente a cosa servono i flag del flag register: la <condizione> di cui si parla è infatti fornita unicamente dallo stato logico dei flag.
Tra le varie condizioni possibili, ne vediamo solo alcune, quelle più usate:
Il salto viene eseguito solo se la condizione è verificata, in caso contrario il processore prosegue con l'istruzione successiva a quella del salto, come se niente fosse successo. Per un elenco completo delle condizioni possibili si rimanda alla tabella riassuntiva delle istruzioni.
Gli esempi presentati finora, che fanno uso dell'istruzione JP, sono tutti salti assoluti, nel senso che l'istruzione specifica l'indirizzo completo della locazione di memoria a cui si vuole saltare.
Un'altra categoria di istruzioni di salto è quella dei cosiddetti salti relativi (JR). In questo caso non viene fornito l'indirizzo assoluto a cui saltare, ma il salto viene specificato relativamente all'indirizzo dell'istruzione corrente. Vediamo un esempio:
Il valore costante che accompagna l'istruzione JR (15 nell'esempio precedente) è detto offset ed è un numero a 8 bit rappresentato in complemento a due, cioè con segno. In pratica l'offset può assumere tutti i valori compresi fra -128 (all'indietro) e +127 (in avanti). Ciò restringe l'ampiezza dell'area di memoria a cui è possibile saltare con una JR a solo 256 locazioni intorno a quella corrente.
Il vantaggio di usare salti relativi, invece di quelli assoluti, è che in questo modo il codice prodotto risulta rilocabile, cioè può essere spostato in differenti locazioni di memoria ed essere eseguito correttamente. Inoltre l'istruzione JR occupa meno byte (avendo un operando a 8 bit invece di 16). La tabella mostra un confronto fra le due istruzioni
Assoluto | Relativo | |
---|---|---|
Istruzione | JP | JR |
Lunghezza operando | 16 bit | 8 bit |
Lunghezza istruzione | 3 byte | 2 byte |
Destinazione | ovunque | 128 bytes prima o dopo |
Come per il salto assoluto, anche il salto relativo può essere condizionato, come mostrano gli esempi seguenti:
Come nel salto assoluto, anche in quello relativo risulta molto conveniente l'uso di etichette nella scrittura del programma (in questo caso è l'assemblatore che si occupa di calcolare l'offset):
Un'istruzione di salto relativo un po' particolare è la DJNZ. Questa istruzione fa riferimento al registro B, lo decrementa ed effettua il salto all'indirizzo relativo specificato se B è diverso da zero. Si tratta di un'istruzione particolarmente comoda per scrivere cicli usando il registro B come contatore. Si consideri ad esempio il seguente ciclo di ritardo scritto usando la DJNZ:
Sito realizzato in base al
template offerto da
http://www.graphixmania.it