ELEMANIA
Z80 - Un programma di esempio
Un programma di esempio

Prima di vedere più nel dettaglio i diversi tipi di istruzioni disponibili per lo Z80, vale la pena di dare subito un'occhiata a un programma esemplificativo. Il lettore a questo punto probabilmente non sarà in grado di comprendere tutto, ma potrà avere fin dall'inizio una visione di come si presenta un programma in assembly e di come funzionano le principali istruzioni dello Z80.

Il programma dunque è il seguente:

	ORG 0		; la prossima istruzione verrà caricata all'indirizzo 0
	JP main		; salto incondizionato all'etichetta main

	ORG 100h	; la prossima istruzione verrà caricata all'indirizzo 100

main:
	LD A,0		; carica 0 in A
	OUT (0),A	; azzera (pulisce) la porta di uscita numero 0

	IN A,(0)	; legge in A dalla porta di ingresso numero 0
	LD B,A		; copia A in B

ciclo:
	IN A,(0)	; legge in A dalla porta di ingresso numero 0
	CP B		; confronta A con B (A-B)
	JP NZ,cambio	; se il risultato dell'operazione è 0, salta a cambio
	JP ciclo	; salto incondizionato all'etichetta ciclo

cambio:
	LD C,A		; copia A in C
	XOR B		; or esclusivo bit a bit di A con B
	OUT (0),A	; visualizza A sulla porta di uscita numero 0
	LD B,C		; copia C in B
	JP ciclo	; salto incondizionato all'etichetta ciclo

Il programma gestisce due porte (dispositivi di input-output): la porta di ingresso numero 0, collegata a un set di 8 micro interruttori (dip switch) e la porta di uscita numero 0, collegata a un set di 8 diodi led (la numerazione è uguale, ma si tratta di due dispositivi distinti, uno di input e l'altro di output).

Lo scopo del programma è il seguente: ogni qualvolta viene cambiato lo stato di uno degli 8 micro interruttori collegati con la porta di ingresso, il corrispondente led collegato con la porta di uscita viene acceso. In pratica il programma visualizza, tramite un led, l'interruttore che è stato modificato.

La figura seguente mostra uno schema di realizzazione circuitale simulato con DEEDS:

Simulatore DEEDS

L'assembly e la direttiva ORG

Notiamo anzitutto la tipica struttura di un programma scritto in assembly. Le istruzioni sono scritte una su ogni riga, partendo dalla seconda tabulazione (si ottiene col tasto TAB della tastiera). La prima colonna a sinistra è riservata alle etichette. I commenti iniziano col punto e virgola (;) e seguono le istruzioni. Per una questione di ordine, spesso anche i commenti vengono allineati con una ulteriore tabulazione.

All'inizio del programma troviamo un tipico uso della direttiva ORG. Non si tratta di un'istruzione (non produce codice eseguibile), ma di un comando per l'assemblatore, il quale specifica in quale posizione della memoria va caricato il programma. Si noti che la prima istruzione (JP main) viene caricata all'indirizzo 0, mentre il resto del programma (dall'etichetta main) viene caricato a partire dall'indirizzo 100h (esadecimale). Come vedremo meglio in seguito, questa soluzione viene spesso usata per lasciare all'inizio della memoria uno spazio libero per gli eventuali vettori di interrupt.

La fase di inizializzazione

Le istruzioni seguenti servono per inizializzare il funzionamento del µP e vengono eseguite una sola volta all'inizio del programma:

main:
	LD A,0		; carica 0 in A
	OUT (0),A	; azzera (pulisce) la porta di uscita numero 0

	IN A,(0)	; legge in A dalla porta di ingresso numero 0
	LD B,A		; copia A in B

In pratica vengono azzerati (spenti) i led di uscita, viene letto un nuovo stato degli interruttori dalla porta di ingresso e questo stato viene copiato in B

Ciclo di controllo

Abbiamo poi una serie di istruzioni ripetute ciclicamente all'infinito che controllano se è cambiato lo stato di uno dei micro interruttori:

ciclo:
	IN A,(0)	; legge in A dalla porta di ingresso numero 0
	CP B		; confronta A con B (A-B)
	JP NZ,cambio	; se il risultato dell'operazione è 0, salta a cambio
	JP ciclo	; salto incondizionato all'etichetta ciclo

Si osservi anzitutto come viene realizzato il ciclo. In assembly non esistono istruzioni specifiche per fare cicli (come le istruzioni while o for dei linguaggi di programmazione ad alto livello). Per fare un ciclo si usa un'etichetta (nel nostro caso ciclo) e un'istruzione di salto che permette di tornare all'inizio del ciclo stesso (nel nostro caso JP ciclo).

Nel ciclo viene anzitutto acquisito di nuovo lo stato dei microinterruttori con IN A,(0). Quindi tale stato viene confrontato con quello precedentemente salvato in B con l'istruzione CP B. A proposito di questa istruzione, essa effettua la sottrazione A-B senza salvare il risultato. Si noti che il primo operando (A) è sottinteso, come accade spesso nelle istruzioni dello Z80. In pratica questa istruzione serve solo per settare i bit del flag register e dunque per permettere il funzionamento della successiva istruzione JP NZ, cambio.

L'istruzione JP NZ, cambio è un'istruzione di salto condizionato: il salto viene cioè effettuato se il risultato dell'ultima operazione aritmetico-logica eseguita (nel nostro caso CP B) è diverso da zero (NZ). In pratica il salto viene fatto se il valore letto in A risulta diverso dal valore precedentemente salvato in B (cioè se c'è stato il cambiamento di qualche micro interruttore).

In caso contrario il programma torna a ciclo con JP ciclo.

Visualizzazione del cambiamento di stato

Le istruzioni che si occupano di visualizzare sui led il cambiamento di stato dei micro interruttori sono le seguenti:

cambio:
	LD C,A		; copia A in C
	XOR B		; or esclusivo bit a bit di A con B
	OUT (0),A	; visualizza A sulla porta di uscita numero 0
	LD B,C		; copia C in B
	JP ciclo	; salto incondizionato all'etichetta ciclo

L'istruzione centrale qui è XOR B, la quale effettua un or esclusivo bit a bit fra il contenuto di A (stato attuale dei micro interruttori) e quello di B (stato precedentemente salvato). Siccome l'operazione di or esclusivo fornisce come risultato 1 solo quando i bit confrontati hanno valori diversi, il risultato di XOR B (si noti come anche in questo caso l'operando A sia sottinteso) mette in A il valore 1 solo in corrispondenza dei bit che sono stati modificati.

A questo punto l'istruzione OUT (0),A si occupa di visualizzare il cambiamento sui led di uscita. Le istruzioni LD C,A e LD B,C servono semplicemente per salvare e poi ripristinare il contenuto di A. Infatti A viene modificato da XOR B e dunque va ripristinato, salvandolo temporaneamente in un altro registro. Questa situazione è tipica: poiché l'accumulatore A è usato in quasi tutte le istruzioni, i valori in esso contenuti vengono modificati continuamente. Se dunque A contiene un valore da conservare, esso deve essere preventivamente copiato in un altro registro.

Codice macchina e programma caricato in memoria

Il programma assemblato e caricato in memoria è il seguente (tutti i valori sono in esadecimale):

Indirizzo Contenuto Assembly
0000 C3 JP main
0001 00 lower byte target address
0002 01 upper byte target address
... ... ...
0100 3E LD A,0    ; main
0101 00 operand
0102 D3 OUT (0),A
0103 00 operand
0104 DB IN A,(0)
0105 00 operand
0106 47 LD B,A
0107 DB IN A,(0)  ; ciclo
0108 00 operand
0109 B8 CP B
010A C2 JP NZ,cambio
010B 10 lower byte target address
010C 01 upper byte target address
010D C3 JP ciclo
010E 07 lower byte target address
010F 01 upper byte target address
0110 4F LD C,A   ; cambio
0111 A8 XOR B
0112 D3 OUT (0),A
0113 00 operand
0114 41 LD B,C
0115 C3 JP ciclo
0116 07 lower byte target address
0117 01 upper byte target address

Si noti come alcune istruzioni (es. LD B,C) non hanno operando e dunque occupano una sola parola di memoria. Altre istruzioni hanno un operando a 8 bit e dunque occupano due parole di memoria (es. LD A,0). Le istruzioni di salto (JP) infine hanno come operando un indirizzo a 16 bit e dunque occupano tre locazioni di memoria (una per il codice operativo e due per l'indirizzo). Si noti inoltre che nello Z80 negli indirizzi i byte alti e bassi sono invertiti di ordine.

 

precedente - successiva

Sito realizzato in base al template offerto da

http://www.graphixmania.it