You are on page 1of 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! 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.).

Observaie:

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:
;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 ;Program p01.asm .MODEL small .STACK 200H .DATA

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] mov si,var2 mov ax,[si] ; AX <- var2 ; == mov ax,[2] ;se foloseste SI ca pointer var2 (cod C echivalent SI=&var2) catre

;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] ; ; ; ; ; 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

mov ax,[bp]

; 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 MOV bx,5 OR ax,9 XOR ax,0FFh NEG ax NOT ax OR ax,1 SHL ax,1 SHR ax,1 ROR ax,1 ROL ax,1 MOV cl,3 SHR ax,cl MOV cl,3 SHL bx,cl ; Valori iniiale ; ; ax <- ax | 0000 1001 ; ax <- ax & 1010 1010 ; ax <- ax ^ 1111 1111 ; ax <- (-ax) ; ax <- (~ax) ; ax <- ax | 0000 0001 ; depl logic la dr cu 1 bit ; rotaie stg (LSB=MSB) ; rotaie dr (MSB=LSB) ; mprim AX la 8 ; nmulim BX cu 8 AX = 0000 0000 0000 0011 BX = 0000 0000 0000 0101 AX = 0000 0000 0000 1011 AX = 0000 0000 0000 1010 AX = 0000 0000 1111 0101 AX = 1111 1111 0000 1011 AX = 0000 0000 1111 0100 AX = 0000 0000 1111 0101 AX = 0000 0000 1111 0101 AX = 1000 0000 0111 1010 AX = 0000 0000 1111 0101 CL = 0000 0011 CL = 0000 0011 AX = 0000 0000 0001 1110 BX = 0000 0000 0010 1000

AND ax,10101010b

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

; folosim CL pt depl cu 3 bii ; folosim CL pt depl cu 3 bii

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 mov dx,offset nr int 21h

; functia 10(0ah) citeste un sir de caractere de la ; tastatura intr-o variabila de memorie

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

You might also like