19.1 L'istruzione AND
Con il mnemonico AND si indica l'istruzione Logical AND (AND logico); lo scopo di questa istruzione è quello di effettuare un AND logico tra i contenuti dei due operandi, SRC e DEST, specificati esplicitamente dal programmatore.A AND Be risulta vera se, e solo se, entrambe le proposizioni sono vere.
A = La capitale della Francia è Parigie:
B = La capitale dell'Italia è BerlinoIn questo caso otteniamo:
A AND B = 0Infatti, la proposizione A è vera, mentre la proposizione B è falsa; in sostanza, alla precedente relazione dobbiamo attribuire il significato di:
A e BIn base alle considerazioni appena esposte, possiamo ricavare la tabella della verità (truth table) relativa all'operatore AND logico; nella parte sinistra della Figura 19.1 viene mostrato anche il simbolo logico di questo operatore. Come esempio pratico, poniamo BX=1000111010100110b, CX=0110100111110010b ed eseguiamo la seguente istruzione:
and bx, cxIn presenza di questa istruzione, la CPU ottiene il seguente risultato: Per pervenire a questo risultato, la CPU esegue le seguenti elaborazioni (a partire dai bit meno significativi dei due operandi):
0 AND 0 = 0 (AND tra i bit in posizione 0)
1 AND 1 = 1 (AND tra i bit in posizione 1)
1 AND 0 = 0 (AND tra i bit in posizione 2)e così via.
19.1.1 Istruzione AND con maschere di bit
L'istruzione AND può essere utilizzata per portare a livello logico 0 determinati bit di un numero binario; osserviamo, infatti, che indipendentemente dal valore (0 o 1) di una proposizione logica A, risulta:A AND 0 = 0e
A AND 1 = AIn sostanza, un AND tra A e 0 produce, in ogni caso, A=0; invece, un AND tra A e 1 lascia inalterato il valore logico (0 o 1) di A.
BITMASK_AND = 0111011101111101bCome si può notare, gli unici bit di BITMASK_AND che valgono 0, sono proprio quelli in posizione 1, 7, 11 e 15; a questo punto, possiamo scrivere l'istruzione:
and ax, BITMASK_ANDIn presenza di questa istruzione, la CPU ottiene il seguente risultato: Come possiamo notare, i bit di AX in posizione 1, 7, 11 e 15 sono stati portati a 0, mentre tutti gli altri sono rimasti inalterati; una costante simbolica come BITMASK_AND, viene definita bit mask (maschera di bit).
19.1.2 AND logico tra operandi di ampiezza arbitraria
L'istruzione AND opera bit per bit, per cui può essere applicata con estrema semplicità, anche ad operandi di ampiezza arbitraria; in sostanza, non dobbiamo fare altro che suddividere ciascun operando, in tante parti direttamente gestibili dalla CPU.Num3 = Num1 AND Num2non dobbiamo fare altro che tradurre in Assembly le seguenti pseudo-istruzioni:
Num3[0] = Num1[0] AND Num2[0] = 3CF218A6h AND 48FB1DC9h = 08F21880h
Num3[4] = Num1[4] AND Num2[4] = 2B96CDEAh AND 66D41695h = 22940480h
Num3[8] = Num1[8] AND Num2[8] = 6F9C482Dh AND 3C9DF1AFh = 2C9C402Dh
Num3[12] = Num1[12] AND Num2[12] = 881E63CAh AND 7BB3F28Dh = 08126288hOvviamente, questo procedimento non è applicabile ai numeri BCD i quali codificano simbolicamente numeri in base 10 (e ciò vale per tutte le altre istruzioni logiche illustrate in questo capitolo); nella eventualità di dover effettuare un AND logico tra due numeri BCD, dobbiamo prima convertire tali numeri nella loro rappresentazione in base 10.
16h AND 00001111b = 00010110b AND 00001111b = 00000110b = 6h = 6dmentre:
16d AND 00001111b = 00010000b AND 00001111b = 00000000b = 0h = 0d
19.1.3 Effetti provocati da AND sugli operandi e sui flags
L'esecuzione dell'istruzione AND tra SRC e DEST, modifica il contenuto del solo operando DEST che viene sovrascritto dal risultato prodotto dall'istruzione stessa; il contenuto dell'operando SRC rimane inalterato.and si, [si]Dopo l'esecuzione di questa istruzione, la componente Offset contenuta in SI, viene sovrascritta dal risultato prodotto da AND!
and dx, dxCome si può facilmente constatare, l'esecuzione di una tale istruzione non provoca alcuna modifica del contenuto di DX; infatti:
0 AND 0 = 0e
1 AND 1 = 1Sfruttando questo aspetto, possiamo utilizzare AND per sapere se il contenuto di un registro vale zero; supponiamo, ad esempio, di avere DX=0111001101001101b. Eseguendo ora l'istruzione:
and dx, dxotteniamo: In sostanza, il risultato della precedente istruzione è zero se, e solo se, tutti i bit di DX valgono 0; se almeno un bit di DX vale 1, il risultato della precedente istruzione è diverso da zero. Come viene spiegato più avanti, per sapere se abbiamo ottenuto un risultato nullo ci basta consultare ZF; è importante anche ribadire che la precedente istruzione non altera il contenuto di DX!
19.2 L'istruzione TEST
Con il mnemonico TEST si indica l'istruzione Logical Compare (comparazione logica mediante AND); lo scopo di questa istruzione è quello di effettuare una comparazione di tipo AND logico, tra i contenuti dei due operandi, SRC e DEST, specificati esplicitamente dal programmatore.19.2.1 Istruzione TEST con maschere di bit
Come è stato appena spiegato, l'istruzione TEST è stata concepita per permettere di "testare" lo stato di determinati bit dell'operando DEST, senza alterarne il contenuto; vediamo alcuni esempi pratici.test bh, 00001000bCome si può notare, solo il bit in posizione 3 della maschera di bit, vale 1; in base a quanto è stato esposto per l'istruzione AND, possiamo affermare che la precedente istruzione produce un risultato diverso da zero se, e solo se, il bit in posizione 3 di BH vale 1. Se, e solo se, il bit in posizione 3 di BH vale 0, otteniamo un risultato nullo; come viene chiarito più avanti, per conoscere il risultato prodotto dalla precedente istruzione, possiamo servirci del flag ZF.
test al, 10000000bo, in modo equivalente:
test al, 80hQuesta istruzione fornisce un risultato nullo se, e solo se, il bit più significativo di AL vale 0 (numero positivo); se, e solo se, il bit più significativo di AL vale 1 (numero negativo), otteniamo un risultato diverso da zero.
19.2.2 TEST tra operandi di ampiezza arbitraria
L'istruzione TEST opera bit per bit, per cui può essere applicata con estrema semplicità, anche ad operandi di ampiezza arbitraria; in sostanza, non dobbiamo fare altro che suddividere ciascun operando in tante parti direttamente gestibili dalla CPU.test byte ptr BigNum1[11], 80h
19.2.3 Effetti provocati da TEST sugli operandi e sui flags
L'esecuzione dell'istruzione TEST tra SRC e DEST, preserva il contenuto di entrambi gli operandi; infatti, il risultato del test viene scartato.test dx, dxIn questo caso, valgono tutte le considerazioni già esposte per l'istruzione AND.
19.3 L'istruzione NOT
Con il mnemonico NOT si indica l'istruzione One's Complement Negation (negazione in complemento a uno); lo scopo di questa istruzione è quello di invertire lo stato di tutti i bit dell'unico operando DEST, specificato esplicitamente dal programmatore.NOT Ae risulta vera se, e solo se, la proposizione è falsa.
A = La capitale della Francia è ParigiIn questo caso otteniamo:
NOT A = 0Infatti, stiamo negando una proposizione vera; stiamo affermando cioè, che la capitale della Francia NON è Parigi.
A = La capitale dell'Italia è BerlinoIn questo caso otteniamo:
NOT A = 1Infatti, stiamo negando una proposizione falsa; stiamo affermando cioè, che la capitale dell'Italia NON è Berlino.
negazione di AIn base alle considerazioni appena esposte, possiamo ricavare la tabella della verità (truth table) relativa all'operatore NOT logico; nella parte sinistra della Figura 19.2 viene mostrato anche il simbolo logico di questo operatore. Come esempio pratico, poniamo CX=1000111010100110b ed eseguiamo la seguente istruzione:
not cxIn presenza di questa istruzione, la CPU ottiene il seguente risultato: Per pervenire a questo risultato, la CPU esegue le seguenti elaborazioni (a partire dal bit meno significativo dell'operando):
NOT 0 = 1 (NOT del bit in posizione 0)
NOT 1 = 0 (NOT del bit in posizione 1)
NOT 1 = 0 (NOT del bit in posizione 2)e così via.
19.3.1 Complemento a 1 di un operando di ampiezza arbitraria
L'istruzione NOT opera bit per bit, per cui può essere applicata con estrema semplicità, anche ad operandi di ampiezza arbitraria; in sostanza, non dobbiamo fare altro che suddividere l'operando in tante parti direttamente gestibili dalla CPU.BigNum1 dd 3CF28615h, 8FB489DDh, 1C8DE4FFhSe vogliamo ottenere il complemento a uno di BigNum1, non dobbiamo fare altro che tradurre in Assembly le seguenti pseudo-istruzioni:
BigNum1[0] = NOT BigNum1[0] = NOT 3CF28615h = C30D79EAh
BigNum1[4] = NOT BigNum1[4] = NOT 8FB489DDh = 704B7622h
BigNum1[8] = NOT BigNum1[8] = NOT 1C8DE4FFh = E3721B00h
19.3.2 Complemento a 2 di un operando di ampiezza arbitraria
Supponiamo di aver definito un dato Num1 il cui contenuto rappresenta un numero intero con segno in complemento a 2; a questo punto, vogliamo cambiare di segno lo stesso contenuto di Num1.NEG(Num1) = NOT(Num1) + 1Come esempio pratico, supponiamo di operare sui numeri interi con segno a 64 bit; in tal caso, possiamo rappresentare tutti i numeri interi con segno compresi tra il limite minimo:
-(264 / 2)e il limite massimo:
+((264 / 2) - 1) = +(263 - 1)Come al solito, il bit di segno è quello più significativo (che in questo caso è il bit in posizione 63); tutti i numeri il cui bit più significativo vale 0 sono positivi, mentre tutti i numeri il cui bit più significativo vale 1 sono negativi.
264 - 3 = 18446744073709551616 - 3 = 18446744073709551613 = FFFFFFFFFFFFFFFDhNegando ora questo numero, dovremmo ottenere +3, cioè 0000000000000003h; in base a quanto è stato detto in precedenza, per negare un numero intero con segno a 64 bit, dobbiamo prima sottoporlo ad un NOT, sommando poi 1 al risultato ottenuto.
Num1 dq -3 ; FFFFFFFFFFFFFFFDhIl seguente codice effettua il cambiamento di segno di -3: Il risultato finale è proprio:
0000000000000003h = +3È importante ricordare che in questo caso, per incrementare di 1 il contenuto di Num1[0], non possiamo utilizzare INC; infatti, l'istruzione INC non modifica il flag CF di cui ha bisogno la successiva istruzione ADC!
19.3.3 Effetti provocati da NOT sugli operandi e sui flags
L'esecuzione dell'istruzione NOT modifica il contenuto del suo unico operando DEST; tale operando viene sovrascritto dal risultato prodotto dall'istruzione stessa.19.4 L'istruzione OR
Con il mnemonico OR si indica l'istruzione Logical Inclusive OR (OR logico inclusivo); lo scopo di questa istruzione è quello di effettuare un OR logico inclusivo tra i contenuti dei due operandi, SRC e DEST, specificati esplicitamente dal programmatore.A OR Be risulta vera se, e solo se, almeno una di esse è vera.
A = La capitale della Francia è Parigie:
B = La capitale dell'Italia è BerlinoIn questo caso otteniamo:
A OR B = 1Infatti, almeno una delle due proposizioni (la A) è vera; in sostanza, all'operatore OR dobbiamo attribuire il significato di:
A o B o entrambeIn base alle considerazioni appena esposte, possiamo ricavare la tabella della verità (truth table) relativa all'operatore OR logico inclusivo; nella parte sinistra della Figura 19.3 viene mostrato anche il simbolo logico di questo operatore. Come esempio pratico, poniamo BX=1000111010100110b, CX=0110100111110010b ed eseguiamo la seguente istruzione:
or bx, cxIn presenza di questa istruzione, la CPU ottiene il seguente risultato: Per pervenire a questo risultato, la CPU esegue le seguenti elaborazioni (a partire dai bit meno significativi dei due operandi):
0 OR 0 = 0 (OR tra i bit in posizione 0)
1 OR 1 = 1 (OR tra i bit in posizione 1)
1 OR 0 = 1 (OR tra i bit in posizione 2)e così via.
19.4.1 Istruzione OR con maschere di bit
L'istruzione OR può essere utilizzata per portare a livello logico 1, determinati bit di un numero binario; osserviamo, infatti, che indipendentemente dal valore (0 o 1) di una proposizione logica A, risulta:A OR 0 = Ae:
A OR 1 = 1In sostanza, un OR tra A e 0 lascia inalterato il contenuto di A; invece, un OR tra A e 1 produce, in ogni caso, A=1.
BITMASK_OR = 0000000100111000bCome si può notare, gli unici bit di BITMASK_OR che valgono 1 sono proprio quelli in posizione 3, 4, 5 e 8; a questo punto, possiamo scrivere l'istruzione:
or ax, BITMASK_ORIn presenza di questa istruzione, la CPU ottiene il seguente risultato: Come possiamo notare, i bit di AX in posizione 3, 4, 5 e 8 sono stati portati a 1, mentre tutti gli altri sono rimasti inalterati.
19.4.2 OR logico inclusivo tra operandi di ampiezza arbitraria
L'istruzione OR opera bit per bit, per cui può essere applicata con estrema semplicità, anche ad operandi di ampiezza arbitraria; in sostanza, non dobbiamo fare altro che suddividere ciascun operando, in tante parti direttamente gestibili dalla CPU.Num3 = Num1 OR Num2non dobbiamo fare altro che tradurre in Assembly le seguenti pseudo-istruzioni:
Num3[0] = Num1[0] OR Num2[0] = 3CF218A6h OR 48FB1DC9h = 7CFB1DEFh
Num3[4] = Num1[4] OR Num2[4] = 2B96CDEAh OR 66D41695h = 6FD6DFFFh
Num3[8] = Num1[8] OR Num2[8] = 6F9C482Dh OR 3C9DF1AFh = 7F9DF9AFh
Num3[12] = Num1[12] OR Num2[12] = 881E63CAh OR 7BB3F28Dh = FBBFF3CFh
19.4.3 Effetti provocati da OR sugli operandi e sui flags
L'esecuzione dell'istruzione OR tra SRC e DEST, modifica il contenuto del solo operando DEST che viene sovrascritto dal risultato prodotto dall'istruzione stessa; il contenuto dell'operando SRC rimane inalterato.or bx, cs:[bx+si+03h]Dopo l'esecuzione di questa istruzione, la componente Offset contenuta in BX viene sovrascritta dal risultato prodotto da OR!
or dx, dxCome si può facilmente constatare, l'esecuzione di una tale istruzione non provoca alcuna modifica del contenuto di DX; infatti:
0 OR 0 = 0e:
1 OR 1 = 1Sfruttando questo aspetto, possiamo utilizzare OR per sapere se il contenuto di un registro vale zero; in tal caso, si applicano tutte le considerazioni già svolte per l'istruzione AND.
19.5 L'istruzione XOR
Con il mnemonico XOR si indica l'istruzione Logical Exclusive OR (OR logico esclusivo); lo scopo di questa istruzione è quello di effettuare un OR logico esclusivo tra i contenuti dei due operandi, SRC e DEST, specificati esplicitamente dal programmatore.A XOR Be risulta vera se, e solo se, una di esse è vera e l'altra è falsa.
A = La capitale della Francia è Parigie:
B = La capitale dell'Italia è RomaIn questo caso otteniamo:
A XOR B = 0Infatti, entrambe le proposizioni sono vere; in sostanza, all'operatore XOR dobbiamo attribuire il significato di:
(A e NOT(B)) o (NOT(A) e B)In base alle considerazioni appena esposte, possiamo ricavare la tabella della verità (truth table) relativa all'operatore OR logico esclusivo; nella parte centrale della Figura 19.4 viene mostrato anche il simbolo logico di questo operatore, mentre nella parte sinistra vediamo una possibile realizzazione dello XOR attraverso porte AND, OR e NOT (la porta NOT viene rappresentata mediante un cerchietto). Come esempio pratico, poniamo BX=1000111010100110b, CX=0110100111110010b ed eseguiamo la seguente istruzione:
xor bx, cxIn presenza di questa istruzione, la CPU ottiene il seguente risultato: Per pervenire a questo risultato, la CPU esegue le seguenti elaborazioni (a partire dai bit meno significativi dei due operandi):
0 XOR 0 = 0 (XOR tra i bit in posizione 0)
1 XOR 1 = 0 (XOR tra i bit in posizione 1)
1 XOR 0 = 1 (XOR tra i bit in posizione 2)e così via.
19.5.1 OR logico esclusivo tra operandi di ampiezza arbitraria
L'istruzione XOR opera bit per bit, per cui può essere applicata con estrema semplicità, anche ad operandi di ampiezza arbitraria; in sostanza, non dobbiamo fare altro che suddividere ciascun operando, in tante parti direttamente gestibili dalla CPU.Num3 = Num1 XOR Num2non dobbiamo fare altro che tradurre in Assembly le seguenti pseudo-istruzioni:
Num3[0] = Num1[0] XOR Num2[0] = 2B96CDEAh XOR 66D41695h = 4D42DB7Fh
Num3[4] = Num1[4] XOR Num2[4] = 6F9C482Dh XOR 3C9DF1AFh = 5301B982h
Num3[8] = Num1[8] XOR Num2[8] = 881E63CAh XOR 7BB3F28Dh = F3AD9147h
19.5.2 Effetti provocati da XOR sugli operandi e sui flags
L'esecuzione dell'istruzione XOR tra SRC e DEST, modifica il contenuto del solo operando DEST che viene sovrascritto dal risultato prodotto dall'istruzione stessa; il contenuto dell'operando SRC rimane inalterato.xor di, ss:[di+05h]Dopo l'esecuzione di questa istruzione, la componente Offset contenuta in DI viene sovrascritta dal risultato prodotto da XOR!
xor dx, dxCome si può facilmente constatare, l'esecuzione di una tale istruzione provoca l'azzeramento del contenuto di DX; infatti:
0 XOR 0 = 0e:
1 XOR 1 = 0Poniamo, ad esempio, DX=1001110010000011b ed eseguiamo la seguente istruzione:
xor dx, dxIn presenza di questa istruzione, la CPU ottiene il seguente risultato: Il ricorso a XOR per l'azzeramento di un registro, è una pratica molto diffusa tra i programmatori Assembly; si tenga presente, comunque, che non si ottiene alcun guadagno in velocità rispetto alle analoghe istruzioni:
mov dx, 0e:
sub dx, dxL'esecuzione dell'istruzione XOR modifica i campi CF, PF, AF, ZF, SF e OF del Flags Register; il solo campo AF assume un valore indeterminato e non ha quindi alcun significato.
19.6 L'istruzione SHL
Con il mnemonico SHL si indica l'istruzione Shift Logical Left (scorrimento logico verso sinistra); lo scopo di questa istruzione è quello di effettuare uno scorrimento verso sinistra dei bit dell'operando DEST, il cui contenuto viene trattato come numero intero senza segno. Il numero di scorrimenti da effettuare, viene indicato dall'operando SRC; i posti rimasti liberi a destra nell'operando DEST vengono riempiti con degli zeri.shl ax, clIn presenza di questa istruzione, la CPU fa scorrere di 5 posti verso sinistra tutti i bit di AX; i 5 posti che si liberano a destra, vengono riempiti con degli zeri. La successione dei singoli scorrimenti produce quindi i seguenti risultati:
AX = 1110010110111000b, CF = 0
AX = 1100101101110000b, CF = 1
AX = 1001011011100000b, CF = 1
AX = 0010110111000000b, CF = 1
AX = 0101101110000000b, CF = 0I singoli bit che traboccano da sinistra, vengono salvati nel flag CF; nel nostro caso, dopo 5 scorrimenti, l'ultimo bit traboccato da sinistra è uno 0, per cui alla fine otteniamo AX=0101101110000000b e CF=0.
shl ax, clCome si può facilmente constatare, dopo i primi 16 scorrimenti tutti i 16 bit di AX sono traboccati da sinistra e sono stati sostituiti con 16 zeri; in sostanza, dopo i primi 16 scorrimenti si ottiene AX=0, per cui è perfettamente inutile continuare con gli altri 239 scorrimenti.
8 + (4 x 255) = 1028 cicli di clockLa frequenza di clock dell'8086 è di circa 5 milioni di cicli al secondo (5 MHz), per cui l'esecuzione dell'istruzione richiede un tempo "abissale" di:
1028 / 5000000 = 0.0002056 secondi = 0.2056 millisecondiQuesto problema è stato eliminato a partire dalle CPU 80286; tali CPU, infatti, sottopongono il contenuto del contatore (CL o Imm8), ad un AND con il valore 00011111b. Come sappiamo, una istruzione del tipo:
and cl, 00011111bazzera i tre bit più significativi di CL e lascia inalterati i restanti 5 bit. In sostanza, le CPU 80286 e superiori, prendono in considerazione solamente i primi 5 bit del contatore; con 5 bit possiamo rappresentare un qualunque valore compreso tra 0 e 31, più che sufficiente per operare con registri a 8, 16 o 32 bit.
19.6.1 Significato matematico dell'istruzione SHL
Come abbiamo visto nel capitolo dedicato alla matematica del computer, moltiplicare un numero intero senza segno m, espresso in base b, per un fattore bn (n intero positivo), equivale ad aggiungere n zeri alla destra dello stesso m; in questo modo, tutte le cifre di m vengono fatte scorrere di n posti verso sinistra.shl ax, nequivale a moltiplicare il contenuto binario di AX per 2n.
shl ax, 4In presenza di questa istruzione, la CPU sottopone il contenuto di AX ai seguenti 4 singoli scorrimenti:
AX = 0001010111100100b = 5604 = 2802 * 2, CF = 0
AX = 0010101111001000b = 11208 = 2802 * 4, CF = 0
AX = 0101011110010000b = 22416 = 2802 * 8, CF = 0
AX = 1010111100100000b = 44832 = 2802 * 16, CF = 0Come si può notare, dopo 4 scorrimenti verso sinistra, il contenuto iniziale 2802 di AX risulta moltiplicato per 24=16!
mul bxLa stessa CPU 80486 DX esegue questa istruzione in 13 cicli di clock e cioè, oltre 6 volte più lentamente rispetto all'uso di SHL!
AX = 1010111100100000b = 44832 = 2802 * 16, CF = 0Sottoponendo ora AX ad un ulteriore scorrimento di 1 bit verso sinistra, otteniamo:
AX = 0101111001000000b = 24128, CF = 1Questo risultato è sbagliato in quanto si è verificato il trabocco da sinistra, di un bit di valore 1; questa situazione viene segnalata da CF=1. In sostanza, il risultato corretto è rappresentato dal contenuto di AX e da un ulteriore bit (quello che è traboccato da sinistra), per un totale di 17 bit; infatti, aggiungendo 1 alla sinistra del precedente risultato, si ottiene:
10101111001000000b = 89664 = 2802 * 25In definitiva, una (pseudo) istruzione del tipo:
mul DEST, 2nè sostituibile con una (pseudo) istruzione del tipo:
shl DEST, nsolo se siamo sicuri che il risultato finale è interamente rappresentabile con l'ampiezza in bit di DEST.
19.6.2 Shift logical left su operandi di ampiezza arbitraria
Supponiamo di voler far scorrere verso sinistra, i bit di un numero intero senza segno di ampiezza arbitraria; in un caso del genere, la strada migliore da seguire consiste nel definire un procedimento generale, indipendente dall'ampiezza in bit dell'operando e dal numero di scorrimenti che vogliamo effettuare.Num1 = 0011110011110010bPoniamo AH=0 e carichiamo in AL il byte meno significativo di Num1 (AL=11110010b); in seguito ad una istruzione:
shl ax, 1otteniamo:
AX = 0000000111100100bIn sostanza, il bit più significativo di AL trabocca da sinistra e finisce nel bit meno significativo di AH; si ha quindi AH=00000001b e AL=11100100b.
shl ax, 1otteniamo:
AX = 0000000001111000bIn sostanza, il bit più significativo di AL trabocca da sinistra e finisce nel bit meno significativo di AH; si ha quindi AH=00000000b e AL=01111000b.
AL = AL OR BL = 01111000b OR 00000001b = 01111001bSalviamo il contenuto di AL in Num1[1]; a questo punto possiamo notare che:
Num1 = 0111100111100100bIl registro AH contiene il bit più significativo di Num1, traboccato da sinistra (nel nostro caso, AH=00000000b); appare anche evidente il fatto che, il procedimento appena descritto, può essere applicato a numeri interi senza segno di qualunque ampiezza.
bigNum db 10010010b, 00111100b, 00011111b ; 000111110011110010010010bIl codice che esegue lo scorrimento unitario verso sinistra, assume il seguente aspetto: Unendo i 3 risultati precedenti, otteniamo:
BigNum = 001111100111100100100100bIl bit più significativo di BigNum, traboccato da sinistra, si trova memorizzato nel bit meno significativo di AH; naturalmente, è fondamentale ricordare che la locazione di memoria riservata a BigNum deve avere spazio sufficiente per contenere il risultato dello shifting.
19.6.3 Effetti provocati da SHL sugli operandi e sui flags
L'esecuzione dell'istruzione SHL, modifica il contenuto del solo operando DEST che viene sovrascritto dal risultato prodotto dall'istruzione stessa; il contenuto dell'operando SRC rimane inalterato.shl cx, cl(ovviamente, sarebbe opportuno evitare l'inserimento nei propri programmi, di questo genere di istruzioni).
shl cx, clPrima di tutto, la CPU calcola:
CL = CL AND 00011111b = 11100110b AND 00011111b = 00000110b = 6Di conseguenza, il contenuto di CX viene alterato e diventa 0011101000000110b; i bit di CX vengono fatti scorrere di 6 posti verso sinistra, con il risultato finale CX=1000000110000000b (CF=0).
19.7 L'istruzione SAL
Con il mnemonico SAL si indica l'istruzione Shift Arithmetic Left (scorrimento aritmetico verso sinistra); lo scopo di questa istruzione è quello di effettuare uno scorrimento verso sinistra dei bit dell'operando DEST, il cui contenuto viene trattato come numero intero con segno in complemento a 2. Il numero di scorrimenti da effettuare, viene indicato dall'operando SRC; i posti rimasti liberi a destra nell'operando DEST, vengono riempiti con degli zeri.19.7.1 Significato matematico dell'istruzione SAL
Il significato matematico dell'istruzione SAL è del tutto simile a quello già illustrato per l'istruzione SHL; più precisamente, possiamo dire che una (pseudo) istruzione del tipo:sal DEST, nè equivalente ad una (pseudo) istruzione del tipo:
imul DEST, 2nNon dobbiamo dimenticare però che questa volta, l'operando DEST rappresenta un numero intero con segno in complemento a 2; come si può facilmente intuire, la situazione appare più delicata a causa del fatto che il bit di segno dell'operando DEST è quello più a sinistra.
sal ax, 1Dopo l'esecuzione di questa istruzione, otteniamo:
AX = 1011100111100010b = -17950 = (-8975) * 21, CF = 1, OF = 0Il risultato è esatto in quanto SAL non ha provocato la perdita del bit di segno di AX; infatti, il bit più significativo di AX continua a valere 1. La CPU segnala questa situazione ponendo OF=0, in quanto, moltiplicando un numero negativo per un numero positivo, abbiamo ottenuto, correttamente, un numero negativo.
sal ax, 1Dopo l'esecuzione di questa istruzione, otteniamo:
AX = 0111001111000100b = +29636, CF = 1, OF = 1Il risultato è sbagliato in quanto SAL ha provocato la perdita del bit di segno di AX; infatti, il bit più significativo di AX è passato da 1 a 0. La CPU segnala questa situazione ponendo OF=1, in quanto, moltiplicando un numero negativo per un numero positivo, abbiamo ottenuto, erroneamente, un numero positivo.
imul DEST, 2nè sostituibile con una (pseudo) istruzione del tipo:
sal DEST, nsolo se siamo sicuri che il risultato finale è interamente rappresentabile con l'ampiezza in bit di DEST.
19.7.2 Shift arithmetic left su operandi di ampiezza arbitraria
Come è stato già sottolineato, gli effetti prodotti da SAL sull'operando DEST, sono assolutamente identici a quelli prodotti da SHL; di conseguenza, se vogliamo applicare SAL ad operandi di ampiezza arbitraria, dobbiamo procedere esattamente come nell'esempio mostrato per SHL.19.7.3 Effetti provocati da SAL sugli operandi e sui flags
Anche in relazione agli effetti provocati da SAL sugli operandi e sui flags, valgono tutte le considerazioni già esposte per SHL.19.8 L'istruzione SHR
Con il mnemonico SHR si indica l'istruzione Shift Logical Right (scorrimento logico verso destra); lo scopo di questa istruzione è quello di effettuare uno scorrimento verso destra dei bit dell'operando DEST, il cui contenuto viene trattato come numero intero senza segno. Il numero di scorrimenti da effettuare, viene indicato dall'operando SRC; i posti rimasti liberi a sinistra nell'operando DEST, vengono riempiti con degli zeri.shr ax, clIn presenza di questa istruzione, la CPU fa scorrere di 5 posti verso destra tutti i bit di AX; i 5 posti che si liberano a sinistra, vengono riempiti con degli zeri. La successione dei singoli scorrimenti produce quindi i seguenti risultati:
AX = 0011100101101110b, CF = 0
AX = 0001110010110111b, CF = 0
AX = 0000111001011011b, CF = 1
AX = 0000011100101101b, CF = 1
AX = 0000001110010110b, CF = 1I singoli bit che traboccano da destra, vengono salvati nel flag CF; nel nostro caso, dopo 5 scorrimenti, l'ultimo bit traboccato da destra è un 1, per cui alla fine otteniamo AX=0000001110010110b e CF=1.
19.8.1 Significato matematico dell'istruzione SHR
Come abbiamo visto nel capitolo dedicato alla matematica del computer, dividere un numero intero senza segno m, espresso in base b, per un divisore bn (con n intero positivo), equivale a troncare n cifre dalla destra dello stesso m; in questo modo, tutte le cifre di m vengono fatte scorrere di n posti verso destra. Risulta, inoltre, che le n cifre troncate dalla destra di m, rappresentano il resto della divisione intera.shr ax, nequivale a dividere il contenuto binario di AX per 2n.
shr ax, 4In presenza di questa istruzione, la CPU sottopone il contenuto di AX ai seguenti 4 singoli scorrimenti:
AX = 0011010101111001b = 13689 = 27378 / 2 (R = 0b), CF = 0
AX = 0001101010111100b = 6844 = 27378 / 4 (R = 10b), CF = 1
AX = 0000110101011110b = 3422 = 27378 / 8 (R = 010b), CF = 0
AX = 0000011010101111b = 1711 = 27378 / 16 (R = 0010b), CF = 0Come si può notare, dopo 4 scorrimenti verso destra, il contenuto iniziale 27378 di AX risulta diviso per 24=16; inoltre, i 4 bit traboccati da destra e cioè, 0010b=2, rappresentano il resto della divisione intera!
div bxLa stessa CPU 80486 DX esegue questa istruzione in 24 cicli di clock e cioè 12 volte più lentamente rispetto all'uso di SHR!
div DEST, 2nè sempre sostituibile con una (pseudo) istruzione del tipo:
shr DEST, n
19.8.2 Shift logical right su operandi di ampiezza arbitraria
Supponiamo di voler far scorrere verso destra, i bit di un numero intero senza segno di ampiezza arbitraria; in tal caso, possiamo facilmente adattare il procedimento già illustrato per l'istruzione SHL.Num1 = 1011110111110011bPoniamo AL=0 e carichiamo in AH il byte più significativo di Num1 (AH=10111101b); in seguito ad una istruzione:
shr ax, 1otteniamo:
AX = 0101111010000000bIn sostanza, il bit meno significativo di AH trabocca da destra e finisce nel bit più significativo di AL; si ha quindi AH=01011110b e AL=10000000b.
shr ax, 1otteniamo:
AX = 0111100110000000bIn sostanza, il bit meno significativo di AH trabocca da destra e finisce nel bit più significativo di AL; si ha quindi AH=01111001b e AL=10000000b.
AH = AH OR BL = 01111001b OR 10000000b = 11111001bSalviamo il contenuto di AH in Num1[0]; a questo punto possiamo notare che:
Num1 = 0101111011111001bIl registro AL contiene il bit meno significativo di Num1, traboccato da destra (nel nostro caso, AL=10000000b); appare anche evidente il fatto che il procedimento appena descritto, può essere applicato a numeri interi senza segno di qualunque ampiezza.
bigNum db 10010010b, 00111100b, 00011111b ; 000111110011110010010010bIl codice che esegue lo scorrimento unitario verso destra, assume il seguente aspetto: Unendo i 3 risultati precedenti, otteniamo:
BigNum = 000011111001111001001001bIl bit meno significativo di BigNum, traboccato da destra, si trova memorizzato nel bit più significativo di AL.
19.8.3 Effetti provocati da SHR sugli operandi e sui flags
L'esecuzione dell'istruzione SHR, modifica il contenuto del solo operando DEST che viene sovrascritto dal risultato prodotto dall'istruzione stessa; il contenuto dell'operando SRC rimane inalterato.shr cx, clL'esecuzione dell'istruzione SHR con CL=0 o Imm8=0, non modifica alcun campo del Flags Register; ovviamente, in un caso del genere, il contenuto di DEST rimane inalterato.
19.9 L'istruzione SAR
Con il mnemonico SAR si indica l'istruzione Shift Arithmetic Right (scorrimento aritmetico verso destra); lo scopo di questa istruzione è quello di effettuare uno scorrimento verso destra, dei bit dell'operando DEST, il cui contenuto viene trattato come numero intero con segno in complemento a 2. Il numero di scorrimenti da effettuare, viene indicato dall'operando SRC; i posti rimasti liberi a sinistra nell'operando DEST, vengono riempiti con il bit di segno dello stesso DEST.sar ax, clIn presenza di questa istruzione, la CPU fa scorrere di 5 posti verso destra tutti i bit di AX; i 5 posti che si liberano a sinistra, vengono riempiti con il bit di segno (1) dello stesso AX. La successione dei singoli scorrimenti produce quindi i seguenti risultati:
AX = 1110001110010101b, CF = 1
AX = 1111000111001010b, CF = 1
AX = 1111100011100101b, CF = 0
AX = 1111110001110010b, CF = 1
AX = 1111111000111001b, CF = 0I singoli bit che traboccano da destra, vengono salvati nel flag CF; nel nostro caso, dopo 5 scorrimenti, l'ultimo bit traboccato da destra è uno 0, per cui alla fine otteniamo AX=1111111000111001b e CF=0.
19.9.1 Significato matematico dell'istruzione SAR
Come è stato dettagliatamente spiegato nel Capitolo 6, solamente in determinati casi, dividere un numero intero con segno m, espresso in base b, per un divisore bn (n intero positivo), equivale a troncare n cifre dalla destra dello stesso m; tale equivalenza sussiste solo se m è un numero intero positivo qualsiasi, oppure se m è un numero intero negativo, multiplo intero del divisore!sar ax, 4 ; +26227 / +16, Q = +1639, R = +3Il risultato prodotto da questa istruzione è:
AX = 0000011001100111b = +1639Inoltre, i 4 bit traboccati da destra, rappresentano il valore 0011b=+3.
sar ax, 4 ; -6544 / +16, Q = -409, R = 0Il risultato prodotto da questa istruzione è:
AX = 1111111001100111b = -409Inoltre, i 4 bit traboccati da destra, rappresentano il valore 0000b=0.
sar ax, 4 ; -31119 / +16, Q = -1944, R = -15Il risultato prodotto da questa istruzione è:
AX = 1111100001100111b = -1945Inoltre, i 4 bit traboccati da destra, rappresentano il valore 0001b=+1.
19.9.2 Shift arithmetic right su operandi di ampiezza arbitraria
Supponiamo di voler far scorrere verso destra, i bit di un numero intero con segno di ampiezza arbitraria; in tal caso, possiamo facilmente adattare il procedimento già illustrato per l'istruzione SHR.bigNum db 10010010b, 00111100b, 11011111b ; 110111110011110010010010bIl codice che esegue lo scorrimento unitario verso destra, assume il seguente aspetto: Unendo i 3 risultati precedenti, otteniamo:
BigNum = 111011111001111001001001bIl bit meno significativo di BigNum, traboccato da destra, si trova memorizzato nel bit più significativo di AL.
19.9.3 Effetti provocati da SAR sugli operandi e sui flags
L'esecuzione dell'istruzione SAR, modifica il contenuto del solo operando DEST che viene sovrascritto dal risultato prodotto dall'istruzione stessa; il contenuto dell'operando SRC rimane inalterato.sar cx, clL'esecuzione dell'istruzione SAR con CL=0 o Imm8=0, non modifica alcun campo del Flags Register; ovviamente, in un caso del genere il contenuto di DEST rimane inalterato.
19.10 Le istruzioni SHLD e SHRD
Con le CPU 80386 e superiori, vengono rese disponibili due ulteriori istruzioni di shifting, rappresentate dai mnemonici SHLD e SHRD; tali istruzioni sono molto simili a SHL e SHR ma, rispetto a queste ultime, svolgono un lavoro molto più complesso.19.10.1 L'istruzione SHLD
Con il mnemonico SHLD si indica l'istruzione Double Precision Shift Logical Left (scorrimento logico verso sinistra, in doppia precisione); lo scopo di questa istruzione è quello di effettuare uno scorrimento logico verso sinistra, dei bit dell'operando DEST (primo operando). Il numero di scorrimenti da effettuare, viene indicato dal contenuto del terzo operando (contatore); i posti rimasti liberi a destra nell'operando DEST, vengono riempiti con altrettanti bit fatti traboccare dalla sinistra dell'operando SRC (secondo operando). Il contenuto dell'operando SRC non subisce alcuna modifica.shld eax, ebx, clIn presenza di questa istruzione, la CPU fa scorrere di 4 posti verso sinistra tutti i bit di EAX; i 4 posti che si liberano a destra vengono riempiti con altrettanti bit fatti traboccare dalla sinistra del registro EBX. Alla fine otteniamo il seguente risultato:
EAX = 01110010101101110001110010100011b, EBX=00111011000111111001001111000010b, CF = 1Come si può notare, il contenuto di EBX rimane inalterato; inoltre, l'ultimo bit traboccato dalla sinistra di EAX è un 1, per cui alla fine otteniamo CF=1.
shld edx, eax, 16
19.10.2 L'istruzione SHRD
Con il mnemonico SHRD si indica l'istruzione Double Precision Shift Logical Right (scorrimento logico verso destra, in doppia precisione); lo scopo di questa istruzione è quello di effettuare uno scorrimento logico verso destra, dei bit dell'operando DEST (primo operando). Il numero di scorrimenti da effettuare, viene indicato dal contenuto del terzo operando (contatore); i posti rimasti liberi a sinistra nell'operando DEST, vengono riempiti con altrettanti bit fatti traboccare dalla destra dell'operando SRC (secondo operando). Il contenuto dell'operando SRC non subisce alcuna modifica.shrd eax, ebx, clIn presenza di questa istruzione, la CPU fa scorrere di 4 posti verso destra tutti i bit di EAX; i 4 posti che si liberano a sinistra vengono riempiti con altrettanti bit fatti traboccare dalla destra del registro EBX. Alla fine otteniamo il seguente risultato:
EAX=11110000011100101011011100011100b, EBX=00111011000111111001001111011111b, CF = 1Come si può notare, il contenuto di EBX rimane inalterato; inoltre, l'ultimo bit traboccato dalla destra di EAX è un 1, per cui alla fine otteniamo CF=1.
19.10.3 Effetti provocati da SHLD e SHRD, sugli operandi e sui flags
L'esecuzione delle istruzioni SHLD e SHRD, modifica il contenuto del solo operando DEST che viene sovrascritto dal risultato prodotto dalle istruzioni stesse; il contenuto dell'operando SRC rimane inalterato.shld ecx, ecx, clSi ricordi che in presenza delle istruzioni SHLD e SHRD, la CPU utilizza come contatore il contenuto dei primi 5 bit di CL, senza apportare alcuna modifica allo stesso CL; ne consegue che la precedente istruzione, non provoca alcuna modifica sul contenuto del registro destinazione ECX!
shrd ax, bx, 30In un caso del genere, anche i flags assumono valori privi di significato!
19.11 L'istruzione ROL
Con il mnemonico ROL si indica l'istruzione Rotate Left (rotazione verso sinistra). Lo scopo di questa istruzione è quello di effettuare una rotazione verso sinistra dei bit dell'operando DEST; il numero di rotazioni da effettuare, viene indicato dall'operando SRC.rol ax, clIn presenza di questa istruzione, la CPU fa ruotare di 5 posti verso sinistra tutti i bit di AX; ogni singolo bit che trabocca dalla sinistra di AX viene memorizzato in CF e, contemporaneamente, viene fatto rientrare dalla destra dello stesso AX. La successione delle singole rotazioni produce quindi i seguenti risultati:
AX = 1110010110111000b, CF = 0
AX = 1100101101110001b, CF = 1
AX = 1001011011100011b, CF = 1
AX = 0010110111000111b, CF = 1
AX = 0101101110001110b, CF = 0L'ultimo bit sottoposto a rotazione è uno 0; di conseguenza, alla fine otteniamo AX=0101101110001110b e CF=0.
19.11.1 ROL su operandi di ampiezza arbitraria
Supponiamo di voler far ruotare verso sinistra i bit di un numero binario di ampiezza arbitraria; in tal caso, possiamo facilmente adattare il procedimento già illustrato per l'istruzione SHL.bigNum db 10010010b, 00111100b, 10011111b ; 100111110011110010010010bIl codice che esegue la rotazione unitaria verso sinistra, assume il seguente aspetto: Unendo i 3 risultati precedenti, otteniamo:
BigNum = 001111100111100100100101bIl bit più significativo di BigNum, traboccato da sinistra, oltre ad essere rientrato da destra, si trova anche memorizzato nel bit meno significativo di AH.
19.11.2 Effetti provocati da ROL sugli operandi e sui flags
L'esecuzione dell'istruzione ROL modifica il contenuto del solo operando DEST che viene sovrascritto dal risultato prodotto dall'istruzione stessa; il contenuto dell'operando SRC rimane inalterato.rol cx, clL'esecuzione dell'istruzione ROL con CL=0 o Imm8=0, non modifica alcun campo del Flags Register; ovviamente, in un caso del genere, il contenuto di DEST rimane inalterato.
19.12 L'istruzione RCL
Con il mnemonico RCL si indica l'istruzione Rotate through Carry Left (rotazione verso sinistra attraverso CF); lo scopo di questa istruzione è quello di effettuare una rotazione verso sinistra dei bit dell'operando DEST+CF, con CF che ricopre il ruolo di bit meno significativo. Il numero di rotazioni da effettuare viene indicato dall'operando SRC.rcl ax, clIn presenza di questa istruzione, la CPU fa ruotare di 5 posti verso sinistra tutti i bit di AX+CF; in sostanza, stiamo sottoponendo a rotazione verso sinistra un operando a 17 bit, con CF che ricopre il ruolo di bit meno significativo. La successione delle singole rotazioni produce quindi i seguenti risultati:
AX = 1110010110111001b, CF = 0
AX = 1100101101110010b, CF = 1
AX = 1001011011100101b, CF = 1
AX = 0010110111001011b, CF = 1
AX = 0101101110010111b, CF = 0L'ultimo bit traboccato da sinistra è uno 0; di conseguenza, alla fine otteniamo AX=0101101110010111b e CF=0.
19.12.1 RCL su operandi di ampiezza arbitraria
Supponiamo di voler far ruotare verso sinistra, con l'ausilio di CF, i bit di un numero binario di ampiezza arbitraria; in tal caso, possiamo facilmente adattare il procedimento già illustrato per l'istruzione SHL.bigNum db 10010010b, 00111100b, 10011111b ; 100111110011110010010010bAssumendo di avere, inizialmente, CF=0, possiamo scrivere il seguente codice: Unendo i 3 risultati precedenti, otteniamo:
BigNum = 001111100111100100100100b, CF = 1Il vecchio contenuto di CF, e cioè 0, viene fatto entrare dalla destra di BigNum; tutti i bit di BigNum scorrono di una posizione verso sinistra. Il bit più significativo di BigNum trabocca da sinistra e finisce nel bit meno significativo di AH; a questo punto, l'istruzione SAHF pone CF=1 (infatti, CF occupa la posizione n. 0 nel registro FLAGS).
19.12.2 Effetti provocati da RCL sugli operandi e sui flags
L'esecuzione dell'istruzione RCL modifica il contenuto del solo operando DEST che viene sovrascritto dal risultato prodotto dall'istruzione stessa; il contenuto dell'operando SRC rimane inalterato.rcl cx, clL'esecuzione dell'istruzione RCL con CL=0 o Imm8=0, non modifica alcun campo del Flags Register; ovviamente, in un caso del genere, il contenuto di DEST rimane inalterato.
19.13 L'istruzione ROR
Con il mnemonico ROR si indica l'istruzione Rotate Right (rotazione verso destra); lo scopo di questa istruzione è quello di effettuare una rotazione verso destra dei bit dell'operando DEST. Il numero di rotazioni da effettuare viene indicato dall'operando SRC.ror ax, clIn presenza di questa istruzione, la CPU fa ruotare di 5 posti verso destra tutti i bit di AX; ogni singolo bit che trabocca dalla destra di AX, viene memorizzato in CF e, contemporaneamente, viene fatto rientrare dalla sinistra dello stesso AX. La successione delle singole rotazioni produce quindi i seguenti risultati:
AX = 0011100101101110b, CF = 0
AX = 0001110010110111b, CF = 0
AX = 1000111001011011b, CF = 1
AX = 1100011100101101b, CF = 1
AX = 1110001110010110b, CF = 1L'ultimo bit sottoposto a rotazione è un 1; di conseguenza, alla fine otteniamo AX=1110001110010110b e CF=1.
19.13.1 ROR su operandi di ampiezza arbitraria
Supponiamo di voler far ruotare verso destra i bit di un numero binario di ampiezza arbitraria; in tal caso, possiamo facilmente adattare il procedimento già illustrato per l'istruzione SHR.bigNum db 10010011b, 00111100b, 00011111b ; 000111110011110010010011bIl codice che esegue la rotazione unitaria verso destra, assume il seguente aspetto: Unendo i 3 risultati precedenti, otteniamo:
BigNum = 100011111001111001001001bIl bit meno significativo di BigNum, traboccato da destra, oltre ad essere rientrato da sinistra, si trova anche memorizzato nel bit più significativo di AL.
19.13.2 Effetti provocati da ROR sugli operandi e sui flags
L'esecuzione dell'istruzione ROR, modifica il contenuto del solo operando DEST che viene sovrascritto dal risultato prodotto dall'istruzione stessa; il contenuto dell'operando SRC rimane inalterato.ror cx, clL'esecuzione dell'istruzione ROR con CL=0 o Imm8=0, non modifica alcun campo del Flags Register; ovviamente, in un caso del genere, il contenuto di DEST rimane inalterato.
19.14 L'istruzione RCR
Con il mnemonico RCR si indica l'istruzione Rotate through Carry Right (rotazione verso destra attraverso CF); lo scopo di questa istruzione è quello di effettuare una rotazione verso destra dei bit dell'operando CF+DEST, con CF che ricopre il ruolo di bit più significativo. Il numero di rotazioni da effettuare viene indicato dall'operando SRC.rcr ax, clIn presenza di questa istruzione, la CPU fa ruotare di 5 posti verso destra tutti i bit di CF+AX; in sostanza, stiamo sottoponendo a rotazione verso destra un operando a 17 bit, con CF che ricopre il ruolo di bit più significativo. La successione delle singole rotazioni produce quindi i seguenti risultati:
AX = 1011100101101110b, CF = 0
AX = 0101110010110111b, CF = 0
AX = 0010111001011011b, CF = 1
AX = 1001011100101101b, CF = 1
AX = 1100101110010110b, CF = 1L'ultimo bit traboccato da destra è un 1; di conseguenza, alla fine otteniamo AX=1100101110010110b e CF=1.
19.14.1 RCR su operandi di ampiezza arbitraria
Supponiamo di voler far ruotare verso destra, con l'ausilio di CF, i bit di un numero binario di ampiezza arbitraria; in tal caso, possiamo facilmente adattare il procedimento già illustrato per l'istruzione SHR.bigNum db 10010011b, 00111100b, 10011111b ; 100111110011110010010011bAssumendo di avere, inizialmente, CF=0, possiamo scrivere il seguente codice: Unendo i 3 risultati precedenti, otteniamo:
BigNum = 010011111001111001001001b, CF = 1Il vecchio contenuto di CF, e cioè 0, viene fatto entrare dalla sinistra di BigNum; tutti i bit di BigNum scorrono di una posizione verso destra. Il bit meno significativo di BigNum trabocca da destra e finisce nel bit più significativo di AL; a questo punto, spostiamo AL in AH, facciamo scorrere di 7 posti verso destra il contenuto di AH ed eseguiamo una istruzione SAHF che pone CF=1 (infatti, CF occupa la posizione n. 0 nel registro FLAGS).
19.14.2 Effetti provocati da RCR sugli operandi e sui flags
L'esecuzione dell'istruzione RCR, modifica il contenuto del solo operando DEST che viene sovrascritto dal risultato prodotto dall'istruzione stessa; il contenuto dell'operando SRC rimane inalterato.rcr cx, clL'esecuzione dell'istruzione RCR con CL=0 o Imm8=0, non modifica alcun campo del Flags Register; ovviamente, in un caso del genere, il contenuto di DEST rimane inalterato.
19.15 Istruzioni logiche nei linguaggi di alto livello
Molti linguaggi di alto livello, forniscono due categorie di istruzioni logiche chiamate, operatori logici e operatori booleani; gli operatori logici agiscono sui singoli bit dei loro operandi (proprio come succede con le istruzioni della CPU esaminate in questo capitolo), mentre gli operatori booleani agiscono sul cosiddetto valore booleano dei loro operandi.C = A AND Bviene definita espressione logica; il risultato che viene memorizzato in C è un valore numerico intero, conseguenza di un AND logico (bit per bit) tra i due operandi A e B.
C = A AND Bviene definita espressione booleana; il risultato che viene memorizzato in C è un valore booleano, conseguenza di un AND booleano tra i due operandi A e B. Il risultato è TRUE se, e solo se, entrambi gli operandi sono TRUE.
A AND B = 10101010b AND 01010101b = 00000000b = 0Un AND booleano produce, invece:
A AND B = TRUE AND TRUE = TRUE = 1(sia A che B hanno, infatti, un valore non nullo).
19.16 Applicazioni pratiche delle istruzioni logiche
Come applicazione pratica delle istruzioni logiche della CPU, possiamo riprendere l'esempio del precedente capitolo, relativo alla conversione in binario di un numero Unpacked BCD; abbiamo visto che applicando il metodo delle divisioni successive (con divisore 2) al numero 07050301h (in formato Unpacked BCD), otteniamo la seguente sequenza di resti: I vari resti rappresentano le cifre binarie del numero decimale 7531; come facciamo a memorizzare tali resti nei singoli bit di un numero binario?