Assembly III

[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:

adc dl,30h

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,02
h
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].

torna a modulo II  
 
 

Assembly modulo III operazioni con bit e byte.