ELEMANIA
Z80 - Istruzioni di caricamento
Istruzioni di caricamento

Le istruzioni di caricamento (in inglese load) sono probabilmente quelle più frequentemente usate nei programmi, poiché permettono di trasferire dati fra i registri interni del µP e fra il µP e la memoria esterna.

In assembly Z80 la sintassi generale di un'istruzione di caricamento è

LD destinazione, sorgente

dove destinazione e sorgente possono, a seconda dei casi, essere registri o locazioni di memoria, secondo i diversi modi di indirizzamento visti. Si presti attenzione all'ordine in cui vengono specificati: prima la destinazione e poi la sorgente del trasferimento.

L'istruzione LD non corrisponde a un'unico codice operativo nel linguaggio macchina dello Z80, poiché si tratta in realtà di tante istruzioni diverse, una per ogni possibile caso e combinazione di destinazione e origine.

LD fra registri interni dello Z80

Il caso più semplce è quello di una LD per trasferire il contenuto di un registro interno in un altro registro. Abbiamo dunque per esempio

LD B,C

che trasferisce il contenuto di C in B (l'istruzione ha codice operativo 47h e occupa dunque un singolo byte in memoria).

LD di un valore a 8 bit in un registro interno

In questo gruppo di istruzioni la destinazione è un registro, mentre la sorgente è un valore numerico costante a 8 bit (un byte). Per esempio

LD B,10

carica in B il valore 10. Il codice operativo in questo caso è 06h e deve essere seguito dal valore dell'operando (0Ah), per cui l'istruzione completa occupa 2 byte (060Ah).

LD fra registro accumulatore e memoria esterna

Si tratta in realtà di due istruzioni

LD A,(nn)
LD (nn),A

che consentono di trasferire il contenuto dell'indirizzo di memoria nn nell'accumulatore A o viceversa. Si notino le parentesi tonde che, nella convenzione utilizzata nell'assembly Z80, stanno a indicare il fatto che nn rappresenta un indirizzo (cioè un valore "puntato" e non una costante, cioè rappresenta il puntatore a una locazione di memoria che contiene il valore da trasferire).

Un esempio di questo tipo di istruzione è

LD A,(812Ah)

che carica in A il contenuto dell'indirizzo di memoria 812Ah. L'istruzione occupa 3 byte: il primo è destinato al codice operativo (3A) e gli altri due all'indirizzo. Come abbiamo già osservato i byte di indirizzo vengono forniti nell'ordine "inverso", cioè prima il byte meno significativo e poi quello più significativo:

3A 2A 81

LD di indirizzo in coppie di registri

I registri interni general purpose (A,B,C,D,E,H e L) dello Z80 sono tutti a 8 bit, mentre gli indirizzi in memoria occupano 16 bit. Non è dunque possibile memorizzare un indirizzo in un registro. A tale scopo lo Z80 utilizza coppie di registri a 8 bit. Le coppie possibili sono BC, DE e HL. Per esempio

LD BC,0584h

memorizza il valore a 16 bit 0584h nella coppia di registri B+C (il byte più significativo 05 viene memorizzato in B e il byte meno significativo 84 in C). Il codice operativo di questa istruzione è 01 e il codice binario completo a tre bit è

01 84 05

con la solita inversione nell'ordine dei due byte di operando.

 

LD fra coppie di registri e memoria esterna

Esistono anche alcune utili istruzioni che consentono di trasferire verso la memoria una coppia di registri (BC, DE, HL) come nell'esempio che segue:

            LD (8000h),BC       ; scrive il contenuto di BC nell'indirizzo 8000h
            LD BC,(8000h)       ; legge il contenuto di 8000h in BC

Si osservino le parentesi che stanno a indicare che il numero è un indirizzo in memoria. Vale la pena a questo proposito di osservare con attenzione il seguente spezzone di programma:

            LD BC, 3F04h         ; scrive il valore 3F04h in BC
            LD (8000h),BC       ; scrive il contenuto di BC nell'indirizzo 8000h

Eseguendo questa coppia di istruzioni il valore a 16 bit 3F04 viene salvato in memoria all'indirizzo 8000h: più esattamente il valore 04 (byte meno significativo) viene scritto all'indirizzo 8000h, mentre il valore 3F (byte più significativo) viene scritto all'indirizzo 8001h.

 

LD con coppie di registri usati come puntatori in memoria

Le coppie di registri BC, DE e HL sono molto usate come puntatori in memoria. In pratica si carica nella coppia un indirizzo, il quale viene poi usato per un'altra istruzione LD.

Si consideri per esempio la seguente coppia di istruzioni

LD HL,8000h
LD (HL),0

La prima istruzione carica il valore 8000h (16 bit) nella coppia di registri HL. La seconda istruzione scrive il valore zero (8 bit) nella locazione di memoria puntata da HL (cioè all'indirizzo 8000h).

La coppia di registri HL è maggiormente utilizzata rispetto a BC e DE poiché queste ultime possono essere usate solo con l'accumulatore A (mentre HL può essere usata con qualsiasi registro). In altre parole, il linguaggio macchina dello Z80 comprende tutte le istruzioni

LD A,(HL)
LD B,(HL)
LD C,(HL)
eccetera

mentre ha soltanto

LD A,(BC)
LD A,(DE)

Per esempio non esiste un'istruzione del tipo LD E,(BC)

Vediamo ora un programma esemplificativo che serve per testare l'area di memoria di 8000h locazioni comprese fra gli indirizzi 8000h e FFFFh per individuare eventuali parole di memoria non correttamente funzionanti.

La tecnica consiste nello scrivere in ogni parola di memoria il valore 00h (8 bit a zero) e poi rileggerlo e quindi scrivere il valore FFh esadecimale (8 bit a uno) e poi rileggerlo. Se i valori scritti e quelli successivamente letti sono uguali, vuol dire che la parola di memoria funziona correttamente, altrimenti significa che c'è un errore.

    LD HL,0FFFFh 	; inizializza HL con FFFFh (fine area di memoria)
	LD D, 0		; azzera il contatore degli errori
inizio:
	LD (HL),0 	; azzera la locazione puntata da HL 
	LD A, (HL)	; legge la locazione puntata da HL 
	CP 0		; confronta il valore letto con zero
	JP NZ,errore	; se sono diversi salta a errore
       	LD (HL),0FFh 	; carica F nella locazione puntata da HL 
	LD A, (HL)	; legge la locazione puntata da HL 
	CP 0FFh		; confronta il valore letto con FF
	JP NZ,errore	; se sono diversi salta a errore
decr:
	DEC HL		; decrementa HL
		    	; Le istruzioni seguenti servono per testare se HL vale 7FFFh
	LD A,H		; copia H in A
	CP 7Fh		; testa se A vale 7Fh
	JP NZ, inizio	; se è diverso ricomincia da inizio

fine:
	LD A,D		; carica 0 in A
	OUT (0),A	; visualizza il numero di errori (se 0, allora tutto ok)
	HALT

errore:
	INC D		; incrementa il contatore degli errori
	JP decr     ; torna a decr

Si osservi in particolare che:

Una possibile traduzione in linguaggio C del ciclo precedente è questa:

i=FINE;
err=0;
while (i!=INIZIO)
{
mem [i]=0;
if (mem [i]!=0)
err++;
mem [i]=0xFF;
if (meme[i]!=0xFF) err++;
i--;
}

 

LD con registri indice

Oltre alle coppie di registri BD, DE e HL di cui abbiamo parlato prima, lo Z80 possiede due registri a 16 bit, IX e IY detti registri indice. Lo scopo di tali registri è appunto quello di indicizzare (cioè di indirizzare) locazioni di memoria.

Si consideri a titolo di esempio lo seguente spezzone di programma:

        LD IX,0400h     ;inizializza IX col valore 0400h
        LD (IX),A         ; copia il contenuto di A nella locazione indicizzata da IX
        INC IX             ; incrementa IX

Le istruzioni che coinvolgono i registri indice hanno tutte un codice operativo a 2 byte (per esempio LD IX,nn ha codice operativo DD21h) e dunque sono più lente da caricare rispetto alle istruzioni standard da un solo byte.

In alcune istruzioni che coinvolgono i registri indice è possibile anche indicare un offset, cioè un valore costante a 8 bit che deve essere sommato al contenuto del registro. Per esempio

LD (IX+12),A

L'istruzione LD (IX),A è equivalente a LD (IX+0),A. Si tratta di due diversi mnemonici assembly che indicano la stessa operazione (in entrambi i casi è presente un operando di valore zero, anche se non esplicitamente dichiarato).

 

precedente - successiva

Sito realizzato in base al template offerto da

http://www.graphixmania.it