|
[La logica di presentazione degli argomenti
di questo modulo si ispira a Linguaggio Assembly per pc IBM
di Peter Norton]
Istruzione adc
Abbiamo gia' incontrato l'istruzione assembly
add che si occupa di addizionare un registro ad un altro [ad esempio;
add ax, bx somma il contenuto del registro bx al contenuto del
registro ax].
Ogni processore della famiglia x86 e superiori possiede delle
spacili locazioni per singoli bit detti flag.
Se riapriamo debug e digitiamo il comado r, nella seconda riga
troveremo: OF DF IF TF SF ZF AF PF CF.
In realta' non proprio queste coppie di lettere [la F sta per
flag]; ma procediamo con ordine
OF Overflow Flag
DF Direction Flag
IF Interrupt Flag
TF Trap Flag
SF Sign Flag
ZF Zero Flag
AF Auxiliary Flag
PF Parity Flag
CF Carry Flag
Ogni flag ha una funzione. Per il momento
prendiamo in considerazione il CF. Quando il risultato di un'operazione
aritmetica eccede i primi 7 bit [partendo da destra] di un byte
di un registro destinazione, come ad esempio nel caso dell'addizione
di numeri binari 10000000 + 10000001, il CF segnala il riporto.
Il risultato della addizione precedente e' 00000001 e non 100000001
come invece dovrebbe essere. Ma l'1 non va perso, o meglio il
riporto e' segnalato dal CF che viene impostato. Quando CF viene
impostato esso prende la forma di CY. Se non impostato prende
il valore di NC. Per questo motivo, quando digitiamo il comando
r di debug troviamo lettere diverse da quelle sopra scritte, tipo:
| NV |
OV |
| UP |
|
| EI |
|
| PL |
NG |
| NZ |
ZR |
| NA |
|
| PO |
|
| NC
|
CY |
L'istruzione add
somma semplicemente due numeri, ma l'istruzione assembly adc [add
with carry] in realta' somma tre numeri: i due registri piu' il
bit del flag di riporto.
Diciamo che in seguito ad un'operazione vogliamo conoscere lo
stato del flag CF. Esiste piu' di un metodo ma nessuno permette
di andare a guardare direttamente dentro CF. Uno di questi e'
quello di utilizzare l'istruzione adc. Se prendiamo la tabella
ascii Codici
dei caratteri ascii possiamo osservare che 30h e' il codice
esadecimale per il carattere ascii 0, mentre 31h e' il codice
esadecimale per il carattere ascii 1. Questo significa che ad
esempio:
potra' dare due risultati
per DL:
31h o 30h a seconda che CF sia impostato o meno. Una volta stampati
i numeri decimali daranno 1 o 0 e questo mostrera' il valore di
CF.
Se compilate il seguente programma con debug il risultato sara'
1 [la b vicino ai numeri binari indica appunto binario; il punto
e virgola [;] dopo un'istruzione consente di scrivere un commento
(precauzione fondamentale in assembly) che non verra' considerato
dal compilatore in fase di assemblaggio].
|
mov al,80h
mov bl,81h
mov ah,02h
add al,bl
adc dl,30h
int 21
int 20
|
;
10000000b
;
10000001b
; impostazione di ah per int21
; somma di due numeri che restituiscono un riporto
;
somma del registro DL con 30h e CF
|
Si noti come il registro DL composto, come
gli altri registri, da 16 bit [parola] possa essere scomposto
in due byte [da 8 bit] e utilizzato per funzioni diverse contemporaneamente.
Istruzioni rcl - loop
L'istruzione
rcl significa Rotate Carry Left, ovvero ruotazione a sinistra
del riporto.
Useremo questa istruzione per stampare un numero in formato binario.
L'istruzione loop e' un'operazione di iterazione: essa permette
di ripetere un ciclo di istruzioni per un tot di volte segnalato
dal registro CX [registro d'uso generale ma anche contatore].
Possiamo
unire in questo modo le due operazioni
|
mov bx,1111
mov cx,0008
rcl bx,1
loop etichetta
int 20
|
;
muovi un
numero nel registro BX
;
carica
il registro contatore per un iterazione di 8 volte
; ruota con rcl il registro BX e sottrai 1 a CX
; torna a etichetta, ovvero ad un nome messo davanti all'istruzione
rcl |
Ecco come funziona questo programma: il
binario di c231h e' 1100001000110001b. Rcl sposta un bit per volta
a sinistra inserendolo dentro a CF e alla destra del numero inserisce
0. Ogni volta che il programma ripassa per etichetta [istruzione
rcl, CX si decrementa di uno]. Dopo 8 volte [CX=0] il numero esadecimale
c231h si e' trasformato in 3100h, ovvero in 0011000100000000.
Proviamolo [al posto di etichetta inseriremo il secondo numero
a 4 cifre [dopo i due punti] posto davati all'istruzione rcl:
|
mov
ah,02h
mov bx,c231
mov cx,0008
rcl bx,1
loop etichetta
mov dl,bh
int 21
int 20
|
; muovi
un numero nel registro BX
;
carica
il registro contatore per un iterazione di 8 volte
; ruota con rcl il registro BX un bit per volta
; torna a etichetta, ovvero ad un nome messo davanti all'istruzione
rcl
; muovi bh in dl per stamparlo |
Quello che vedremo stampato sul monitor
e' un 1 perche' inserendo in DL il registro BH abbiamo inserito
31h che, come abbiamo visto, e'
il codice esadecimale per il carattere ascii 1.
Procedendo oltre giungendo a stampare le cifre binarie che compongono
un numero esadecimale:
|
mov
ah,02h
mov bl,31
mov cx,0008
rcl bl,1
adc dl,30
int 21
mov dl, 00
loop etichetta
int 20
|
; muovi
un numero nel registro BL
;
carica
il registro contatore per un iterazione di 8 volte
; ruota con rcl il registro BL un bit per volta
; addiziona al registro DL il numero 30h e CF
; stampa l'uno o lo zero
; ripulisci il registro DL per renderlo disponibile ad una
nuova iterazione
; torna a etichetta, ovvero ad un nome messo davanti all'istruzione
rcl |
Il risultato di questo programma e' 00110001,
ovvero 31h binario [in seguito vedremo dei metodi piu' eleganti
di ripulire un registro].
|