destinatie.Poate efectua operatii intre registrii generali,intre registrii
səhifə 6/10 tarix 16.12.2017 ölçüsü 1,03 Mb. #35021
destinatie.Poate efectua operatii intre registrii generali ,intre registrii
de procesor si variabilele de memorie ,intre registrii generali si cei de
adresa etc.Operatia se poate executa doar daca sursa si destinatia sunt
de acelasi tip de data (byte la byte,word la word etc.).Este probabil cea
mai uzitata instructiune si a fost deja exemplificata extensiv (vezi toate
exemplele precedente).
XCHG - inlocuieste reciproc cei doi operanzi (permuteaza reciproc).Ca
rezultat sursa va primi valoarea destinatiei si reciproc.Ordinea celor
doi operanzi nu conteaza.Se poate utiliza pentru date de tip byte,word,
sau dword,atat intre variabile cat si intre registri,sau intre registri
si variabile de memorie (poate introduce date din memorie in registri sau
din registri in memorie).
EXEMPLU: program assmb27;
uses WinCRT;
var nr1,nr2:word;
begin
asm
mov ax,333
mov bx,777
xchg ax,bx
xchg bx,nr1
xchg ax,nr2
end;
writeln('valoarea preluata de nr1 este: ',nr1);
writeln('valoarea preluata de nr2 este: ',nr2);
end.
La fel ca si MOV este destinata mai ales pentru a face schimb de date
intre procesor si memoria fizica.In cazul unui grup de procesoare de
acelasi fel,impreuna cu instructiunile I/O se poate utiliza pentru ope-
ratiile de colaborare dintre procesoare (trimite si/sau primeste date de
la un alt procesor,cu sau fara intermedierea memoriei fizice).
PUSH - transfera datele de la sursa in stiva de memorie interna a
procesorului.Ca rezultat al operatiei,datele din sursa vor fi arhivate
in varful stivei,iar pointerul de stiva va fi decrementat cu dimensiunea
datelor (SP=SP-tipul de data).Sursa poate fi o variabila de memorie,un
registru general sau de adresa sau o valoare imediata (byte,word,dword).
-38-
EXEMPLU: program assmb28;
uses WinCRT;
var nr1:word;
begin
asm
mov ax,77
push ax
pop bx
mov nr1,bx
end;
writeln('numarul preluat din stiva este: ',nr1);
end.
(vezi si POP)
POP - transfera datele din stiva de memorie,la destinatia specificata
(vezi exemplul de mai sus).Este operatia complementara pentru PUSH.Dupa
efectuarea operatiei,incrementeaza valoarea pointerului de stiva (SP)
cu o valoare egala cu tipul de data(SP=SP+tipul de data).Destinatia
datelor poate fi o variabila de memorie,un registru general sau un regis-
tru de adresa.In cazul operatiilor succesive,se aplica regula LIFO (last
in first out),care este valabila pentru toate operatiile asupra stivei.
EXEMPLU: program assmb29;
uses WinCRT;
var nr1,nr2,nr3:word;
begin
asm
push 0
mov ax,55
push ax
push 99
pop nr1
pop nr2
pop nr3
end;
writeln('Primul numar extras din stiva este: ',nr1);
writeln('Al doilea numar extras din stiva = ',nr2);
writeln('Al treilea numar extras din stiva = ',nr3);
end.
Observati ca numarul 0 care a fost primul numar introdus in stiva este
extras doar dupa a treia operatie POP,respectiv este ultimul numar
extras din stiva.Aceast regula determina ordinea in care se vor introduce
datele in stiva,atunci cand se efectueaza operatii succesive.Astfel,pentru
a ajunge la numarul zero,trebuiesc efectuate trei operatii de tip POP,in
care datele extrase fie se pierd ,fie vor fi salvate in variabile de me-
morie si registri si apoi vor fi reintroduse in stiva cu PUSH.Pentru a
evita operatiile complicate de reorganizare a stivei,este bine ca datele
sa fie introduse in stiva astfel incat sa poata fi extrase in ordinea in
care vor fi necesare pentru opratiile derulate.In acest scop,este bine
sa schematizati algoritmul de introducere si respectiv de extragere a
datelor,inainte de a trece la efectuarea operatiilor efective.In acest
mod,puteti economisi un numar mare de operatii inutile.
-39-
Pentru a determina gradul de ocupare a stivei,si pozitia actuala din
interiorul stivei se pot utiliza pointerul de stiva SP si pointerul spre
baza stivei BP.Pointerul spre baza stivei este constant si exprima in
acelasi timp si dimensiunea stivei.Diferenta dintre pointerul de stiva
si pointerul spre baza stivei exprima gradul de ocupare a stivei (se
mai numeste si deplasament intern in cadrul stivei).
EXEMPLU: program assmb30
uses WinCRT;
var nr1,nr2,nr3:word;
begin
asm
mov nr1,SP
push 77
push 55
push ax
push 19
mov nr2,SP
mov cx,BP
sub cx,SP
mov nr3,cx
end;
writeln('valoarea initiala a stivei este: ',nr1);
writeln('valoarea finala a stivei este: ',nr2);
writeln('deplasamentul in stiva este: ',nr3,' bytes');
end.
Stiva poate fi utilizata si in locul unor variabile de memorie,pentru
a putea efectua un numar oarecare de operatii succesive,fara sa mai fie
nevoie de o variabile auxiliare pentru pastrarea rezultatelor partiale.
Acest gen de operatii este util in situatiile de "memorie la limita".
EXEMPLU: program assmb31;
uses WinCRT;
var a,b,c:word;
begin
asm
push 77+39
pop a
add a,84
push a
pop b
add b,55
push b
pop c
end;
writeln('Valoarea finala este: ',c);
end.
In exemplul de mai sus,am utilizat stiva doar pentru valorile temporare.
Observati insa ca puteam efectua toate operatiile fara ajutorul nici unei
variabile de memorie,utilizand doar stiva si registrii de procesor.Acest
gen de operatii poate fi util in situatii limita din etapa de depanare
a programelor (stiva poate prelua si apoi returna un numar mare de valori
fara sa fie necesara nici o variabila de memorie).
-40-
Instructiunile pushf si popf sunt asemenatoare cu push si pop,dar sunt
utilizate pentru salvarea in stiva a registrului FLAGS si respectiv pentru
resetarea registrului FLAGS utilizand valorile arhivate in stiva.
PUSF - scade pointerul de stiva cu 2 bytes si salveaza word-ul cel mai
putin semnificativ din registrul FLAGS in stiva (low word).
POPF -reseteaza registrul FLAGS cu valoarea preluata din stiva si apoi
incrementeaza valoarea pointerului SP cu doi bytes(elibereaza stiva).
Acest gen de operatie este recomandabil atunci cand doriti sa reveniti la
o anumita configuratie a registrului FLAGS,dupa ce a-ti efectuat o serie
de operatii in care registrul FLAGS a fost modificat.
EXEMPLU: program assmb32;
uses WinCRT;
var nr1:word;
b1,b2:byte;
begin
asm
pushf
mov bx,-17
lahf
mov b1,ah
mov ah,0
sahf
mov bx,133
lahf
mov b2,ah
popf
end;
writeln('Valoarea registrului AH este: ',b1);
writeln('Valoarea registrului AH este: ',b2);
end.
In exemplul de mai sus,dupa ce am salvat registrul FLAGS,am transferat
in registrul bx,valoarea -17.Ca rezultat,datorita faptului ca -17 este
o valoare negativa,bitul de semn din registrul FLAGS,denumit SF (bitul 7)
a primit valoarea 1.Pentru a verifica acest fapt ,am apelat instructiunea
lahf,care copiaza SF,ZF,AF,PF si CF din FLAGS in AH (mai exact in bitii
7,6,4,2 si 0 in valoarea de 1 byte a registrului AH).Apoi am copiat
valoarea din registrul AH in variabila b1.La afisarea acestei variabile,
se returneaza valoarea 131.Numarul zecimal 131,scris binar este:
1000 0011
adica,citind de la coada la cap,bitul 0 este 1,bitul 1 este 1,bitul 2 este
0....bitul 7 este 1(deci SF este setat 1-rezulta ca numarul este negativ).
In continuare am adus la zero registrul AH si apoi am salvat aceste valori
in registrul FLAGS cu ajutorul instructiunii sahf.Ca rezultat registrul
FLAGS va avea configuratia: 0000 0000.Apoi am salvat in registrul bx o
valoare pozitiva oarecare si am preluat din nou registrul AH in variabila
b2.La afisare,variabila b2 returneaza 2,care in reprezentare binara este:
0000 0010
adica toti biti de stare(0,2,4,6 si 7) sunt zero (bitul 1 nu conteaza).
La final am restaurat valoarea initiala a registrului FLAGS cu valorile
preluate din stiva,cu ajutorul instructiunii popf.
Verificati valoarea registrului FLAGS,dupa diverse operatii aritmetice.
-41-
INSTRUCTIUNI PENTRU CONTROLUL REGISTRULUI FLAGS
-sunt destinate pentru a modifica direct valoarea bitilor de stare din
registrul FLAGS.Instructiunile din aceasta categorie sunt:pushf,popf,
stc,clc,std,cld,sti,cli,lahf si sahf.Instructiunile de acest tip nu au
operanzi.Pushf si popf au fost deja prezemtate (vezi exemplul anterior).
LAHF copiaza flag-urile SF ,ZF,AF,PF si CF in registrul AH,ocupand bitii
de stare 0,2,4,6 si 7.
SAHF efectueaza operatia inversa,respectiv salveaza valoarea bitilor de
stare 0,2,4,6 si 7 in flag-urile CF,PF,AF,ZF si ZF din registrul FLAGS.
EXEMPLU: program asasmb33;
uses WinCRT;
var b1,b2:byte;
begin
asm
mov ah,131
sahf
mov bx,55
lahf
mov b1,ah
add bx,77
test bx,ax
lahf
mov b2,ah
end;
writeln('registrul AH este: ',b1);
writeln('registrul AH este: ',b2);
end.
Valorile returnate sunt: 131 ,adica 1000 0011 si 22,adica 0001 0110 .
STC seteaza flagul CF la valoarea 1 iar CLC seteaza flagul CF la zero.
STD seteaza flagul DF la valoarea 1 iar CLD seteaza flagul DF la zero.
STI seteaza flagul IF la valoarea 1 iar CLI seteaza flagul IF la sero.
EXEMPLU: program assmb34;
uses WinCRT,WinProcs;
var nr1:word;
b1,b2:byte;
begin
asm
mov ah,0
sahf
stc
std
sti
pushf
pop nr1
end;
b1:=HIBYTE(nr1);
b2:=LOBYTE(nr1);
writeln('byte-ul superior 8-15 din FLAGS este: ',b1);
writeln('byte-ul inferior 0-7 din FLAGS este: ',b2);
end.
Valorile returnate sunt 6 si 3.Deci FLAG este(6:3),adica 00000110 00000011
-42-
Alte instructiuni pentru registrul FLAGS sunt cmc,care seteaza flagul
CF la valoarea complementara (0 daca este 1 sau 1 daca este 0) si res-
pectiv instructiunea TEST destinatie,sursa care efectueaza operatia
logica AND asupra flag-urilor OF,SF,ZF,PF si CF.
Registrul FLAGS si instructiunile care opereaza asupra sa,au un rol
important mai ales pentru functiile si utilitarele destinate pentru ana-
liza si depanarea programelor.Valoarea bitilor de stare din registrul
FLAGS detecteaza nivelul de program la care s-a atrecurat o eroare de
calcul,o valoare in afara domeniului de reprezentare (overflow) sau
o eroare de semn,etc.
Registrul FLAGS este utilizat si pentru programarea rutinelor auto-
mate de setare ale unor functii,pentru utilitarele plug-and-play etc.
Pentru a intelege cat mai usor operatiile efectuate ,verificati de fiecare
data valorile returnate,pentru modul lor de reprezentare binara.
Pentru o reprezentare mai intuitiva,va puteti imagina faptul ca
FLAGS este un procesor cu 16 linii de adresa iar dintre acestea,liniile
0,2,4,6,7,8,9,10 si 11 formeaza flag-urile CF,FP,AF,ZF,SF,TF,IF,DF si OF.
Pentru orice operatie neclara,desenati pe o hartie cu patratele semnalul
binar,la intrarea si la iesirea din procesor.
EXEMPLU:
OPERATII
INTRARE DATE
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
___|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|___ AH=255
| CF PF AF ZF SF TF IF DF OF | SAHF
| | STD
| | STI
| CF PF AF ZF SF TF IF DF OF |
|___________________________________________________|
| | | | | | | | | | | | | | | |
1 1 1 1 1 1 1 1 0 1 1 0 0 0 0 0
IESIRE DATE
Prin cele trei operatii de mai sus,am setat tot byte-ul inferior la va-
loarea 1 (255 binar este 1111 1111 iar SAHF incarca tot byte-ul inferior)
respectiv STD si STI seteaza bitii 9 si 10 la valoarea 1 .
INSTRUCTIUNI PENTRU CONVERSIA DATELOR
Permit schimbarea tipului de data.Pentru procesorul 8086 se pot apela
instructiunile cbw si cwd,care convertesc un byte intr-un word si respec-
tiv un word intr-un dword.Procesoarele 80386 accepta si instructiunile
cdq (dword in qword) si movsx(care conversteste un btye direct in dword).
Se utilizeaza pentru a realiza compatibilitatea dintre serii de date ar-
hivate in format diferit(Exemplu: pentru a utiliza o banca de date arhi-
vate in format de 32 de biti,cu un program care lucreaza pe 64 de biti).
CBW -converteste o data de tip byte intr-o data de tip word,in registrul
AX.Ca rezultat,data de tip word va mentine valoarea din registrul AL,
iar AH va fi "adus la zero"(se sterg datele din AH).
-43-
EXEMPLU: program assmb35;
uses WinCRT;
var b1:byte;
w1:word;
begin
b1:=33;
asm
mov AL,b1
mob AH,22
cbw
mov w1,AX
mov b1,AH
end;
writeln('dupa conversie numarul rezultat este: ',w1);
writeln('iar registrul AH este: ',b1);
end.
Practic,registrul AL a fost "extins" la intregul registru AX.
(EXEMPLU: 0001 0110 devine 0000 0000 0001 0110 )
CWD - converteste o valoare de tip word,la o valoare de tip dword(adica
16 biti la 32 de biti).Rezultatul va ocupa ambii registrii AX si DX
si va pastra valoarea registrului AX in timp ce DX va fi "adus la
zero" (datele din DX se sterg).
EXEMPLU: program assmb36;
uses WinCRT;
var dw1,dw2:word;
begin
asm
mov AX,299
mov DX,555
cwd
mov dw1,AX
mov dw2,DX
end;
writeln('valoarea registrului AX este: ',dw1);
writeln('valoarea registrului DX este: ',dw2);
end.
Pentru a nu pierde date in timpul conversiei,este bine ca datele din
registrul auxiliar (AH si respectiv DX ) sa fie valorificate inaintea
operatiei de conversie.
Conversia se poate face si prin extensia semnului,caz in care registrul
auxiliar va contine semnul numarului.Exemplu: AH in loc sa fie "adus la
zero" va mentine semnul numarului din AL,practic,fiecare bit va contine
valoarea flag-ului de semn,adica bitul 7 din registrul FLAGS.In acest caz,
registrul auxiliar va fi umplut fie cu 0 fie cu 1.
INSTRUCTIUNI ARITMETICE BINARE
Efectueaza operatii aritmetice simple de adunare ,scadere,inmultire si
impartire.Instructiunile din acest grup sunt: add,adc,inc,dec,sub,sbb,
cmp,neg,xadd,mul,imul,div si idiv.Toate aceste instructiuni opereaza
atat cu registri si valori imediate cat si cu variabile de memorie,dar
cel putin unul dintre operanzi trebuie sa nu fie o variabila de memorie.
-44-
ADD d,s -adauga valoarea din operandul sursa (s) la valoarea din operandul
de destinatie (d).Ca rezultat,operandul de destinatie (d) va contine
suma valorilor din cei doi operanzi.Daca valoarea rezultata este
in afara domeniului de reprezentare,seteaza automat flag-ul CF.
Nu se pot efectua operatii intre doua variabile de memorie,in rest
se pot face toate combinatiile intre registri,variabile si constante.
EXEMPLU: program assmb37;
uses WinCRT;
var nr1:word;
begin
asm
mov ax,33
mov bx,57
add ax,-19
add bx,-43
add ax,bx
mov nr1,ax
add nr1,23+46
end;
writeln('rezultatul final este: ',nr1);
end.
ADC d,s -este operatia "add with carry".Este identica cu ADD,dar adauga
la suma celor doi operanzi si valoarea flag-ului CF (carry flag).Ca
rezultat,atunci cand flagul CF este setat (1),rezultatul va fi suma
celor doi operanzi plus 1 (Exemplu: 1 +1 =3):
EXEMPLU: program assmb38;
uses WinCRT;
var nr1:word;
begin
asm
mov ax,1
stc
adc ax,1
mov nr1,ax
end;
writeln('rezultatul este: ',nr1);
end.
Rezultatul operatiei este influentat da valoarea flagului CF.Prin combi-
narea unui numar oarecare de instructiuni ADC la care sursa are valoarea
zero,se pot obtine valori diferite,in functie de setarea flagului CF.
Acest gen de algoritimi se pot utiliza pentru a obtine un set de variante
in functie da valoarea flag-ului.Se utilizeaza mai ales pentru programele
de depanare si setare automata.
INC d -adauga 1 la valoarea de destinatie (d).Aceasta instructiune nu
afecteaza flag-ul CF (chiar daca se depaseste setul de valori repre-
zentabile).Destinatia poate fi un registru general sau o variabila de
memorie iar valoarea din operandul de destinatie poate fi de tip
byte,word sau dword.Se utilizeaza mai ales in interiorul unor bucle
de repetitie,in care valoarea creste progresiv pana cand se ajunge la
pragul de iesire din bucla (Exemplu: verificarea succesiva a unui set
de valori,fata de o conditie fixa).
-45-
EXEMPLU: program assmb39;
uses WinCRT;
var nr1:word;
begin
while nr1 < 20 do
asm
mov ax,nr1
inc ax
mov nr1,ax
end;
writeln('rezultatul este: ',nr1);
end.
SUB d,s -este operatia inversa fata de ADD.Scade valoarea sursei din va-
loarea operandului de destinatie.Daca rezultatul necesita "un impru-
mut" (este mai mic decat zero),seteaza flagul CF (la valoarea 1).
Regulile sunt identice cu cele de la ADD(nu se pot efectua operatii
intre doua variabile de memorie).Efectueaza o scadere simpla:
EXEMPLU: program assmb40;
uses WinCRT;
var nr1:word;
begin
asm
mov ax,33
sub ax,32
mov nr1,ax
end;
writeln('rezultatul este: ',nr1);
end.
SBB d,s -este operatia "subbstract with borrow".Este identica cu SUB dar
scade din destinatie si valoarea flag-ului CF.Daca CF este 1,rezul-
tatul obtinut va fi mai mic cu o unitate decat cel returnat de SUB.
EXEMPLU: program assmb41;
uses WinCRT;
var nr1:word
begin
asm
Dostları ilə paylaş: