Sunteți pe pagina 1din 42

Introducere n limbajul de asamblare

Ne vom referi n cele ce urmeaz la familia de microprocesoare intitulat


iAPx86 ce stau la baza calculatoarelor IBM PC, ncepnd de la procesoarele 8088 i
8086, continund cu 80286, 80386, 80486, Pentium, .a.m.d. Procesorul 8086
reprezint, de fapt, baza familiei ce este cunoscut pe scurt sub denumirea de familia
microprocesoarelor x86. De aceea se vor face referiri n continuare la aceast
arhitectur (8086).
Elementele arhitecturale de baz ale microprocesorului

Figura 1. Regitrii de uz general acumulator,


index de baz, contor i de date

Regitrii microprocesorului
Regitrii (sau registrele) microprocesorului reprezint locaii de memorie
speciale aflate direct pe cip; din aceast cauz reprezint cel mai rapid tip de
memorie. Alt lucru deosebit legat de regitri este faptul c fiecare dintre acetia au un
scop bine precizat, oferind anumite funcionaliti speciale, unice. Exist patru mari

categorii de regitri: regitrii de uz general, registrul indicatorilor de stare (flags),


regitrii de segment i registrul pointer de instruciune.
Regitrii de uz general
Regitrii de uz general (vezi figura 1 i figura 2) sunt implicai n operarea
majoritii instruciunilor, drept operanzi surs sau destinaie pentru calcule, copieri
de date, pointeri la locaii de memorie sau cu rol de contorizare. Fiecare dintre cei 8
regitri de uz general AX, BX, CX, DX, SP, BP, DI,SI sunt regitri pe 16 bii pentru
microprocesorul 8086, iar de la procesorul 80386 ncoace au devenit regitri pe 32 de
bii, denumii, respectiv: EAX, EBX, ECX, EDX, ESP, EBP, EDI, ESI (litera E
provine de la Extended extins n englez). Mai mult, cei mai puin semnificativi 8 bii
ai regitrilor AX, BX, CX, DX formeaz respectiv regitrii AL, BL, CL, DL (litera L
provine de la Low jos n englez), iar cei mai semnificativi 8 bii ai acelorai regitri
formeaz regitrii AH, BH, CH, DH (litera H provine de la High nalt n englez)
(figura 1).

Figura 2. Regitrii de uz general index i pointer

Ne vom concentra n continuare atenia asupra regitrilor generali pe 16 bii;


fiecare dintre acetia poate stoca o valoare pe 16 bii, poate fi folosit pentru stocarea
unei valori din memorie sau poate fi utilizat pentru operaii aritmetice i logice. Spre
exemplu, urmtoarele instruciuni:

MOV BX, 2
MOV DX, 3

ADD BX, DX

ncarc valoarea 2 n registrul BX, valoarea 3 n registrul DX, adun cele dou
valori iar rezultatul (5) este memorat n registrul BX. n exemplul anterior putem
utiliza oricare dintre regitrii de uz general n locul regitrilor BX i DX. n afara
proprietii de a stoca valori i de a folosi drept operanzi surs sau destinaie pentru
instruciunile de manipulare a datelor, fiecare dintre cei 8 regitri de uz general au
propria personalitate. Vom vedea n continuare care sunt caracteristicile specifice
fiecruia dintre regitrii de uz general.
Registrul AX (EAX)
Registrul AX (EAX) este denumit i registrul acumulator, fiind principalul
registru de uz general utilizat pentru operaii aritmetice, logice i de deplasare de
date. Totdeauna operaiile de nmulire i mprire presupun implicarea registrului
AX. Unele dintre instruciuni sunt optimizate pentru a se executa mai rapid atunci
cnd este folosit AX. n plus, registrul AX este folosit i pentru toate transferurile de
date de la/ctre porturile de Intrare/Ieire. Poate fi accesat pe poriuni de 8, 16 sau
32 de bii, fiind referit drept AL (cei mai puin semnificativi 8 bii din AX), AH (cei
mai semnificativi 8 bii din AX), AX (16 bii) sau EAX (32 de bii). Prezentm n
continuare alte cteva exemple de instruciuni ce utilizeaz registrul AX. De remarcat
este faptul c transferurile de date se fac pentru instruciunile (denumite i mnemonice)
Intel de la dreapta spre stnga, exact invers dect la Motorola (vom vedea i alt
exemplu asemntor la scrierea datelor n memorie sub format diferit la Motorola
fa de Intel), unde transferul se face de la stnga la dreapta.
Instruciunea: MOV AX, 1234H ncarc valoarea 1234H (4660 n zecimal) n
registrul acumulator AX. Dup cum spuneam, cei mai puini semnificativi 8 bii ai
registrului AX sunt identificai de AL (A-Low) iar cei mai semnificativi 8 bii ai
aceluiai registru sunt identificai ca fiind AH (A-High). Acest lucru este utilizat
pentru a lucra cu date pe un octet, permind ca registrul AX s fie folosit pe postul a
doi regitri separai (AH i AL). Aceeai regul este valabil i pentru regitrii de uz
general BX, CX, DX. Urmtoarele trei instruciuni seteaz registrul AH cu valoarea
1, incrementeaz cu 1 aceast valoare i apoi o copiaz n registrul AL:
MOV AH, 1
INC AH
MOV AL, AH
Valoarea final a registrului AX va fi 22 (AH = AL = 2).
Registrul BX (EBX)

Registrul BX (Base), sau registrul de baz poate stoca adrese pentru a face
referire la diverse structuri de date, cum ar fi vectorii stocai n memorie. O valoare
reprezentat pe 16 bii stocat n registrul BX poate fi utilizat ca fiind o poriune din
adresa unei locaii de memorie ce va fi accesat. Spre exemplu, urmtoarele
instruciuni ncarc registrul AH cu valoarea din memorie de la adresa 21.
MOV
MOV
MOV
MOV

AX, 0
DS, AX
BX, 21
AH, [ BX ]

Se observ c am ncrcat valoarea 0 n registrul DS nainte de a accesa locaia


de memorie referit de registrul BX. Acest lucru este datorat segmentrii memoriei
(segmentare discutat mai n detaliu n seciunea consacrat regitrilor de segment);
implicit, atunci cnd este folosit ca pointer de memorie, BX face referire relativ la
registrul de segment DS (adresa la care face referire este o adres relativ la adresa de
segment coninut n registrul DS).
Registrul CX (ECX)
Specializarea registrului CX (Counter) este numrarea; de aceea, el se numete
i registrul contor. De asemenea, registrul CX joac un rol special atunci cnd se
folosete instruciunea LOOP. Rolul de contor al registrului CX se observ imediat
din exemplul urmtor:
MOV CX, 5
start:

<instruciuni ce se vor executa de 5 ori>

SUB CX, 1
JNZ start
Deoarece valoarea iniial a lui CX este 5, instruciunile cuprinse ntre eticheta
start i instruciunea JNZ se vor executa de 5 ori (pn cnd registrul CX devine 0).
Instruciunea SUB CX, 1 decrementeaz registrul CX cu valoarea 1 iar instruciunea
JNZ start determin saltul napoi la eticheta start dac CX nu are valoarea 0. n
limbajul microprocesorului exist i o instruciune special legat de ciclare. Aceasta
este instruciunea LOOP, care este folosit n combinaie cu registrul CX. Liniile de
cod urmtoare sunt echivalente cu cele anterioare, dar aici se utilizeaz instruxiunea
LOOP:

MOV CX, 5
start:

<instruciuni ce se vor executa de 5 ori>

LOOP start
Se observ c instruciunea LOOP este folosit n locul celor dou instruciuni
SUB i JNZ anterioare; LOOP decrementeaz automat registrul CX cu 1 i execut
saltul la eticheta specificat (start) dac CX este diferit de zero, totul ntr-o singur
instruciune.
Registrul DX (EDX)
Registrul de uz general DX (Data register), denumit i registrul de date, poate
fi folosit n cazul transferurilor de date Intrare/Ieire sau atunci cnd are loc o
operaie de nmulire sau de mprire. Instruciunea IN AL, DX copiaz o valoare
de tip Byte dintr-un port de intrare, a crui adres se afl n registrul DX.
Urmtoarele instruciuni determin scrierea valorii 101 n portul I/O 1002:
...
MOV AL, 101
MOV DX, 1002
OUT DX, AL

Referitor la operaiile de nmulire i mprire, atunci cnd mprim un


numr pe 32 de bii la un numr pe 16 bii, cei mai semnificativi 16 bii ai
dempritului trebuie s fie n DX. Dup mprire, restul mpririi se va afla n DX.
Cei mai puin semnificativi 16 bii ai dempritului trebuie s fie n AX iar ctul
mpririi va fi n AX. La nmulire, atunci cnd se nmulesc dou numere pe 16 bii,
cei mai semnificativi 16 bii ai produsului vor fi stocai n DX iar cei mai puin
semnificativi 16 bii n registrul AX.
Registrul SI
Registrul SI (Source Index) poate fi folosit, ca i BX, pentru a referi adrese de
memorie. De exemplu, secvena de instruciuni urmtoare:
MOV
MOV
MOV
MOV

AX, 0
DS, AX
SI, 33
AL, [ SI ]

ncarc valoarea (pe 8 bii) din memorie de la adresa 33 n registrul AL.


Registrul SI este, de asemenea, foarte folositor atunci cnd este utilizat n legtur cu
instruciunile dedicate tipului string (ir de caractere). Secvena urmtoare :
CLD
MOV AX, 0
MOV DS, AX
MOV SI, 33
LODSB
nu numai c ncarc registrul AX cu valoarea de la adresa de memorie referit
de registrul SI, dar adun, de asemenea, valoarea 1 la SI. Acest lucru este deosebit de
eficient atunci cnd se acceseaz secvenial o serie de locaii de memorie, cum ar fi
irurile de caractere. Instruciunile de tip string se pot repeta de mai multe ori, astfel
nct o singur instruciune poate avea ca efect sute sau mii de operaii.
Registrul DI
Registrul DI (Destination Index) este utilizat n mod asemntor registrului SI.
n secvena de instruciuni urmtoare:
MOV
MOV
MOV
ADD

AX, 0
DS, AX
DI, 1000
BL, [ DI ]

se adun la registrul BL valoarea pe 8 bii stocat la adresa 1000. Registrul DI


este puin diferit fa de registrul SI n cazul instruciunilor de tip string; dac SI este
ntotdeauna pe post de pointer surs de memorie, registrul DI servete drept pointer
destinaie de memorie. Mai mult, n cazul instruciunilor de tip string, registrul SI
adreseaz memoria relativ la registrul de segment DS, n timp ce DI conine referiri
la memorie relativ la registrul de segment ES. n cazul n care SI i DI sunt utilizai
cu alte instruciuni, ei fac referire la registrul de segment DS.
Registrul BP
Pentru a nelege mai bine rolul regitrilor BP i SP, a sosit momentul s
spunem cteva lucruri despre poriunea de memorie denumit stiv (n englez stack).
Stiva (vezi figura 3) reprezint o poriune special de locaii adiacente din memorie.
Aceasta este coninut n cadrul unui segment de memorie i identificat de un
selector de segment memorat n registrul SS (cu excepia cazului n care se folosete
modelul nesegmentat de memorie n care stiva poate fi localizat oriunde n spaiul
de adrese liniare al programului). Stiva este o poriune a memoriei unde valorile pot

fi stocate i accesate pe principul LIFO (Last In First Out), drept urmare ultima
valoare stocat n stiv este prima ce va fi citit din stiv. De regul, stiva este
utilizat la apelul unei proceduri sau la ntoarcerea dintr-un apel de procedur
(principalele instruciuni folosite sunt CALL i RET).

Figura 3. Structura stivei

Registrul pointer de baz, BP (Base Pointer) poate fi utilizat ca pointer de


memorie precum regitrii BX, SI i DI. Diferena este aceea c, dac BX, SI i DI
sunt utilizai n mod normal ca pointeri de memorie relativ la segmentul DS, registrul
BP face referire relativ la segmentul de stiv SS. Principiul este urmtorul: o
modalitate de a trece parametrii unei subrutine este aceea de a utiliza stiva (acest
lucru se ntmpl n mod obinuit n limbajele de nivel nalt, C sau Pascal, spre
exemplu). Dac stiva se afl n poriunea de memorie referit de registrul de segment
SS (Stack Segment), datele se afl n mod normal n segmentul de memorie referit de
ctre DS, registrul segment de date. Deoarece BX, SI i DI se refer la segmentul de
date, nu exist o modalitate eficient de a folosi regitrii BX, SI, DI pentru a face
referire la parametrii salvai n stiv din cauz c stiva este localizat ntr-un alt
segment de memorie. Registrul BP ofer rezolvarea acestei probleme asigurnd
adresarea n segmentul de stiv. Spre exemplu, instruciunile:
PUSH BP
MOV BP, SP
MOV AX, [ BP+4 ]

fac s se acceseze segmentul de stiv pentru a ncrca registrul AX cu primul


parametru trimis de un apel C unei rutine scrise n limbaj de asamblare. n concluzie,
registrul BP este conceput astfel nct s ofere suport pentru accesul la parametri,
variabile locale i alte necesiti legate de accesul la poriunea de stiv din memorie.
Registrul SP
Registrul SP (Stack Pointer), sau pointerul de stiv, reine de regul adresa de
deplasament a urmtorului element disponibil n cadrul segmentului de stiv. Acest
registru este, probabil, cel mai puin general dintre regitrii de uz general, deoarece
este dedicat mai tot timpul administrrii stivei.
Registrul BP face n fiecare clip referire la vrful stivei acest vrf al stivei
reprezint adresa locaiei de memorie n care va fi introdus urmtorul element n
stiv. Aciunea de a introduce un nou element n stiv se numete mpingere (n
englez push); de aceea, instruciunea respectiv poart numele de PUSH. n mod
asemntor, operaia de scoatere a unui element din vrful stivei poart, n englez,
numele de pop, iar instruciunea echivalent operaiei se numete POP. n figurile 3 i
4 sunt ilustrate modificrile survenite n coninutul stivei i al regitrilor SP, BX i
CX ca urmare a execuiei instruciunilor urmtoare (se presupune c registrul SP are
iniial valoarea 1000):
MOV BX, 9
PUSH BX
MOV CX, 10
PUSH CX
POP BX
POP CX

Figura 3. Modalitatea de funcionare a stivei dup execuia


primelor 4 instruciuni

Este permis stocarea valorilor n registrul SP precum i modificarea valorii


sale prin adunare sau scdere la fel ca i n cazul celorlali regitri de uz general;
totui, acest lucru nu este recomandat dac nu suntem foarte siguri de ceea ce facem.
Prin modificarea registrului SP, vom modifica adresa de memorie a vrfului stivei,
ceea ce poate avea efecte neprevzute, aceasta pentru c instruciunile PUSH i POP
nu reprezint unicele modaliti de utilizare a stivei. Indiferent dac apelm o
subrutin sau ne ntoarcem dintr-un astfel de apel de subrutin, fie procedur sau
funcie, n acest caz este folosit stiva. Unele resurse de sistem, precum tastatura sau
ceasul de sistem, pot folosi stiva n momentul trimiterii unei ntreruperi la
microprocesor. Acest lucru presupune c stiva este folosit continuu, deci dac se
modific registrul SP (adic adresa stivei), datele din noile locaii de memorie nu vor
mai fi cele corecte. n concluzie, registrul SP nu trebuie modificat n mod direct; el
este modificat automat n urma instruciunilor POP, PUSH, CALL, RET. Oricare
dintre ceilali regitri de uz general pot fi modificai n mod direct n orice moment.

Figura 4. Funcionarea stivei dup ultimile dou instruciuni POP

Registrul pointer de instruciuni (IP)


Registrul pointer de instruciuni (IP Instruction Pointer, vezi figura 5) este
folosit, ntotdeauna, pentru a stoca adresa urmtoarei instruciuni ce va fi executat
de ctre microprocesor. Pe msur ce o instruciune este executat, pointerul de
instruciune este incrementat i se va referi la urmtoarea adres de memorie (unde
este stocat urmtoarea instruciune ce va fi executat). De regul, instruciunea ce
urmeaz a fi executat se afl la adresa imediat urmtoare instruciunii ce a fost
executat, dar exist i cazuri speciale (rezultate fie din apelul unei subrutine prin
instruciunea CALL, fie prin ntoarcerea dintr-o subrutin, prin instruciunea RET).
Pointerul de instruciuni nu poate fi modificat sau citit n mod direct; doar
instruciuni speciale pot ncrca acest registru cu o nou valoare. Registrul pointer de
instruciune nu specific pe de-a ntregul adresa din memorie a urmtoarei
instruciuni ce va fi executat, din aceeai cauz a segmentrii memoriei. Pentru a
aduce o instruciune din memorie, registrul CS ofer o adres de baz iar registrul
pointer de instruciune indic adresa de deplasament plecnd de la aceast adres de
baz.

Figura 5. Regitrii de segment, pointerul de instruciuni i registrul


indicatorilor de stare

Registrul indicatorilor de stare (FLAGS)

Figura 6. Registrul indicatorilor de stare - detaliu

Registrul indicatorilor de stare (FLAGS) pe 16 bii conine informaii legate de


starea microprocesorului precum i de rezultatele ultimilor instruciuni executate. Un
indicator de stare (flag) este n sine o locaie de memorie de 1 bit ce indic starea
curent a microprocesorului i modalitatea sa de operare. Un indicator se spune c
este setat dac are valoarea 1 i nu este setat n caz contrar. Indicatorii de stare
se modific dup execuia unor instruciuni aritmetice sau logice. Exemple de
indicatori de stare (vezi figura 6):
- C (Carry) indic apariia unei cifre binare de transport n cazul unei adunri
sau mprumut n cazul unei scderi;
- O (Overflow) apare n urma unei operaii aritmetice. Dac este setat,
nseamn c rezultatul nu ncape n operandul destinaie;
- Z (Zero) indic faptul c rezultatul unei operaii aritmetice sau logice ste
zero;
- S (Sign) indic semnul rezultatului unei operaii aritmetice;
- D (Direction) cnd este zero, procesarea elementelor irului se face de la
adresa mai mic la cea mai mare, n caz contrar este invers;
- I (Interrupt) controleaz posibilitatea microprocesorului de a rspunde la
evenimente externe (apeluri de ntrerupere);
- T (Trap) este folosit de programele de depanare (de tip debugger), activnd
sau nu posibilitatea execuiei programului pas cu pas. Dac este setat, UCP

ntrerupe fiecare instruciune, lsnd programul depanator s executet


programul respectiv pas cu pas;
- A (Auxiliary carry) suport operaii n codul BCD. Majoritatea programelor
nu ofer suport pentru reprezentarea numerelor n acest format, de aceea se
utilizeaz foarte rar;
- P (Parity) este stetat n conformitate cu paritatea biilor cei mai puin
semnificativi ai unei operaii cu date. Astfel, dac rezultatul unei operaii
conine un numr par de bii 1, acest indicator este setat. Dac numrul de
bii 1 din rezultat este impar, atunci indicatorul PF este zero. Este folosit de
regul de programe de comunicaii, dar Intel a introdus acest indicator nu
pentru a ndeplini o anumit funcionalitate, ci pentru a asigura
compatibilitatea cu vechile microprocesoare ale familiei x86.
Regitrii de segment
Proprietile regitrilor de segment (vezi figura 5) sunt n strns legtur cu
noiunea de segmentare a memoriei. Premiza de la care se pleac este urmtoarea:
8086 este capabil s adreseze 1MB de memorie, astfel c sunt necesare adrese pe 20
de bii pentru a cuprinde toate locaiile din spaiul de 1 MB de memorie. Totui,
registrele utilizate sunt registre pe 16 bii, deci a trebuit s se gseasc o soluie
pentru aceast problem. Soluia gsit se numete segmentarea memoriei; n acest caz
memoria de 1MB este mprit n 16 segmente de cte 64 KB (16*64 KB = 1024
KB = 1 MB).
Noiunea de segmentare a memoriei presupune utilizarea unor adrese de
memorie formate din dou pri. Prima parte reprezint adresa segmentului iar cea
de-a doua poriune reprezint adresa de deplasament, sau offset-ul (figura 7).

Figura 7. Cele dou poriuni ale unei adrese segmentate

Fiecare pointer de memorie pe 16 bii este combinat cu coninutul unui


registru de segment pe 16 bii pentru a forma o adres complet pe 20 de bii.
Adresa de segment mpreun cu adresa de deplasament sunt combinate n felul
urmtor: valoarea de segment este deplasat la stnga cu 4 bii (nmulit cu 16 = 24)
i apoi adunat cu valoarea adresei de deplasament. Adresa astfel construit se
numete adres efectiv; fiind o adres pe 20 de bii poate accesa 220 octei de
memorie, adic 1 MB de memorie. Construirea unei adrese efective este prezentat
n figura 8.

Figura 8. Exemplu de calcul al adresei efective


Registrul CS acest registru face referire la nceputul blocului de 64 KB de
memorie n care se afl codul programului (segmentul de cod). Microprocesorul
8086 nu poate aduce alt instruciune pentru execuie dect cea definit de CS.
Registrul CS poate fi modificat de un numr de instruciuni, precum instruciuni de
salt, apel sau de ntoarcere. El nu poate fi ncrcat n mod direct cu o valoare, ci doar
prin intermediul unui alt registru general.
Registrul DS face referire ctre nceputul segmentului de date, unde se afl
mulimea de date cu care lucreaz programul aflat n execuie.
Registrul ES face referire la nceputul blocului de 64KB cunoscut sun
denumirea de extra-segment. Acesta nu este dedicat nici unui scop anume, fiind
disponibil pentru diverse aciuni. Uneori acesta poate fi folosit pentru creearea unui
bloc de memorie de 64 KB adiional pentru date. Acest extra-segment lucreaz
foarte bine n cazul instruciunilor de tip STRING. Toate instruciunile de tip
STRING ce scriu n memorie folosesc adresarea ES : DI ca adres de memorie.
Registrul SS face referire la nceputul segmentului de stiv, care este blocul
de 64 KB unde se afl stiva. Toate instruciunile ce folosesc implicit registrul SP
(instruciunile POP, PUSH, CALL, RET) lucreaz n segmentul de stiv deoarece
registrul SP este capabil s adreseze memoria doar n segmentul de stiv.

Formatul general al unei instruciuni n limbaj de asamblare


O linie de cod scris n limbaj de asamblare are urmtorul format general:
<nume> <instructiune/directiva> <operanzi> <;comentariu>
unde:
<nume> - reprezint un nume simbolic opional;
<instructiune/directiva> - reprezint mnemonica (numele) unei
instruciuni sau a unei directive;
<operanzi> - reprezint o combinaie de unul, doi sau mai muli
operanzi (sau chiar nici unul), care pot fi constante, referine de memorie,
referine de regitri, iruri de caractere, n funcie de structura particular a
instruciunii;
<;comentariu> - reprezint un comentariu opional ce poate fi plasat
dup caracterul ; pn la sfritul liniei respective de cod.
Nume de variabile i etichete
Numele folosite ntr-un program scris n limbaj de asamblare pot identifica
variabile numerice, variabile ir de caractere, locaii de memorie sau etichete. Spre
exemplu, urmtoarea secven de cod, care calculeaz valoarea lui trei factorial
(3!=1x2x3=6) cuprinde cteva nume de variabile i etichete:
.MODEL small
.STACK 200h
.DATA
Valoare_Factorial DW ?
Factorial DW ?
.CODE
Trei_Factorial PROC
MOV ax, @data
MOV ds, ax
MOV [Valoare_Factorial], 1
MOV [Factorial], 2
MOV cx, 2
Ciclare:
MOV ax, [Valoare_Factorial]
MUL [Factorial]
MOV [Valoare_Factorial], ax
INC [Factorial]
LOOP Ciclare

RET
Trei_Factorial ENDP
END
Numele Valoare_Factorial i Factorial sunt utilizate pentru definirea a dou
variabile de tip word (pe 16 bii), Trei_Factorial identific numele procedurii
(subrutinei) ce conine codul pentru calculul factorialului, permind apelul su din
alt parte a programului. Ciclare reprezint un nume de etichet, identificnd adresa
instruciunii MOV ax, [Valoare_Factorial], astfel nct instruciunea LOOP folosit
mai jos s poat face un salt napoi la aceast instruciune. Numele de variabile pot
conine urmtoarele caractere: literele a-z i A-Z, cifrele de la 0-9 precum i
caracterele speciale _ (underscore liniu de subliniere), @ (at n englez citit i a
rond sau coad de maimu), $ i ?. Se poate folosi si caracterul punct (.) drept
prim caracter al numelui unei etichete. Cifrele 0-9 nu pot fi utilizate pe prima poziie
a numelui; de asemenea, nu pot fi folosite nume care s conin un singur caracter $
sau ?. Fiecare nume poate fi definit o singur dat (numele sunt unice) i pot fi utilizate
ca operanzi de oricte ori se dorete ntr-un program. Un nume poate s apar ntrun program singur pe o linie (linia respectiv nu mai conine alt instruciune sau
directiv). n acest caz, valoarea numelui este dat de adresa instruciunii sau
directivei de pe linia urmtoare din program. De exemplu, n secvena urmtoare:
...
JMP scadere
...
scadere:
SUB AX, CX
...
urmtoarea instruciune care va fi executat dup instruciunea JMP scadere
va fi instruciunea SUB AX, CX. Exemplul anterior este echivalent cu secvena:
...
JMP scadere
...
scadere: SUB AX, CX
...
Exist unele avantaje atunci cnd scriem instruciunile pe linii separate. n
primul rnd, atunci cnd scriem un nume de etichet pe o singur linie, este mai uor
s folosim nume lungi de etichete fr a strica forma programului scris n limbaj de
asamblare. n al doilea rnd, este mai uor s adugm ulterior o nou instruciune n
dreptul etichetei dac aceasta nu este scris pe aceeai linie cu instruciunea.
Numele variabilelor sau etichetelor folosite ntr-un program nu trebuie s se
confunde cu numele rezervate de asamblor, cum ar fi numele de directive i
instruciuni, numele regitrilor, etc. De exemplu, o declaraie de genul:

...
ax DW 0
BYTE:
...
nu poate fi acceptat, deoarece AX este numele registrului acumulator, AX, iar
BYTE reprezint un cuvnt cheie rezervat.
Orice nume de etichet ce apare pe o linie fr instruciuni sau apare pe o linie
cu instruciuni trebuie s aib semnul : dup numele ei. Tototdat, se ncearc s se
dea un nume sugestiv etichetelor din program. Fie urmtorul exemplu:
...
CMP AL, a
JB Nu_este_litera_mica
CMP AL, z
JA Nu_este_litera_mica
SUB AL, 20H
; se transforma in litera mare
Nu_este_litera_mica:

comparativ cu:
...
CMP AL, a
JB x5
CMP AL, z
JA x5
SUB AL, 20H
x5:

; se transforma in litera mare

Dac n primul caz am folosit un nume sugestiv de etichet


(Nu_este_litera_mica), n cazul al doilea, identic din punct de vedere al
funcionalitii cu primul, eticheta a fost denumit x5, absolut nesugestiv!

Observaie:

Limbajul de asamblare nu este case sensitive. Aceasta semnific faptul c, ntr-un


program scris n limbaj de asamblare, numele de variabile, etichete, instruciuni,
directive, mnemonice, etc., pot fi scrise att cu litere mari ct i cu litere mici,
nefcndu-se diferena ntre ele (Nu_este_litera_mica este acelai lucru cu
nu_este_litera_mica sau Nu_Este_Litera_Mica, etc.).

Directive de segment simplificate


Datorit faptului c regitrii microprocesorului 8086 sunt regitri pe 16 bii, sa impus folosirea unor segmente de memorie de cte 64Ko (maxim ct se poate
adresa avnd la dispoziie 16 bii - 64Ko=2^16=65536). ntr-un program scris n
limbaj de asamblare (vom folosi n continuare prescurtarea ASM) exist trei
segmente: segmentul de cod, segmentul de date i segmentul de stiv.
Directivele de segment (fie sub form standard, fie sub form simplificat)
sunt necesare n orice program scris n limbaj de asamblare pentru a defini i
controla utilizarea segmentelor iar directiva END este folosit ntotdeauna pentru a
ncheia codul programului.
Exemple de directive de segment simplificate sunt:
.STACK
.CODE
.DATA
.MODEL
DOSSEG
END
.STACK,.CODE,.DATA definesc, respectiv, segmentele de stiv, de cod i de
date.
De exemplu, .STACK 200H definete o stiv de 512 octei (n ASM valorile
ce sunt ncheiate cu litera H semnific faptul c este vorba despre hexazecimal). O
astfel de valoare pentru stiv este suficient n mod normal; unele programe, ns
(ndeosebi cele recursive) pot necesita dimensiuni mai mari ale stivei.
Directiva .CODE marcheaz nceputul segmentului de cod.
Directiva .DATA marcheaz nceputul segmentului de date, adic locul n care
vom plasa variabilele de memorie. Reprezentativ aici este faptul c trebuie ncrcat n
mod explicit registrul de segment DS cu valoarea "@data" naintea accesrii locaiilor
de memorie n segmentul definit de .DATA. Avnd n vedere c un registru de
segment poate fi ncrcat fie dintr-un registru general fie dintr-o locaie de memorie
dar nu poate fi ncrcat direct cu o constant, registrul de segment DS este ncrcat
n general printr-o secven de 2 instruciuni:
...
mov ax, @data
mov ds, ax
...
(se poate folosi i alt registru general n locul lui AX).

Secvena anterioar semnific faptul c DS se va referi ctre segmentul de date


ce ncepe cu directiva .DATA.
Considerm n continuare un exemplu de program ce afieaz textul memorat
n DataString pe ecran:
;Program p01.asm
.MODEL small
.STACK 200H
.DATA

;se specific modelul de memorie SMALL


;se definete o stiv de 512 octei
;se specific nceputul segmentului de
;date
DataString DB 'Hello!$' ;se
definete
variabila
;DataString, iniializat cu valoarea
;"Hello!"
.CODE
;nceputul
segmentului
de
cod
al
;programului
ProgramStart:
;orice program are o etichet de
;nceput
mov bx,@data
;secvena ce seteaz registrul DS s
;fac referire la segmentul de date ce
;ncepe cu .DATA
mov ds,bx
mov dx, OFFSET DataString ;se ncarc n DX adresa
;variabilei DataString
mov ah,09
;codul funciei DOS de afiare a unui
;string
int 21H
;apelul DOS de afiare a string-ului
mov ah, 4cH
;codul funciei DOS de terminare a
;programului
int 21H
;apelul DOS de terminare a programului
END ProgramStart
;directiva de terminare a codului
;programului

Explicaii:
1. Se pot introduce comentarii ntr-un program ASM prin folosirea ";". Tot ce
urmeaz dup ";" i pn la sfritul liniei este considerat comentariu.
2. Nu are importan dac programul este scris folosind litere mari sau mici
(nu este "case sensitive").
3. Fr cele dou instruciuni care seteaz registrul DS ctre segmentul definit
de .DATA, funcia de afiare a string-ului nu ar fi funcionat cum trebuie. Variabila
DataString se afl n segmentul .DATA i nu poate fi accesat dac DS nu este
poziionat ctre acest segment. Acest lucru se explic n modul urmtor: atunci cnd
facem apelul DOS de afiare a unui string, trebuie s parcurgem ntreaga adres de
tipul segment:offset a string-ului n DS:DX. De aceea, de abia dup ce am ncrcat
DS cu segmentul .DATA i DX cu adresa (offset-ul) lui DataString avem o referin
complet segment:offset ctre DataString.

Observaii.
Nu trebuie s ncrcm n mod explicit registrul de segment CS deoarece
DOS face acest lucru automat n momentul cnd rulm un program. Astfel, dac CS
nu ar fi deja setat la momentul execuiei primei instruciuni din program, procesorul
nu ar ti unde s gseasc instruciunea i programul nu ar rula niciodat. n mod
asemntor, registrul de segment SS este setat de DOS nainte de execuia
programului i de regul rmne nemodificat pe perioada execuiei programului.
Cu registrul de segment DS lucrurile stau altfel. n timp ce registrul CS se
refer la intruciuni (cod), SS se refer ("pointeaz") la stiv, DS "pointeaz" la date.
Programele nu manipuleaz direct instruciuni sau stive dar au de-a face n mod
direct cu date. De asemenea, programele vor acces la date situate n segmente diferite
n orice moment. Se poate dori ncrcarea n DS a unui segment, accesarea datelor
din acel segment i apoi ncrcarea lui DS cu un alt segment pentru a accesa un bloc
diferit de date. n programe mici sau medii nu vom avea nevoie de mai mult de un
segment de date dar programe mai complexe folosesc deseori segmente de date
multiple.
Urmtorul program va afia un caracter pe ecran, folosind ncrcarea
registrului ES n locul lui DS.
;Program p02.asm
.MODEL small
.STACK 200H
.DATA
OutputChar DB 'B'
.CODE
ProgramStart:
mov dx, @data
mov es, dx
mov
mov
mov
int
mov
int
END

;definirea variabilei OutputChar


;iniializat cu valoarea "B"

;spre deosebire de programul anterior,


se folosete ES pentru specificarea
segmentului de date
bx, offset OutputChar
;se ncarc BX cu adresa
;variabilei OutputChar
dl, es:[bx]
;se ncarc AL cu valoarea de la
;adresa explicit es:[bx]
;(adresare indexat)
ah,02
;codul funciei DOS de afiare a
;unui caracter
21H
;apelul DOS de execuie a afirii
ah, 4cH
;codul funciei DOS de terminare a
;programului
21H
;apelul DOS de terminare a programului
ProgramStart
;directiva de terminare a codului
;programului

DOSSEG este directiva ce face ca segmentele dintr-un program s fie grupate


conform conveniilor Microsoft de adresare a segmentelor.
Directiva .MODEL
Este directiva ce specific modelul de memorie pentru un program ASM ce
folosete directive de segment simplificate.
Definiii: "near" nseamn adresa (offset-ul) pe 16 bii din cadrul aceluiai
segment, n timp ce "far" nseamn o adres complet de tip segment:offset, din
cadrul altui segment dect cel curent.
Modelele de memorie ce se pot specifica prin intermediul directivei .MODEL
sunt:
- tiny - att codul ct i datele programului ncap n acelai segment de 64Ko.
Att codul ct i datele sunt de tip near.
- small - codul programului trebuie s fie ntr-un singur segment de 64Ko i
datele ntr-un bloc separat de 64Ko; codul i datele sunt near
- medium - codul programului poate fi mai mare dect 64Ko dar datele
trebuie s fie ntr-un singur segment de 64 Ko. Codul este far, datele sunt near.
- compact - codul programului poate fi ntr-un singur segment, datele pot fi
mai mari de 64 Ko. Codul este near, datele sunt far.
- large - att codul ct i datele pot depi 64Ko, dar nici un masiv de date nu
poate depi 64 Ko. Att codul ct i datele sunt far.
- huge - att codul ct i datele pot depi 64Ko i masivele de date pot
depi 64 Ko. Att codul ct i datele sunt far. Pointerii la elementele dintr-un masiv
sunt far.
n continuare sunt prezentate cteva exemple legate de modalitile de
declarare a variabilelor i de adresare a memoriei.
var1 DW 01234h
var2 DW 01234
var3 RESW 1
var4 DW ABCDh

;se defineste o variabila word cu


;valoarea 1234h
;se defineste o variabila word cu
;valoarea zecimala 1234 (4D2 in hexa)
;se rezerva spatiu pentru o variabila
;word (de valoare 0)
;atribuire ilegala!

mesajsco2 DB 'SCO 2 este cursul preferat!'


...start:
mov ax,cs
mov ds,ax

; setarea
; DS=CS

segmentului de date

; orice referinta de memorie se presupune ca este relativa


la segmentul DS
mov ax,[var2]

; AX <- var2
; == mov ax,[2]

mov si,var2

;se foloseste SI ca pointer


var2 (cod C echivalent SI=&var2)

catre

mov ax,[si]

;se citeste din memorie valoarea lui


;var2 (*(&myvar2))
;(referinta indirecta)

mov bx,mesajsco2 ; BX este pointer la un string


; (cod C echivalent: BX=&mesajsco2)
dec BYTE [bx+1]

; transforma 'C' in 'B' !

mov si, 1
; Foloseste SI cu rol de index
inc byte [mesajsco2+SI] ; == inc byte [SI + 8]
; == inc byte [9]
; Memoria poate fi adresata folosindu-se 4 registri:
; SI -> Implica DS
; DI -> Implica DS
; BX -> Implica DS
; BP -> Implica SS ! (nu este foarte des utilizat)
;
;Exemple:
mov
mov
mov
mov
mov

ax,[bx]
al,[bx]
ax,[si]
ah,[si]
cx,[di]

mov ax,[bp]

;
;
;
;
;

ax
al
ax
ah
di

<<<<<-

word
byte
word
byte
word

in memorie
in memorie
referit de
referit de
referit de

referit de BX
referit de BX
SI
SI
DI

; AX <- [SS:BP] Operatie cu stiva!

; In plus, sunt permise BX+SI si BX+DI:


mov ax,[bx+si]
mov ch,[bx+di]
; Deplasamente pe 8 sau 16 biti:
mov
mov
mov
mov

ax,[23h]
ah,[bx+5]
ax,[bx+si+107]
ax,[bx+di+47]

;
;
;
;

ax
ah
ax
ax

<<<<-

word
byte
word
word

in
in
la
la

memorie DS:0023
memorie [DS:BX+5]
adresa [DS:BX+SI+107]
adresa [DS:BX+DI+47]

; ATENTIE: copierea din memorie in memorie este ilegala!


;Totdeauna trebuie sa se treaca valoarea copiata printr-un
;registru
mov [bx],[si]
mov [di],[si]

;Ilegal
;Ilegal

; Caz special: operatiile cu stiva!


pop word [var]

; var <- [SS:SP]

Adrese de memorie i valori


Un program scris n limbaj de asamblare se poate referi fie la o adres de
memorie (OFFSET = DEPLASAMENT), fie la o valoare stocat de variabil n
memorie. Din pcate, limbajul de asamblare nu este nici strict, nici intuitiv cu privire
la modurile n care aceste dou tipuri de referire sunt fcute i, drept urmare,
referirile la OFFSET sau la valoare sunt deseori confundate. n figura 9 sunt ilustrate
conceptele de adres de deplasament (offset) i valoare stocat n memorie.

Figura 9. Ilustrarea noiunilor de adres de deplasament i


valoare stocat n memorie
Deplasamentul unei variabile de memorie var de dimensiune word este
valoarea constant 5004H, obinut cu operatorul OFFSET. Spre exemplu,
instruciunea:
MOV BX, OFFSET var

ncarc valoarea 5004H n registrul BX. Valoarea 5004H nu se modific; ea


este construit n cadrul instruciunii. Valoarea lui var este 1234H, citit din memorie
la adresa dat de offset-ul 5004H din segmentul de date. O modalitatea de citire a
acestei valori este de a ncrca registrele BX, SI, DI sau BP cu offset-ul lui var i apoi
folosirea registrului respectiv pentru adresarea memoriei. Instruciunile:
MOV BX, OFFSET var
MOV AX, [ BX ]
Au ca efect ncrcarea valorii lui var (1234H) n registrul AX.
De asemenea, se poate ncrca valoarea lui var direct n AX folosind:
MOV AX, var
Sau
MOV AX, [ var ]
n timp ce valoarea deplasamentului rmne constant, valoarea 1234H nu
este permanent asociat cu var. De exemplu, instruciunile:
MOV [ var ], 5555H
MOV AX, [ var ]
Au ca efect ncrcarea valorii 5555H n registrul AX.
Cu alte cuvinte, n timp ce deplasamentul lui var este o valoare constant ce
descrie o adres fix dintr-un segment de date, valoarea variabilei var este un numr
ce poate fi modificat i care se afl memorat la adresa (de memorie) respectiv.
Instruciunile:
MOV [ var ], 1
ADD [ var ], 2
Modific valoarea lui var la 3, dar instruciunea:
ADD OFFSET var, 2 este echivalent cu ADD 5002H, 2, ceea ce este un
lucru fr sens, deoarece este imposibil s se nsumeze o constant cu alta.
O problem ce poate aprea adesea n timpul programrii este aceea a omiterii
lui OFFSET; de exemplu, dac scriem MOV SI, var atunci cnd, de fapt, dorim
ncrcarea n SI a deplasamentului lui var. Nu va fi semnalat nici o eroare n acest
caz, avnd n vedere c var este o variabil de tip word. Totui, n momentul execuiei
programului, registrul SI va fi ncrcat cu valoarea lui var (1234H), n loc de
OFFSET, ceea ce poate conduce la rezultate imprevizibile. n acest caz, referirile la
constantele de adres vor fi precedate de OFFSET iar referirile la valori din memorie
s fie cuprinse ntre paranteze drepte ([ i ]), eliminnd astfel ambiguitatea.

Instruciuni ale microprocesorului Intel


Microprocesoarele din familia Intel x86 dispun de o serie impresionant de
instruciuni, asemeni tuturor procesoarelor din clasa procesoarelor CISC (Complex
Instruction Set Computer). Instruciunile se pot mpri n: instruciuni logice,
aritmetice, de transfer i de control. Prezentm n continuare cteva exemple din
fiecare clas de instruciuni.
Instruciuni logice
Instruciunile logice implementeaz funciile logice de baz, pe un octet sau pe
cuvnt. Ele acioneaz bit cu bit, deci se aplic funcia logic respectiv tuturor
biilor sau perechilor de bii corespunztori operanzilor. Instruciunile logice sunt
urmtoarele:

NOT:
AND:
OR:
XOR:
TEST:

A =~A
A &= B
A |= B
A ^= B
A&B

De regul, instruciunile logice au efect asupra indicatorilor de stare, cu


excepia instruciunii NOT, care nu are efect asupra nici unui flag (indicator de
stare). Aceste efecte sunt urmtoarele:
Se terge indicatorul carry (C)
Se terge indicatorul overflow (O)
Se seteaz zero flag (Z) dac rezultatul este zero, sau l terge n caz
contrar
Se copiaz bitul mai nalt al rezultatului n indicatorul sign (S)
Se seteaz bitul de paritate (P) conform cu paritatea rezultatului
Instruciunea NOT
Este o instruciune cu un singur operand (instruciune unar), cu forma
general:
NOT destinatie
Unde destinatie este fie un registru, fie o locaie de memorie pe 8 sau 16 bii.
Instruciunea are ca efect inversarea (negarea) tuturor biilor operandului, adic
aducerea n forma codului invers - complement fa de 1.
Instruciunea AND

Este o instruciune cu doi operanzi (instruciune binar), cu forma general:


AND destinatie, sursa
Unde destinatie este fie un registru, fie o locaie de memorie pe 8 sau 16 bii, iar
sursa poate fi registru, locaie de memorie sau o constant pe 8 sau 16 bii.
Instruciunea are ca efect operaia: <destinatie> == <destinatie> AND <sursa>.
Indicatorii de stare modificai sunt: SF, ZF, PF, CF, OF = 0, AF nedefinit.
Instruciunea TEST (AND non-distructiv)
Este o instruciune cu doi operanzi (instruciune binar), cu forma general:
TEST destinatie, sursa
Unde destinatie este fie un registru, fie o locaie de memorie pe 8 sau 16 bii, iar
sursa poate fi registru, locaie de memorie sau o constant pe 8 sau 16 bii.
Instruciunea are acelai efect ca i instruciunea AND, cu deosebirea c nu se
modific operandul destinaie, iar indicatorii de stare sunt modificai n acelai mod
ca i n cazul instruciunii AND.
Instruciunea OR
Este o instruciune cu doi operanzi, cu forma general:
OR destinatie, sursa
Unde destinatie este fie un registru, fie o locaie de memorie pe 8 sau 16 bii, iar
sursa poate fi registru, locaie de memorie sau o constant pe 8 sau 16 bii.
Instruciunea are efectul: <destinatie> == <destinatie> OR <sursa>. Indicatorii de
stare modificai sunt: SF, ZF, PF, CF, OF = 0, AF nedefinit.
Instruciunea XOR (SAU-Exclusiv)
Este o instruciune cu doi operanzi, cu forma general:
XOR destinatie, sursa
Unde destinatie este fie un registru, fie o locaie de memorie pe 8 sau 16 bii, iar
sursa poate fi registru, locaie de memorie sau o constant pe 8 sau 16 bii.
Instruciunea are efectul: <destinatie> == <destinatie> XOR <sursa>. Indicatorii
de stare modificai sunt: SF, ZF, PF, CF, OF = 0, AF nedefinit. Funcia XOR,
denumit SAU-Exclusiv (sau anti-coinciden) are valoarea logic 1 atunci cnd
operanzii si sunt diferii (unul are valoarea 0 iar cellalt valoarea 1) i valoarea logic
0 cnd ambii operanzi au aceeai valoare (fie ambii au valoarea 0, fie ambii au
valoarea 1).
Observaie:
De cele mai multe ori, instruciunile AND i OR sunt folosit pe post de
mascare a datelor; n acest sens, o valoarea de tip masc (mask) este utilizat
pentru a fora anumii bii s ia valoarea zero sau valoarea 1 n cadrul altei valori. O

astfel de masc logic are efect asupra anumitor bii, n timp ce pe alii i las
neschimbai. Exemple:
Instruciunea AND CL, 0Fh face ca cei mai semnificativi 4 bii s ia
valoarea 0, n timp ce biii mai puin semnificativi sunt lsai neschimbai;
astfel, dac registrul CL are valoarea iniial 1001 1101, dup execuia
instruciunii AND CL, 0Fh va avea valoarea 0000 1101.
Instruciunea OR CL, 0Fh face ca cei mai puin semnificativi 4 bii
s ia valoarea 1, n timp ce biii mai semnificativi s rmn nemodificai. Dac
registrul CL are valoarea iniial 1001 1101, dup execuia instruciunii OR CL,
0Fh va avea valoarea 1001 1111.

Figura 10. Instruciuni de deplasare i de rotaie

Instruciuni de deplasare i de rotaie


Acest tip de instruciuni (vezi figura 10) permit realizarea operaiilor de
deplasare i de rotaie la nivel de bit. Ele au doi operanzi, primul operand fiind cel
asupra cruia se aplic operaia de deplasare pe bii, iar cele de-al doilea (operandul
numrtor sau contor) semnific numrul de bii cu care se face aceast deplasare.
Operaiile se pot face de la dreapta spre stnga sau invers. Deplasarea nseamn

translatarea tuturor biilor din operand la stnga/dreapta, cu completarea unei valori


fixe n poziia rmas liber i cu pierderea biilor din dreapta/stnga. Rotaia
presupune translatarea biilor din operand la stnga/dreapta, cu completarea n
dreapta/stnga cu biii care se pierd n partea opus. Sintaxa general a
instruciunilor de deplasare i rotaie este urmtoarea:
INSTR

<operand> , <contor>

Unde INSTR reprezint numele instruciunii, <operand> reprezint un


registru sau o locaie de memorie pe 8 sau 16 bii, iar <contor> semnific numrul
de bii cu care se face deplasarea, adic fie o constant, fie registrul CL (care i
confirm astfel rolul de numrtor).
Observaie.
Totdeauna exist dou modaliti de deplasare:
Prin folosirea unui contor efectiv de exemplu: SHL AX, 1
Prin folosirea registrului CL pe post de contor de exemplu: SHL AX,
CL
Instruciunea SHL/SAL (Shift Left/Shift Arithmetic Left)
Aceast instruciune translateaz biii operandului o poziie la stnga de cte
ori specific operandul numrtor. Poziiile rmase libere prin deplasarea la stnga
sunt umplute cu zerouri la bitul cel mai puin semnificativ, n timp ce bitul cel mai
semnificativ se deplaseaz n indicatorul CF (Carry Flag).
Reprezint o modalitate rapid de nmulire cu o putere a lui 2 (n funcie de
numrul de bii pentru care se face deplasarea la stnga).
Exemple:
1. nmulirea lui AX cu 10 (1010 n binar) (nmulim cu 2 i cu 8, apoi adunm
rezultatele)
shl ax, 1
; AX ori 2
mov bx, ax
; salvm 2*AX n BX
shl ax, 2
; 2*AX(original) * 4 = 8*AX(original)
add ax, bx
; 2*AX + 8*AX = 10*AX
2. nmulirea lui AX cu 18 (10010 n binar) (nmulim cu 2 i cu 16, apoi
adunm rezultatele)
shl

ax, 1

; AX ori 2

mov bx, ax
shl ax, 3
add ax, bx

; salvm 2*AX
; 2*AX(original) ori 8 = 16*AX(original)
; 2*AX + 16*AX = 18*AX

Instruciunea SHR (Shift Right)


Aceast instruciune translateaz biii operandului o poziie la dreapta de cte
ori specific operandul numrtor. Bitul cel mai puin semnificativ se deplaseaz n
indicatorul CF (Carry Flag).
Reprezint o modalitate rapid de mprire fr semn la o putere a lui 2 (dac
deplasarea se face cu o poziie la dreapta, operaia este echivalent cu o mprire la 2,
dac deplasarea se face cu dou poziii, operaia este echivalent cu o mprire la 22,
etc.). Operaia de mprire se execut fr semn, completndu-se cu un bit 0 dinspre
stnga (bitul cel mai semnificativ).
Instruciunea SAR (Shift Arithmetic Right)
Aceast instruciune translateaz biii operandului o poziie la dreapta de cte
ori specific operandul numrtor. Bitul cel mai semnificativ rmne neschimbat, n
timp ce bitul cel mai puin semnificativ este copiat n indicatorul CF (Carry Flag).
Reprezint o modalitate rapid de mprire cu semn la o puterea a lui 2 (n
funcie de numrul de bii cu care se face deplasarea la dreapta).
Instruciunea RCL (Rotate through Carry Left)
Aceast instruciune determin o rotaie a biilor operandului ctre stnga prin
intermediul lui CF (Carry Flag). Astfel, cel mai semnificativ bit trece din operand n
CF, apoi se deplaseaz toi biii din operand cu o poziie la stnga iar CF original
trece n bitul cel mai puin semnificativ din operand.
Instruciunea ROL (Rotate Left)
Aceast instruciune determin o rotaie a biilor operandului ctre stnga.
Astfel, cel mai semnificativ bit trece din operand n bitul cel mai puin semnificativ.
Exemplu:
Dup execuia instruciunilor:
ROL AX, 6
AND AX, 1Fh
Biii 10-14 din AX se mut n biii 0-4.

Instruciunea RCR (Rotate through Carry Right)


Aceast instruciune determin o rotaie a biilor operandului ctre dreapta
prin intermediul lui CF (Carry Flag). Astfel, bitul din CF este scris napoi n bitul cel
mai semnificativ al operandului.
Instruciunea ROR (Rotate Right)
Aceast instruciune determin o rotaie a biilor operandului ctre dreapta.
Bitul cel mai puin semnificativ trece n bitul cel mai semnificativ.
Exemple:
MOV ax,3

; Valori iniiale

AX = 0000 0000 0000 0011

MOV bx,5

BX = 0000 0000 0000 0101

OR ax,9

ax <- ax | 0000 1001

AX = 0000 0000 0000 1011

AND ax,10101010b

; ax <- ax & 1010 1010

AX = 0000 0000 0000 1010

XOR ax,0FFh

; ax <- ax ^ 1111 1111

AX = 0000 0000 1111 0101

NEG ax

; ax <- (-ax)

AX = 1111 1111 0000 1011

NOT ax

; ax <- (~ax)

AX = 0000 0000 1111 0100

OR ax,1

; ax <- ax | 0000 0001

AX = 0000 0000 1111 0101

SHL ax,1

; depl logic la stg cu 1 bit AX = 0000 0001 1110 1010

SHR ax,1

; depl logic la dr cu 1 bit

AX = 0000 0000 1111 0101

ROR ax,1

; rotaie stg (LSB=MSB)

AX = 1000 0000 0111 1010

ROL ax,1

; rotaie dr (MSB=LSB)

AX = 0000 0000 1111 0101

MOV cl,3

; folosim CL pt depl cu 3 bii

SHR ax,cl

; mprim AX la 8

MOV cl,3

; folosim CL pt depl cu 3 bii

SHL bx,cl

; nmulim BX cu 8

CL = 0000 0011

AX = 0000 0000 0001 1110


CL = 0000 0011

BX = 0000 0000 0010 1000

Instruciuni aritmetice
Instruciunea ADD (ADDition)
Instruciunea ADD are formatul general:
ADD <destinatie> <sursa>
Unde <destinatie> poate fi un registru general sau o locaie de memorie, iar
<sursa> poate fi registru general, locaie de memorie sau o valoare imediat. Cei doi
operanzi nu pot fi ns n acelai timp locaii de memorie. Rezultatul operaiei este

urmtorul: <destinatie> == <destinatie> + <sursa>. Indicatorii de stare modificai


n urma acestei operaii sunt: AF, CF, PF, SF, ZF, OF. Operanzii pot fi pe 8 sau pe
16 bii i trebuie s aib aceeai dimensiune. Dac apare ambiguitate la modul de
exprimare al operanzilor (8 sau 16 bii) se va folosi operatorul PTR.
Exemple:
ADD AX, BX
; adunare ntre regitri AX AX + BX
ADD DL, 33h
; adunare efectiv - DL DL + 33h
MOV DI, NUMB ; adresa lui NUMB
MOV AL, 0
; se terge suma
ADD AL, [DI]
; adun [NUMB]
ADD AL, [DI + 1] ; adun [NUMB + 1]
ADD word ptr [DI], -2 ; destinatie in memorie, sursa imediata
ADD byte ptr VAR, 5
; fortarea instructiunii pe un octet, VAR fiind
;declarat DW
Instruciunea INC (Increment addition)
Instruciunea INC are formatul general:
INC <destinatie>
Unde <destinatie> este un registru sau un operand n memorie, pe 8 sau pe 16
bii iar semnificaia operaiei este incrementarea valorii destinaie cu 1. Toi
indicatorii de stare sunt afectai, cu excepia lui CF (Carry Flag).
Exemplu:
MOV DI, NUMB
MOV AL, 0
ADD AL, [DI]
INC DI
ADD AL, [DI]

; adresa lui NUMB


; terge suma
; adun [NUMB]
; DI = DI + 1
; adun [NUMB + 1]

Instruciunea ADC (ADdition with Carry)


Instruciunea ADD are formatul general:
ADD <destinatie> <sursa>
Unde <destinatie> poate fi un registru general sau o locaie de memorie, iar
<sursa> poate fi registru general, locaie de memorie sau o valoare imediat.

Instruciunea acioneaz ntocmai ca ADD, cu deosebirea c la rezultat este adugat


i bitul CF. Este utilizat, de regul, pentru a aduna numere mai mari de 16 bii (808680286) sau mai mari de 32 de bii la 80386, 80486, Pentium.
Exemplu:
Adunarea a dou numere pe 32 de bii se poate face astfel (BXAX) +
(DXCX):
ADD AX, CX
ADC BX, DX
Instruciunea SUB (SUBstract)
Instruciunea SUB are formatul general:
SUB <destinatie> <sursa>
Unde <destinatie> poate fi un registru general sau o locaie de memorie, iar
<sursa> poate fi registru general, locaie de memorie sau o valoare imediat.
Rezultatul operaiei este urmtorul: <destinatie> == <destinatie> - <sursa>.
Indicatorii de stare modificai n urma acestei operaii sunt: AF, CF, PF, SF, ZF, OF.
Operanzii pot fi pe 8 sau pe 16 bii i trebuie s aib aceeai dimensiune. Scderea
poate fi vzut ca o adunare cu reprezentarea n complementul fa de 2 al
operandului surs i cu inversarea bitului CF, n sensul c, dac la operaie (adunarea
echivalent) apare transport, CF=0 i dac la adunarea echivalent nu apare
transport, CF=1.
Pentru instruciunile:
MOV CH, 22h
SUB CH, 34h
Rezultatul este -12 (1110 1110), iar indicatorii de stare se modific astfel:
ZF = 0 (rezultat diferit de zero)
CF = 1 (mprumut)
SF = 1 (rezultat negativ)
PF = 0 (paritate par)
OF = 0 (fr depire)
Instruciunea DEC (DECrement substraction)

Instruciunea DEC are formatul general:


DEC <destinatie>
Unde <destinatie> este un registru sau un operand n memorie, pe 8 sau pe 16
bii iar semnificaia operaiei este decrementarea valorii destinaie cu 1. Toi
indicatorii de stare sunt afectai, cu excepia lui CF (Carry Flag).
Instruciunea SBB (SuBstract with Borrow)
Instruciunea SBB are formatul general:
SBB <destinatie>, <sursa>
Unde <destinatie> i <sursa> pot fi registru sau operand n memorie, pe 8 sau
pe 16 bii. Rezultatul operaiei este urmtorul: <destinatie> == <destinatie> <sursa> - CF, deci la fel ca i n cazul instruciunii SUB, dar din rezultat se
scade i bitul CF. Indicatorii de stare modificai n urma acestei operaii sunt:
AF, CF, PF, SF, ZF, OF. Aceast instruciune este utilizat, de regul, pentru
a scdea numere mai mari de 16 bii (la 8086 - 80286) sau de 32 de bii (la
80386, 80486, Pentium).
Exemplu
Scderea a dou numere pe 32 de bii se poate face astfel (BXAX) - (SIDI):
SUB AX, DI
SBB BX, SI
Exemple de programe
1. Program care citete un numr de la tastatur i afieaz dac numrul este
par sau nu:
; Programul citeste un numar si afiseaza un mesaj referitor la paritate
dosseg
.model small
.stack
.data
mesaj db 13,10,'Introduceti numarul:(<=9)$'
mesg_par db 13,10,'Numarul introdus este par!$'
mesg_impar db 13,10,'Numarul introdus este impar!$'

.code
pstart:
mov ax,@data
mov ds,ax
mov ah,09
mov dx,offset mesaj
int 21h
mov ah,01h ; se citeste un caracter de la tastatura
; codul ASCII al caracterului introdus va fi in AL
int 21h
mov bx,2
div bx ; se imparte AX la BX, catul va fi in AX, restul in DX
cmp dx,0
jnz impar
mov ah,09
mov dx,offset mesg_par
int 21h
jmp sfarsit
impar: mov ah,09
mov dx,offset mesg_impar
int 21h
sfarsit:
mov ah,4ch
int 21h ; sfarsitul programului
END pstart
2. Program care calculeaz ptratul unui numr introdus de la tastatur.
; Programul calculeaza patratul unui numar (<=256) introdus de la tastatura
; Valoarea patratului se calculeaza in registrul AX (valoare maxima 2^16 =
65536)
dosseg
.model small
.stack
.data
nr DB 10,10 dup(0)
r DB 10, 10 dup(0)

mesaj db 13,10,'Introduceti numarul:(<=256)$'


patrat db 13,10,'Patratul numarului este:$'
.code
pstart:
mov ax,@data
mov ds,ax
mov ah,09
mov dx,offset mesaj
int 21h
mov ah,0ah
mov dx,offset nr
int 21h
mov cl,nr[1] ; incarc in CL numarul de cifre al numarului introdus
inc cl
; in sir se va merge pana la pozitia cl+1
mov si,1
; folosesc registrul SI pe post de contor
xor ax,ax
; initializez AX cu valoarea 0
mov bl,10 ; se va inmulti cu valoarea 10 care este stocata in BL
inmultire:
mul bl
inc si
mov dl,nr[si]
sub dl,30h
add ax,dx
cmp si,cx
jne inmultire
mul ax
xor si,si
mov bx,10
cifra: ; aici incepe afisarea rezultatului din AX
div bx
add dl,30h
mov r[si],dl
inc si
xor dx,dx

cmp ax,0
jne cifra
mov ah,9
mov dx, offset patrat
int 21h
caracter:
dec si
mov ah,02 ;apelarea functiei 02 pentru afisarea unui caracter
mov dl,r[si] ;al carui cod ASCII este in DL
int 21h
cmp si,0
jne caracter
jmp sfarsit
mov ah,9
mov dx,offset patrat
int 21h
sfarsit:
mov ah,4ch
int 21h ; stop program

END pstart
3. Program care calculeaz valoarea unui numr ridicat la o putere. Att
numrul ct i exponentul (puterea) sunt introduse de la tastatur.
; Programul calculeaza un numar ridicat la o putere
; Observatie. Deoarece rezultatul se calculeaza in registrul AX care este un
; registru pe 16 biti, valoarea maxima calculata corect este 2^16= 65536
.model small
.stack
.data
mesaj1 db 13,10,'Introduceti numarul:(<=9)$'
mesaj2 db 13,10,'Introduceti puterea:(<=9)$'

mesaj_final db 13,10,'Rezultatul este: $'


mesaj_putere_0 db 13,10, 'Orice numar ridicat la puterea 0 este 1! $'
r db 30 dup(0) ; in variabila r se va stoca reultatul
.code
pstart:
mov ax,@data
mov ds,ax
mov ah,09
mov dx,offset mesaj1
int 21h
mov ah,01h ; se citeste un caracter de la tastatura
; codul ASCII al caracterului introdus va fi in AL
int 21h
and ax,00FFh
sub ax, 30h ; se obtine valoarea numerica
; scazandu-se codul lui 0 in ASCII (30H)
push ax ; se salveaza valoarea lui ax in stiva
mov ah,09
mov dx,offset mesaj2
int 21h
mov ah,01h ; se citeste un caracter de la tastatura
; codul ASCII al caracterului introdus va fi in AL
int 21h
and ax,00FFh
sub ax, 30h ; se obtine valoarea numerica
; scazandu-se codul lui 0 in ASCII (30H)
mov cx,ax ; registrul CX contorizeaza numarul de inmultiri
cmp cx,0
jne putere_0
mov ah,09
mov dx, offset mesaj_putere_0
int 21h
jmp sfarsit
putere_0:
pop bx
;se salveaza in BX valoarea cu care inmulteste
mov ax,0001
inmultire:

mul bx
loop inmultire
xor si,si
mov bx,10
cifra:
div bx
add dl,30h
mov r[si],dl
inc si
xor dx,dx
cmp ax,0
jne cifra
mov ah,9
mov dx, offset mesaj_final
int 21h
caracter:
dec si
mov ah,02 ;apelarea functiei 02 pentru afisarea unui caracter
mov dl,r[si] ;al carui cod ASCII este in DL
int 21h
cmp si,0
jne caracter

sfarsit:
mov ah,4ch
int 21h ; sfarsitul programului
END pstart
4. Program care verific dac un numr este palindrom (un numr se numete
palindrom dac scris de la dreapta la stnga sau invers are aceeai valoare).
; Programul verifica daca un numar sau sir de caractere este palindrom
dosseg
.model small
.stack

.data
nr DB 10,10 dup(0)
mesaj db 13,10,'Introduceti numarul:$'
mesaj_nu db 13,10,'Numarul nu este palindrom!$'
mesaj_da db 13,10,'Numarul este palindrom!$'
.code
pstart:
mov ax,@data
mov ds,ax
mov ah,09
mov dx,offset mesaj
int 21h
mov ah,0ah
mov dx,offset nr
int 21h
mov si,1
mov cl,nr[si] ; incarc in CL numarul de cifre al numarului introdus
and cx,00FFh
mov ax,cx
mov bl,2
div bl
; in AL este catul impartirii lui AX la 2
and ax,00FFh
inc ax
inc cx
mov di,cx
urmatorul_caracter:
inc si
; SI creste de la inceputul sirului spre mijloc
mov bl,nr[di]
cmp nr[si],bl
jne nu_este
dec di
; DI scade de la sfarsitul sirului spre mijloc
cmp si,ax
; in sir se va merge pana la pozitia cl+1
jne urmatorul_caracter
mov ah,9

mov dx,offset mesaj_da


int 21h
jmp sfarsit
nu_este:
mov ah,9
mov dx,offset mesaj_nu
int 21h
sfarsit:
mov ah,4ch
int 21h ; stop program
END pstart
5. Program care calculeaz suma cifrelor unui numr introdus de la tastatur.
; Programul calculeaza suma cifrelor unui numar introdus de la tastatura
dosseg
.model small
.stack
.data
nr DB 10,10 dup(?)
rezultat DB 10,10 dup(?)
mesaj db 13,10,'Introduceti numarul:$'
mesaj_suma db 13,10,'Suma cifrelor numarului este: $'
.code
pstart:
mov ax,@data
mov ds,ax
mov ah,09
; aici se afiseaza mesajul initial de introducere
mov dx,offset mesaj ; a numarului
int 21h

mov ah,0ah

; functia 10(0ah) citeste un sir de caractere de la


; tastatura intr-o variabila de memorie

mov dx,offset nr
int 21h
mov si,1
mov cl,nr[si] ; incarc in CL numarul de cifre al numarului introdus
and cx,00FFh
inc cx
; CX stocheaza acum ultima pozitie din sirul de cifre
xor ax,ax
; stocam rezultatul in AX, pe care il initializam cu zero
urmatorul_caracter:
inc si
; SI creste de la inceputul sirului spre sfarsit
add al,nr[si]
sub al,30h

; scadem codul ASCII al lui zero

cmp si,cx
; in sir se va merge pana la pozitia cl+1
jne urmatorul_caracter
xor si,si

; SI este indicele din sirul care va contine rezultatul

cifra: ; aici incepe afisarea rezultatului din AX


mov bx,0ah
div bx
add dl,30h
mov rezultat[si],dl
inc si
xor dx,dx
cmp ax,0
jne cifra
mov ah,9
mov dx,offset mesaj_suma
int 21h
caracter:
dec si
mov ah,02
;apelarea functiei 02 pentru afisarea unui caracter
mov dl,rezultat[si] ;al carui cod ASCII este in DL
int 21h
cmp si,0

jne caracter
mov ah,4ch
int 21h
END pstart

; terminarea programului

S-ar putea să vă placă și