|
|
səhifə | 7/10 | tarix | 16.12.2017 | ölçüsü | 1,03 Mb. | | #35021 |
| mov ax,33
stc
sbb ax,32
mov nr1,ax
end;
writeln('rezultatul este: ',nr1);
end.
Comparati rezultatul cu cel obtinut in exercitiul precedent.
Instructiunea se utilizeaza mai ales in bucle care contin o secventa de
genul : stc
sbb ax,0
sbb ax,0 ...etc.
In functie de numarul de instructiuni sbb,daca flagul CF este 1,se va
obtine un rezultat diferit.Astfel,se pot genera rezultate diferite,in
functie de valoarea flagului CF.Se utilizeaza la depanare si setari.
-46-
DEC d - decrementeaza destinatia d cu o unitate.Este inversa instructiunii
INC.Nu afecteaza flagul CF.Se utilizeaza pentru a scadea o unitate
dintr-o valoare sau dintr-un registru.Cel mai frecvent se utilizeaza
pentru functii si bucle de repetitie,pentru a asigura repetarea sec-
ventiala a unei operatii:
EXEMPLU: program assmb42;
uses WinCRT;
var nr1,nr2:word;
function D2(nr1:word):word;assembler;
asm
mov ax,nr1
dec ax
end;
begin
for nr1:=2 to 15 do
begin
nr2:=D2(nr1);
writeln('nr1= ',nr1,' nr2= ',nr2);
end;
end.
CMP d,s -compara sursa cu destinatia prin efectuarea unei operatii de
scadere a sursei din destinatie,dar fara sa modifice valoarea
celor doi operanzi (sursa si destinatia raman cu valorile ini-
tiale).Dupa comparare,actualizeaza registrul FLAGS in functie de
rezultatul obtinut (semn,paritate etc.).Pentru valorificarea
rezultatului trebuie preluat registrul FLAGS si interpretate
noile setari:
EXEMPLU: program assmb43;
uses WinCRT,WinProcs;
var nr1:word;
begin
asm
mov ax,55
mov bx,55
cmp ax,bx
pushf
pop nr1
end;
writeln('numarul rezultat este: ',LOBYTE(nr1));
end.
In exemplul de mai sus,puteti alterna valorile celor doi operanzi.In
cazul in care rezultatul comparatiei va fi negativ (sursa are valoare
mai mare decat destinatia),byte-ul inferior din registrul FLAGS va returna
o valoare mai mare decat 131 (deoarece bitul de semn va fi setat 1).Daca
cele doua valori sunt egale,byte-ul inferior din FLAGS va fi 70,iar daca
sursa va fi mai mica decat destinatia,byte-ul inferior va avea o valoare
mai mica decat 70 (2 sau 6 etc.).Revedeti reprezentarea binara a numerelor
zecimale,pentru a descifra semnificatia registrului FLAGS,biti cu bit.
Pentru a utiliza propriu zis instructiunea de comparare,se poate edita
un program sau o functie care evalueaza valoarea registrului FLAGS in
urma executiei unei instructiuni cmp:
-47-
EXEMPLU: program assmb44;
uses WinCRT,WinProcs;
var x1,y1,z1,r:word;
function Compara(x1,y1:word):word;assembler;
asm
mov ax,x1
mov bx,y1
cmp ax,bx
pushf
pop z1
end;
begin
x1:=9;
for y1:=1 to 15 do
begin
r:=Compara(x1,y1);
if LOBYTE(z1)=70 then
writeln(' numerele sunt egale cu : ',x1)
else
writeln('numerele nu sunt egale !');
end;
end.
In mod similar se pot selecta situatiile in care sursa este mai mare,sau
sursa este mai mica decat destinatia( LOBYTE(z1) > 70 sau <70 ).
NEG d - scade din zero un intreg.Rezultatul acestei operatii este schim-
barea bitului de semn din registrul FLAGS.Implicit operandul speci-
ficat ca destinatie isi schimba semnul (din pozitiv devine negativ
iar din negativ devine pozitiv cu valoarea complementara "in oglinda")
EXEMPLU: program assmb45;
uses WinCRT;
var nr1,nr2:word;
begin
asm
mov ax,-77
neg ax
mov nr1,ax
mov bx,3
neg bx
mov nr2,bx
end;
writeln('numarul nr1 este: ',nr1);
writeln('numarul nr2 este: ',nr2);
end.
Observati ca pentru 3 se returneaza 65533,adica complementul fata de
valoarea maxima de 65535.Doua instructiuni NEG succesive se anuleaza
reciproc.
Toate instructiunile aritmetice binare de mai sus,actualizeaza valoarea
bitilor de stare din byte-ul inferior al registrului FLAGS(adica SF,ZF,PF
si OF.Unele dintre ele actualizeaza si flag-ul CF.Valorile actuale ale
fiecarui bit de stare se utilizeaza pentru programarea unor rutine auto-
mate de verificare si depanare a programelor de calcul.
-48-
MUL s -efectueaza multiplicarea valorii din registrul AX cu cea din
sursa (s).Daca operandul este un byte,atunci se va multiplica prim
s valoarea continuta in registrul AL iar rezultatul se va salva
in registrii AH si AL.Daca operandul este un word,atunci se va
multiplica prin s valoarea din registrul AX iar rezultatul se va
salva in registrii AX si DX.Pentru operandul de un byte,rezultatul
returnat va fi de 1 word (pe 16 biti) iar daca operandul este de
tip word,rezultatul returnat va fi de tip dword(32 de biti).
MUL reseteaza registrul FLAGS la fel ca si INC.
Valoarea din s trebuie sa fie din tipul unsigned (pozitiva).
EXEMPLU: program assmb46;
uses WinCRT;
var nr1,nr2:byte;
rez1:word;
begin
asm
mov ax,13
mov bx,7
mul bx
mov nr1,ah
mov nr2,al
mov rez1,ax
end;
writeln('numarul nr1 rezultat este(AH): ',nr1);
writeln('numarul nr2 rezultat este(AL): ',nr2);
writeln('rez1 este(AX): ',rez1);
end.
Daca valoarea din AX este negativa,rezultatul va fi complementul fata de
65535 al rezultatului.Pentru a obtine rezultatul corect se poate utiliza
instructiunea NEG:
EXEMPLU: program assmb47;
uses WinCRT;
var nr1,nr2:word;
begin
asm
mov ax,-15
mov bx,77
mul bx
neg ax
mov nr1,ax
mov nr2,dx
end;
writeln(' nr1 este (AX): ',nr1);
writeln(' nr2 este (DX): ',nr2);
end.
Instructiunea MUL nu este performanta in cazul numerelor mari.Se poate
utiliza cu succes mai ales pentru programarea unor bucle de repetitie
cu numere mici,sau pentru calculul unor adrese (Offset-ul nu poate fi
mai mare decat valorile reprezentabile ale rezultatului).
Pentru procesoarele din generatiile actuale,MUL accepta si operand de
32 de biti si returneaza rezultatul pe 64 de biti(accepta valori f.mari).
-49-
IMUL s -este identica cu MUL,dar accepta ca opernad(sursa s),un mumar de
tip signed (cu semn)(Exemplu: imul s ...unde s este -7 ).
DIV s -este instructiunea prin care valoarea din registrul acumulator(AX)
este impartita prin valoarea din sursa (s).In ecuatie,deimpartitul
stocat in AX trebuie sa fie cu tip dublu fata de divizorul specificat
iar rezultatul si restul var fi din acelasi tip cu divizorul.Astfel,
daca divizorul este de tip byte,deimpartitul va fi de tip word si va
fi preluat din AX.Rezultatul este returnat in AL,iar restul in AH:
EXEMPLU: program assmb48;
uses WinCRT;
var nr1:byte;
rez,rest:byte;
begin
asm
mov ax,19
mov nr1,3
div nr1
mov rez,AL
mov rest,AH
end;
writeln('19 impartit la 3 rezulta: ');
writeln(rez,' rest ',rest);
end.
Daca divizorul este de tip word,deimpartitul va fi de tip dword si va
fi preluat din registrii AX si DX,respectiv word-ul superior va fi
preluat din DX iar cel inferior va fi preluat din AX.Rezultatul va fi
returnat in AX iar restul va fi returnat in DX.
EXEMPLU: program assmb49;
uses WinCRT;
var nr1:word;
rez,rest:word;
begin
asm
mov AX,29
mov DX,0
mov nr1,5
div nr1
mov rez,AX
mov rest,DX
end;
writeln('rezultatul impartirii este: ');
writeln('rez,' rest ',rest);
end.
Asadar,impartirea se face cu rest,iar rezultatul si restul suprascriu
valoarea initiala.In caz ca doriti sa repetati operatia puteti salva
valorile initiale cu PUSH inainte de a efectua impartirea.
IDIV s - este identica cu DIV,dar accepta pentru divizor (valoarea din
sursa s) o valoare de tip signed (cu semn).In rest toate regulile sunt
identice cu cele de la instructiunea DIV(deimpartitul este preluat din
AX daca divizorul este de tip byte,sau din DX si AX daca este tip word)
-50-
INSTRUCTIUNI ARITMETICE DECIMALE
-sunt instructiuni care se utilizeaza in combinatie cu instructiunile
aritmetice binare (cele prezentate mai sus).Se utilizeaza pentru a
ajusta rezultatul unei operatii binare la un numar de tip unpacked deci-
mal,sau packed decimal sau pentru a modifica operanzii unei operatii
aritmetice binare astfel incat se fie de tip packed sau unpacked decimal.
Cu alte cuvinte,numerele zecimale sunt scrise in format hexazecimal,
din care se exclud numerele care incep cu o litera.Astfel,de exemplu,
numarul 10 decimal,transformat in hexazecimal,in loc sa fie 0A va fi tot
10.Diferenta este ca numarul 10 decimal,in reprezentare binara este:
0000 1010 iar numarul 10 hexazecimal in reprezentare binara este:
0001 0000.Instructiunile AAA si AAS,dupa ce au realizat ajustarea ASCII,
inlocuiesc prin zerouri primii patru biti din bytes.Astfel,in cazul
exemplului de mai sus,10 decimal devine 10 unpacked,adica 10 hexazecimal,
adica 0001 0000,care,dupa inlocuirea primilor patru biti devine 0000 0000
adica 0.
Dupa inlocuirea primilor patru biti cu zerouri,valorile posibile vor
fi cuprinse intre 0000 0000 si 0000 1111 adica intre 0 si 15.
AAA - este operatia de ajustare dupa adunare in AX (ASCII Adjust for Add
in AX).Modifica valoarea din registrul AL astfel incat sa fie de tip
unpacked decimal,dupa care inlocuieste prin zero primii patru biti.
Instructiunea AAA se poate apela doar dupa o operatie de adunare a
doi operanzi de tip unpacked decimals in AL.Daca este cazul,este
setat si flagul CF,iar AH este incrementat daca "carry" este necesar.
EXEMPLU: program assmb50;
uses WinCRT;
var nr1,nr2,nr3:byte;
begin
asm
mov AL,1+9
AAA
mov nr1,AL
mov AL,1+10
AAA
mov nr2,AL
mov AL,1+24
AAA
mov nr3,AL
end;
writeln('nr1 este: ',nr1);
writeln('nr2 este: ',nr2);
writeln('nr3 este: ',nr3);
end.
In exemplul de mai sus,1+9 rezulta 10 (vezi mai sus).1+10 rezulta 11,care
scris unpacked devine 11 hexazecimal,adica 0001 0001.Dupa inlocuirea prin
zero a primilor patru biti,devine 0000 0001,adica 1.1+24 rezulta 25,care
scris hexazecimal este 1F,adica 0001 1111.Dupa inlocuirea primilor patru
biti prin zerouri,numarul devine 0000 1111,adica 15.
Cu ajutorul acestei instructiuni,orice numar de tip byte va fi transformat
intr-o valoare cuprinsa intre 0 si 15 (respectiv 0000 0000 la 0000 1111).
-51-
Pentru a clarifica orice nelamurire,sau pentru a programa aceste instruc-
tiuni,trebuie sa aveti un tabel de conversie a numerelor decimale in
hexazecimale si in numare binare (perferabil tabelul complet care include
si numerele octale,respectiv ASCII).
Acest gen de operatii,sunt utile atunci cand se doreste selectia unei
anumite optiuni dintre maxim 16 posibile.De exemplu,daca doriti sa se-
lectati automat o linie de adresa a unui procesor cu 16 linii de adresa,
se va utiliza instructiunea AAA,pentru a selecta una dintre liniile de
date in functie de valoarea din registrul AL.
AAS -este operatia de ajustare dupa scadere (ASCII Adjust for substract
in AX).Este similara cu AAA,dar poate fi apelata doar dupa ce s-a
efectuat in AL o operatie de scadere cu doi operanzi unpacked decimali
Instructiunea schimba valoarea din AL la o valoare unpacked (despache-
tata) si apoi inlocuieste prin zero primii patru biti.
EXEMPLU: program assmb51;
uses WinCRT;
var nr1:byte;
begin
asm
mov AL,29-13
AAS
mov nr1,AL
end;
writeln('numarul rezultat este: ',nr1);
end.
In exemplul de mai sus,29-13 rezulta 16 in AL.Ajustat la o valoare de tip
unpacked,16 devine 10 hexazecimal adica 0001 0000.Dupa inlocuirea celor
patru biti prin zerouri,numarul devine 0000 0000,adica 0.
AAM -este operatia de ajustare dupa inmultire(ASCII Adjust for Multiply
in AX).Este operatia prin care rezultatul unei inmultiri va fi adjustat
la doua numere unpacked distincte,returnate in registrii AH si AL.In
registrul AH se va returna digitul cu ordinul superior,iar in registrul
AL se va returna digitul cu ordinul inferior.
EXEMPLU: program assmb52;
uses WinCRT;
var nr1:byte;
r1,r2:byte;
begin
asm
mov AX,255
mov nr1,1
mul nr1
AAM
mov r1,AL
mov r2,AH
end;
writeln('registrul AL este: ',r1);
writeln('registrul AH este: ',r2);
end.
Pentru a intelege operatia,repetati exercitiul cu numarul 256,apoi 257,
apoi executati diferite inmultiri si observati cei doi digiti.
-52-
AAD - este oparatia de ajustare pentru impartire (ASCII adjust for
divide in AX) care modifica valorile din AH si AL astfel incat
rezultatul impartirii dintre doua numere zecimale sa fie tot un
numar zecimal.AH va contine digitul superior iar AL va contine
digitul inferior.Instructiunea efectueaza ajustarea la un numar
decimal despachetat si plaseaza rezultatul in AL in timp ce AH va
contine valoarea zero.Regulile sunt la fel ca pentru AAM.
EXEMPLU: program assmb53;
uses WinCRT;
var nr1:byte;
rez1,rest1:byte;
rez2,rest2:byte;
rez3,rest3:byte;
begin
asm
mov AX,34
mov nr1,5
div nr1
mov rez1,AL
mov rest1,AH
AAD
mov rez2,AL
mov rest2,AH
div nr1
mov rez3,AL
mov rest3,AH
end;
writeln('rez1= ',rez1,' rest1= ',rest1);
writeln('rez2= ',rez2,' rest2= ',rest2);
writeln('rez3= ',rez3,' rest3= ',rest3);
end.
Pentru a intelege mai bine operatia efectuata,executati exercitiul cu o
serie de numere consecutive in AX (33,34,35,36,37...etc).Observati cum
valoarea din AH este transferata in AL in urma operatiei AAD.
DAA -este operatia de ajustare decimala pentru adunare (Decimal Adjust for
Add in AX).Daca este cazul,seteaza si flagul CF.Nu are operanzi.
EXEMPLU: program assmb54;
uses WinCRT;
var nr1,nr2:byte;
begin
asm
mov AL,0+0
DAA
mov nr1,AL
mov AL,1+1
DAA
mov nr2,AL
end;
writeln('nr1 este: ',nr1);
writeln('nr2 este: ',nr2);
end.
-53-
Instructiunea trebuie sa urmeze dupa o operatie de adunare in AL.Ajustarea
consta practic in adunarea numarului 96 la valoarea din AL.Pentru a
intelege mai bine operatia,consultati tabelul ASCII.Valoarea 96 decimala
corespunde cu litera "a" ASCII.Instructiunea este foarte untila mai ales
pentru operatii asupra codurilor numerice ale caracterelor ASCII.
EXEMPLU: program assmb54b;
uses WinCRT;
var x,y:byte;
function Scrie(y:byte):word;assembler;
asm
mov AL,x+0
DAA
mov y,AL
end;
begin
for x:=96 to 119 do
begin
y:=Scrie(x);
write(CHR(y));
end;
end.
DAS - este operatia de ajustare decimala pentru scadere (Decimal Adjust
for Substract in AX).Trebuie sa urmeze dupa o operatie de scadere
in AL.Daca este necesar,se seteaza si flagul CF.
EXEMPLU: program assmb55;
uses WinCRT;
var nr1,nr2:byte;
begin
asm
mov AL,198-1
DAS
mov nr1,AL
mov AL,199-3
DAS
mov nr2,AL
end;
writeln('caracterul cu numarul: ',nr1,' este: ',CHR(nr1));
writeln('caracterul cu numarul: ',nr2,' este: ',CHR(nr2));
end.
Practic,ajustarea consta din scadrea valorii 96 din valoarea stocata in
AL.Astfel,instructiunea se poate utiliza pentru operatii cu caractere,sau
pentru a afla numerul de ordine al unui carcater,etc.Atentie insa la
faptul ca numerele despachetate exclud valorile hexazecimale 0A,0B,0C,0D,
0E si 0F.Astfel in loc de 256 de valori rezulta doar 250.Functiile liniare
in care se utilizeaza doar valoarea 96 vor returna valori eronate atunci
cand operatia se face "cu imprumut (with borrow) ",adica atunci cand se
depaseste valoarea domeniul de reprezentare pentru un byte (0-256).
Efectuati cateva exercitii cu serii de numere consecutive si evaluati
rezultatul.Atunci cand programati functii automate,cu aceste instructiuni,
verificati cu atentie fiecare valoare posibila,inainte de a utiliza
functia respectiva.
-54-
INSTRUCTIUNI LOGICE
-sunt asemanatoare cu operatiile logice,dar spre deosebire de operatiile
simple in care operanzii trebuie sa fie obligatoriu valori imediate,in
instructiunile logice se pot utiliza ca operanzi atat registrii cat si
variabilele de memorie.
NOT d -este operatia de negare a operandului de destinatie (d).Negarea se
face prin returnarea valorii complementare ("in oglinda").Nu are
nici un efect asupra registrului FLAGS.Valoarea rezultata inlocuieste
valoarea preexistenta.
EXEMPLU: program assmb56;
uses WinCRT;
var nr1:word;
nr2:byte;
begin
asm
mov nr1,15
NOT nr1
mov AL,15
NOT AL
mov nr2,AL
end;
writeln('Complementul "WORD" al lui 15 este: ',nr1);
writeln('Complementul "BYTE" al lui 15 este: ',nr2);
end.
AND d,s
OR d,s
XOR d,s - sunt similare cu operatiile logice cu acelasi nume,dar accepta
70>
Dostları ilə paylaş: |
|
|