>ADD, ADC e INC
La prima operazione matematica che si impara alle elementari è senza dubbio la
somma ed anche io comincio con quella.
Le istruzioni che eseguono la somma sono tre :
ADD < registro|memoria >,< registro|memoria|valore > ADC < registro|memoria >,< registro|memoria|valore > INC < registro|memoria >NOTA: dato che i trasferimenti diretti memoria-memoria non sono possibili i due operandi non possono essere entrambi locazioni di memoria.
Perchè 3 istruzioni ?
ADD op1,op2 effettua la somma tra op1 e op2 e mette il risultato in op1
ADC op1,op2 effettua la somma tra op1 e op2, mette il risultato in op1 e se c'è
riporto somma 1 al risultato
INC op incrementa di 1 op; il numero è considerato senza segno quindi non
viene modificato il valore del CF in caso di riporto.
Queste operazioni effettuano una somma a prescindere dal fatto che si stia
lavorando con numeri con segno o senza segno, sta al programmatore interpretare
il valore della somma.
Sta anche al programmatore il compito di controllare il risultato in caso di
OVERFLOW (quando il valore della somma non sta nei registri) analizzando il
valore del bit di overflow nel Flag Register.
Vediamo alcuni esempi
.DATA dato DB 39 ;1 byte .CODE ... ... mov al,26 ;al=26 inc al ;al=27 add al,76 ;al=103 add al,dato ;al=142 oppure al=-114 (se con segno!!) mov ah,al ;ah=142, al=142 add al,ah ;al=28 con CF=1 ... ...Tramite l'istruzione ADC è possibile effettuare somme che non stanno in un unico registro:
.DATA dato32 DD 316423 .CODE ... ... mov ax,43981 ;ax=43981 sub dx,dx ;dx=0 add ax,WORD PTR dato32[0] ;somma ax ai 2 byte meno ; significativi di dato32 adc dx,WORD PTR dato32[2] ;somma dx ai 2 byte più ; significativi di dato32 ; tenendo conto del riporto ... ...Questo programma effettua la somma 316423+43981
>SUB, SBB, DEC e NEG
Dopo l'addizione non poteva mancare la sottrazione!
La sintassi per queste operazioni è la seguente:
SUB < registro|memoria >,< registro|memoria|valore > SBB < registro|memoria >,< registro|memoria|valore > DEC < registro|memoria > NEG < registro|memoria >Cominciamo dalla SUB che funziona esattamente come la ADD: sottrae dal primo operando il secondo e mette il risultato nel primo. Valgono le stesse osservazioni fatte per la somma quindi se non ve le ricordate andate a rileggerle.
.DATA dato DB 122 .CODE ... ... mov al,95 ;al=95 dec al ;al=94 sub al,23 ;al=71 sub al,dato ;al=-51 se con segno oppure ; al=205 senza segno mov ah,119 sub al,ah ;al=86 con OF=1Quando il risultato va sotto lo zero viene settato il SF (sign flag).
Esempio:
.DATA datoA DD 316423 datoB DD 156739 .CODE ... ... mov ax,WORD PTR datoA[0] mov dx,WORD PTR datoA[2] ;ora ho il primo numero in DX:AX sub ax,WORD PTR datoB[0] sbb dx,WORD PTR datoB[2] ;ho il risultato in DX:AX ... ...L'ultima istruzione che rientra nella categoria delle sottrazioni è la NEG che cambia il segno dell'operando e che quindi deve essere usata solo per i numeri con segno.
mov ax,143 ;ax=143 --> 8Fh neg ax ;ax=-143 --> FF71hNOTA: Vi ricordo che i numeri negativi sono rappresentati in complemento a 2.
>MUL e IMUL
La terza operazione che vediamo è la moltiplicazione, senza segno (MUL) e con
segno (IMUL).
La loro sintassi è la seguente:
MUL < registro|memoria > IMUL < registro|memoria >Vi chiederete dove sta il secondo fattore. Bene l'operando specificato nella MUL (o nella IMUL) verrà moltiplicato per il numero che è contenuto nell'accumulatore (AX per i 16bit, AL per gli 8bit o EAX per i 32bit).
1byte * AL --> risultato in AX (CF=0 e OF=0 se e solo se AH=0) 2byte * AX --> risultato in DX:AX (CF=0 e OF=0 se e solo se DX=0) 4byte * EAX -> risultato in EDX:EAX (CF=0 e OF=0 se e solo se EDX=0)Anche qui vediamo alcuni esempi:
.DATA dato DW -30000 .CODE ... ... mov al,23 ;al=23 mov bl,24 ;bl=24 mul bl ;ax=552 (CF=1 e OF=1) mov ax,50 imul dato ;DX:AX=-1500000 (CF=1 e OF=1)Da questo esempio si capisce anche come funziona la IMUL.
Per processori 80186 e superiori la IMUL prevede anche le seguenti sintassi:
IMUL < registro >,< valore > IMUL < registro >,< memoria >,< valore >In questo caso il risultato viene messo nel registro specificato e nel caso non ci stia viene settato CF e OF.
imul dx,455 ;moltiplica dx*455 imul ax,[bx],6 ;moltiplica il valore puntato da bx*6 e ; mette il risultato in ax>DIV e IDIV
DIV < registro|memoria > IDIV < registro|memoria >Per effettuare una divisione di un numero a 16bit per uno di 8bit devo mettere il numero da dividere in AX e specificare il divisore (cioè l'altro numero) in un altro registro. Il risultato della divisione sarà in AL e il resto in AH ; quindi fate attenzione il dividendo viene perso.
.DATA data16 DW -2000 data32 DD 500000 .CODE ... ... mov ax,700 ;ax=700 mov bl,36 ;bl=36 div bl ;al=19 (quoziente), ah=16 (resto) mov ax,WORD PTR dato32[0] mov dx,WORD PTR dato32[2] ;carico il dividendo in DX:AX idiv dato16 ;500000/-2000 ;AX=-250 , DX=0 mov ax,WORD PTR dato16 cwd ;lo estendo a 32bit in DX:AX mov bx,-421 idiv bx ;ax=4 , dx=-316Ora che abbiamo visto le 4 operazioni fondamentali analizzeremo alcune istruzioni che lavorano con i numeri binari in notazione BCD.
>AAA (Adjust after an Addition)
Per capire cosa fa vediamo un esempio:
mov ax,9 ;ax=9 mov bx,3 ;bx=3 add al,bl ;al=C aaa ;al=2 ah=1 CF=1Come si vede dall'esempio il risulato (in "unpacked" BCD) l'ho in ax: in ah ci sono le decine e in al le unità. Notate che setta anche il Carry a 1 (questo indica che il risultato in decimale non sta in una cifra, ma è composto da 2 cifre).
>AAS (Adjust After a Subtraction)
mov ax,103h ;ax=13h (in BCD : ah=1 al=3 !!!) mov bx,4 ;bx=4 sub al,bl ;al=FFh (-1) aas ;al=9 ah=0 CF=1Dopo la prima istruzione mov, ax è ovviamente uguale a 103h; tuttavia un'altra interpretazione è: contiene la versione (non compattata) del valore BCD 13.
>AAM (Adjust After a Multiplication)
mov ax,903h mul ah ;moltiplica ah*al = 1Bh aam ;ah=2 al=7;Attenzione : questa istruzione si può usare solo per le moltiplicazioni senza segno !!!
>AAD (Adjust BEFORE a division)
A differenza delle altre 3 questa va usata prima di una divisione infatti
trasforma il numero in BCD in codice binario prima dell'operazione.
Dopo la divisione il risultato va risistemato tramite un AAM.
Vediamo ad esempio (25/2):
mov ax,205h ;carico il dividendo (25) mov bl,2 ;carico il divisore (2) aad ;trasforma il 25 in BCD in 19h binario (ax=19h) div bl ;quoziente in al=0Ch resto in ah=1 aam ;sistema al in ax=102h (12 in BCD)Notate che il resto viene perso: se vi serve ricordatevi di salvarlo prima dell'istruzione AAM.
Abbiamo visto come si lavora con numeri a 2 cifre ma se devo usare numeri più
grossi?
Semplice devo iterare il metodo per ogni cifra del numero !!
Esistono poi altre due istruzioni per lavorare con un altro tipo di numeri BCD
cosiddetti "packed" in cui ogni cifra occupa solo 4 bit.
A differenza delle altre non cambiano il valore di ah ma lavorano sul registro
di flag ogni volta che c'è un riporto.
>DAA (Adjust After an Addition)
mov ax,8833h ;carica 88 e 33 in un unico registro add al,ah ;0BBh daa ;CF=1 e AL=21>DAS (Adjust After an Subtraction)
mov ax,3883h ;carica 38 e 83 in BCD sub al,ah ;04Bh das ;CF=0 AL=45Vediamo ora le istruzioni che il processore ci mette a disposizione per effettuare operazioni logiche.
>AND < registro|memoria >,< registro|memoria|valore >
Effettua un AND bit a bit degli operandi.
L'AND può essere utile per azzerare alcuni bit di un registro tramite una
"maschera" in cui i bit da azzerare sono 0 e gli altri sono 1:
mov ax,035h ;00110101 mov bx,0FBh ;11111011 and ax,bx ;00110001 ho azzerato il secondo bit !!I bit di solito vengono convenzionalmente contati a partire da destra e da 0.
>OR < registro|memoria >,< registro|memoria|valore >
Effettua l'OR bit a bit.
Può essere utile per settare solo alcuni bit di un registro con un'opportuna
"maschera" di bit.
>XOR < registro|memoria >,< registro|memoria|valore >
Effettua l'OR esclusivo bit a bit.
E' molto usata per azzerare il valore di un registro facendo XOR con se stesso:
è molto veloce!!
>NOT < registro|memoria >
Effettua il NOT logico sui bit dell'operando.
Vediamo infine alcune istruzioni non prettamente matematiche ma che vengono spesso utilizzate per questo scopo.
>SHL e SHR
Queste due istruzioni shiftano a sinistra e destra (risp.) l'argomento.
Innanzi tutto la sintassi è la seguente:
SHL < registro|memoria >,< CL|1 > SHR < registro|memoria >,< CL|1 >Vediamo cosa vuol dire con un esempio:
mov al,01001011 ;al=01001011 shl al,1 ;al=10010110 CF=0In pratica è successo che tutti i bit sono stati spostati di una posizione verso sx, il bit più significativo è andato nel CF e quello meno significativo è stato messo a zero.
>ROR e ROL
Queste servono per far ruotare i bit a destra e sinistra (risp.)
La loro sintassi è uguale a shl e shr (non sto a riscriverla!).
Vediamo subito un esempio:
mov al,01001011 ;al=01001011 ror al,1 ;al=10100101 mov cl,3 rol al,cl ;al=00101101Bene anche questa puntata è finita. Ora dovreste avere i mezzi per scrivere qualche semplice routine matematica.
Assembly Page di Antonio |
|