Vous êtes sur la page 1sur 314

Capitolul1

Introducere Arhitectura8086 Modurideadresare


1.1Introducere.Necesitatealimbajuluideasamblare
Limbajul de asamblare (ASM) permite nelegerea la nivel de amnunt a ceea ce se ntmpl n realitate ntrun calculator. Familiarizarea cu un asemenea limbaj este mai mult dect benefic pentru un programator, contribuind la eficienaprogramelordezvoltate,indiferentdelimbajulutilizat. Exist mai multe motive pentru care programarea n ASM este necesar. Codul generat n ASM se execut n general foarte rapid. Unele module de program trebuie implementate n ASM datorit acestei viteze de lucru. Uneori, o parte a unui program este scris ntrun limbaj de nivel nalt, iar modulele critice sunt scrisecaproceduriASM,apelatelarndullordemoduleledenivelnalt. Pe de alt parte, exist situaii n care e nevoie de acces direct la dispozitive de intrare/ieire sau la locaii fizice de memorie, iar aceste operaii nu pot fi executate n unele limbaje de nivel nalt. De exemplu, la calculatoarele personale, programele TSR i rutinele de tratare a ntreruperilor sunt aproape totdeaunascrisenASM. Pe scurt, limbajul de asamblare ofer viteze de execuie i acces la hardware carenupotfidisponibile(celmaiadesea)nlimbajeledenivelnalt. Un alt aspect important este cel al dezvoltrii de programe pentru echipamente dedicate. Nu toate programele executabile sunt destinate calculatoarelor de uz general. Dezvoltarea masiv a microprocesoarelor a fcut ca acestea s controleze n prezent funcionarea celor mai diverse obiecte tehnice, de la maini de gtit sau de splat rufe pn la echipamente de control industrial sau pentru comanda avioanelor. Toate aceste microprocesoare funcioneaz pe baza unor programe i nu trebuie s fii cine tie ce specialist ca si dai seama c e puin probabil ca un program care controleaz un cuptor cu

2 Capitolul1
microunde sau un osciloscop s fi fost scris n PASCAL sau n BASIC. De fapt, majoritatea programelor pentru asemenea echipamente dedicate sunt scrise n limbaj de asamblare, pentru c, ntrun asemenea context, ceea ce conteaz estevitezadeexecuieivolumulfoartelimitatdememorie. Pe de alt parte, nu toate microprocesoarele sunt de uz general. Exist microprocesoare specializate, destinate unor scopuri precise, cum ar fi procesoare de semnal, microcontrollere industriale, automate programabile etc. Pentru asemenea procesoare, nu se justific (n general) dezvoltarea de compilatoare pentru limbaje de nivel nalt, programele fiind dezvoltate n limbajele specifice acestor procesoare, care sunt asemntoare limbajelor de asamblarepentruprocesoareledeuzgeneral. Exist i un puternic rol formativ al programrii n limbaj de asamblare. Un programator nu ajunge niciodat la un nivel superior (de expert), dac nu trece (mcarodatnvia)prindezvoltareadeprogrameASM. Cartea de fa i propune s ofere cititorului un mijloc de ai nsui limbajul de asamblare pentru procesoarele din familia Intel (IBMPC). Ca mediu de dezvoltare, este folosit familia de produse software Borland (Turbo Assembler, TurboLinkeriTurboDebugger). O atenie sporit este acordat dezvoltrii de aplicaii mixte (n limbaje de nivel nalt i n ASM). Ca limbaj de nivel nalt tipic, sa ales limbajul C, pentru care exist medii de dezvoltare integrate oferite de firma Borland, total compatibileculimbajuldeasamblare. n aceast carte nu se insist prea mult pe interfaa software cu sistemul BIOS sau cu sistemul DOS. Exist multe manuale de firm care descriu n detaliu funciile i subfunciile BIOS i DOS. Scopul acestei cri este de a oferi mijloace de dezvoltare de module ASM eficiente i integrarea lor n aplicaiicomplexe.

1.2Noiuniintroductivedehardware.Registre.Stiv
n ASM, calculatorul este vzut la nivelul hardware: adrese fizice de memorie, registre,ntreruperietc.Suntnecesareunelenoiunipregtitoare. Unitatea de baz a informaiei memorate n calculator este bitul. Un bit reprezint o cifr binar (de aici i numele, care e o prescurtare de la binary digit), deci poate avea valorile 0 sau 1. Modelul hardware corespunztor este acela de bistabil. Un bistabil este, deci, un circuit electronic cu dou stri stabile,codificate0i1,capabilsmemorezeunbitdeinformaie. Un grup de bistabili formeaz un registru. De exemplu, 8 bistabili formeaz un registru de 8 bii. Informaia care se poate memora ntrun asemenea registru poate fi codificat n binar, de la valoarea 00000000 (toi biii egali cu 0), pn la valoarea 11111111 (toi biii egali cu 1). Este uor de vzut c

Programarenlimbajdeasamblare 3 numrul combinaiilor care pot fi memorate este 256 (2 la puterea a 8a). n general, un registru de n bii va putea memora 2 n combinaii distincte. Aceste combinaii se numesc octei sau bytes (dac n = 8), respectiv cuvinte (dac n = 16, 32 etc.). La procesoarele din familia Intel, cuvintele sunt de 16 sau 32 de bii (putnd exista i cantiti pe un numr mai mare de bii,dartoatemultiplude8). Memoria unui calculator este vzut ca o succesiune de octei. Fiecare octet are asociat o adres de memorie. Pentru a putea adresa memoria, e nevoie de un registru de adrese, a crui lungime determin dimensiunea maxim a memoriei. Dac avem un registru de adrese de 8 bii, atunci vom putea adresa 28 octei de memorie. Procesorul 8086 are un registru de adrese de 20 de bii, deci poate adresa 220 octei de memorie (sau 1 megaoctet de memorie). Zonele de memorie vor fi reprezentate grafic pe vertical, ca succesiunideocteisaucuvinte,delaadresemicictreadresemari. O adres cu semnificaie special este adresa instruciunii care se execut n mod curent. Toate procesoarele au un registru destinat acestui scop, numit contor program (Program Counter). Acest registru conine ntotdeauna adresainstruciuniicareurmeazafiexecutat. O zon special de memorie este aa numita zon de stiv. Stiva este un concept abstract de structur de date, dar procesoarele dispun de instruciuni main pentru operaii cu o asemenea structur de date. O zon de stiv este caracterizat de o adres curent (numit adresa vrfului stivei), adresat printrun registru numit SP (Stack Pointer, indicator de stiv). Operaiiledebazcustivasunt:
PUSH (X), care se poate descrie prin actiunile: (SP) (SP) - 1 ((SP)) X POP (X), care se poate descrie prin actiunile: X ((SP)) (SP) (SP) + 1

Notaia (SP) nseamn coninutul lui SP, iar ((SP)), coninutul locaiei de memorie adresate de (SP). Din analiza celor dou operaii, se vede c structura de stiv este de tip Primul Intrat, Primul Ieit sau First In, First Out, adic ultima cantitate care a fost mpins n stiv printro operaie PUSH va fi cea care se va extrage la urmtoarea operaie POP. La procesorul 8086, cantitile transferate n stiv sunt cuvinte de 16 bii, deci adresa curent a vrfului stivei (coninut n SP) este adunatsausczutcu2.

4 Capitolul1
Stiva poate fi folosit explicit pentru salvri i refaceri de date. Ea este folosit implicit n mecanismul de apel de procedur. Cnd se apeleaz o procedur cu numele PR, printrun apel generic de forma CALL PR, se va da controlul (adic se va produce un salt) la prima instruciune a procedurii. Acest salt nu nseamn altceva dect c n registrul contor program se va depune adresa primeiinstruciunidinprocedur. Se pune ns problema revenirii din procedur, la execuia unei instruciuni generice RETURN. Controlul trebuie s revin n programul apelant i s se executeinstruciuneadedupapeluldeprocedur. Acest fapt este posibil, deoarece la execuia instruciunii CALL, nainte de a se executa saltul la procedur, se salveaz n stiv coninutul contorului program (adic adresa instruciunii imediat urmtoare apelului de procedur). Instruciunea RETURN nu face altceva dect s extrag aceast adres din stiv i s o plaseze n contorul program, execuia continund cu instruciunea de dup apelul de procedur. Acest mecanism este ilustrat n Figura1.1. Un program ASM (ca de altfel i unul n limbaj de nivel nalt) este organizat n treispaiidememorie: spaiul (zona) de cod acesta cuprinde instruciunile care compun programulsaucodul spaiul (zona) de date acesta cuprinde datele statice definite n program (caresegsesclaadresefixe) spaiul(zona)destivacestacuprindestivarezervatprogramului.

Programarenlimbajdeasamblare 5 Figura 1.1 Rolul stivei la apelul unei proceduri Zona de date poate fi detaliat n date constante, date iniializate sau neiniializateetc. Trebuie remarcat c orice program executabil are structura de mai sus, indiferent de limbajul n care a fost scris, dar n ASM aceast structur este vizibil i gestionat de ctre programator. Acesta poate chiar schimba semnificaiile zonelor respective. De exemplu, exist situaii (programe TSR) ncaredatelesuntdefinitenacelaispaiudememoriecuinstruciunile. Pe lng cele trei spaii de memorie, mai exist i aa numitul spaiu de memorie disponibil. Acesta folosete la alocri dinamice de memorie (la momentul execuiei programului) i este gestionat n mod indirect, prin apeluri ctresistemuldeoperare.

1.3Reprezentriinternealedatelor
1.3.1Bazedenumeraie
n tehnica de calcul, pe lng baza de numeraie 10, sunt folosite bazele de numeraie 2, 8 i 16, iar sistemele de numeraie respective se numesc binar, octal i hexazecimal. n sistemul hexazecimal, cifrele de la 10 la 15 se noteaz cu literele de la A pn la F. Tabelul 1.1 ilustreaz corespondena dintre sistemele zecimal, binar, octal i hexazecimal. Trebuie reinut faptul esenial c, n memoria calculatorului, informaia de orice fel (date sau programe) este ntotdeaunareprezentatnformbinar,decicasecvenedecifre0sau1. Deoarece este greu de operat cu numere mari n baza 2, pentru exprimarea unor cantiti binare se folosesc bazele 8 i 16. De exemplu, numrul 255 se poateexprimanacestebazeprin255(10)=11111111(2)=FF(16)=377(8). Informaia este organizat n calculator pe grupe de cte 8 cifre binare (bii). Un asemenea grup se mai numete i octet (sau byte). Octetul este unitatea de msurncareseexprimvolumulmemorieiunuicalculator. Deoarece dimensiunea memoriei este totdeauna o putere a lui 2, multiplii folositi pentru octei nu sunt 100, 1000 etc., ci puteri adecvate ale lui 2. Astfel, un numr de 210 = 1024 de octei se mai numete i kilooctet sau kilobyte (pe scurt KO sau KB). Similar, un numr de 2 20 = 10264576 octei se numete megaoctet sau megabyte (MO sau MB). Se mai folosete i gigaoctetul (gigabyteul), care este egal cu 230 octei. Aadar, multiplii folosii n tehnica decalculsunt: kilo=210=1024 mega=220=10264576 giga=230=1073741824

6 Capitolul1
Zecimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Binar 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 Octal 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 Hexazecimal 0 1 2 3 4 5 6 7 8 9 A B C D E F

Tabelul 1.1 Reprezentarea numerelor n bazele 10, 2, 8 i 16

1.3.2Reprezentareanumerelorntregi
Numerele ntregi pot fi reprezentate pe unul sau mai muli octei, deci pe un numr n de bii. Deoarece fiecare bit poate lua dou valori (0 i 1), numrul totaldevaloridistincteeste2n. n cazul numerelor fr semn, valoarea intern a biilor (octeilor) reprezint chiar valoarea numrului. Este uor de vzut c, dac reprezentarea este pe n bii, domeniul posibil de valori este de la 0 la 2 n1. Pentru n = 3 rezult domeniuldinTabelul1.2. n ceea ce privete reprezentarea numerelor cu semn, trebuie spus c valorile interne care se pot reprezenta (deci configuraiile de bii) sunt aceleai ca la numerele fr semn. Aceste configuraii variaz ntre 0000...0000 (toi biii egalicu0)i1111...1111(toibiiiegalicu1). Se pune deci problema ca, printro convenie adecvat, s se considere o parte din aceste configuraii de bii ca reprezentnd numere ntregi pozitive, iarcealaltpartenumerenegative.

Programarenlimbajdeasamblare 7
Reprezentare intern 000 001 010 011 100 101 110 111 0 1 2 3 4 5 6 7 Valoare

Tabelul 1.2 Reprezentarea numerelor fr semn pe 3 bii Exist mai multe sisteme de reprezentare, dintre care cel mai rspndit este sistemul de reprezentare n complement fa de 2. n acest sistem, bitul cel mai semnificativ joac un rol special, anume de a preciza semnul numrului (din acest motiv se numete bit de semn). Dac bitul de semn este 0, numrul reprezentatestepozitiv,iardacbituldesemneste1,numrulestenegativ. n ceea ce privete valoarea absolut (modulul) a numrului, ea se obine difereniat,funciedesemnulnumrului,nfelulurmtor: dac bitul de semn este 0, atunci configuraia intern reprezint chiar valoareanumrului dac bitul de semn este 1, atunci valoarea absolut a numrului se obine prin complement fa de 2, adic prin complementarea tuturor biilor (0devine1ireciproc)iprinadunareaapoiavalorii1. Aceast regul se aplic pentru ambele sensuri de conversie (de la reprezentri internelanumerecusemnireciproc). De exemplu, fie numrul de bii n = 3 i s considerm reprezentarea 111. Bitul de semn este 1, deci este vorba de un numr negativ. Prin complementare se obine 000, iar prin adunare cu 1 se obine 001, adic valoarea absolut 1.Astfel,reprezentareabinar111pe3biicorespundenumrului1. Reprezentarea n complement fa de 2 pe n bii are urmtoarele proprietigenerale: domeniuldereprezentareeste2n1...2n11 existosingurreprezentarepentru0,anume000...000 bitulcelmaisemnificativestebitdesemn calculul valorilor absolute pentru numere negative se face prin aplicarea reguliicomplementuluifade2.

8 Capitolul1
n Tabelul 1.3 sunt ilustrate domeniile de valori pentru numere cu semn pe n = 3 bii. S remarcm faptul important c o aceeai reprezentare intern poate avea semnificaii (interpretri) diferite, dup cum se consider reprezentarea cu semn sau fr semn. De exemplu, valoarea intern 1010 este interpretat ca 6 n reprezentarea cu semn i ca +10 n reprezentarea fr semn pe 4 bii. Se vede c diferena dintre aceste dou valori posibile este chiar 2n (n cazul de fa16). De aici se poate deduce o alt regul pentru aflarea rapid a reprezentrii numerelor negative: se adun 2n, iar valoarea obinut se reprezint ca numr frsemn. De exemplu, ca s obinem reprezentarea lui 120 pe 8 bii, adunm 256 i obinem valoarea pozitiv 136. Reprezentarea lui 136 n baza 2 va fi atunci reprezentareancomplementfade2alui120,adic10001000sau88H.
Reprezentare intern 000 001 010 011 100 101 110 111 0 1 2 3 4 3 2 1 Valoare

Tabelul 1.3 Reprezentarea numerelor cu semn pe 3 bii n diverse sisteme de afiare a datelor numerice, n care este folosit numai baza 10, se utilizeaz codificarea de tip BCD care nseamn Zecimal Codificat n Binar(nenglez,Binary Coded Decimal). n acest sistem, se reprezint o cifr zecimal pe un grup de 4 bii (4 bii pot codifica 16 valori distincte, deci 6 valori nu vor fi folosite). Un octet va codifica deci 2 cifre zecimale. De exemplu, octetul cu valoarea 01011001 reprezint codificarea BCD pentru numrul zecimal 59 (primul grup de 4 bii reprezint cifra 5, iar al doilea grup cifra 9). Dac este necesar, se pot considera n octei pentrumemorareaa2ncifrezecimale. Calculatoarele dispun, de obicei, de instruciuni speciale pentru calcule n format BCD. Sunt unele probleme care trebuie avute n vedere, i anume

Programarenlimbajdeasamblare 9 operaiile de corecie care trebuie fcute dup (sau naintea) operaiilor n BCD, deoarece nu toate cele 16 combinaii binare posibile sunt cifre BCD corecte. Formatul BCD se mai numete i BCD mpachetat, pentru al deosebi de formatul BCD despachetat, n care se reprezint o cifr BCD pe un octet. n terminologia firmei INTEL (reflectat n denumirile instruciunilor procesoarelor), formatul BCD despachetat este denumit (oarecum incorect) format ASCII. Justificarea denumirii este c, prin adugarea valorii 30H (codul ASCII al cifrei 0), se obine codul ASCII al cifrei reprezentate de octetul respectiv. Toate cele trei sisteme de reprezentare a numerelor ntregi ilustreaz faptul c datele din memoria calculatorului se pot interpreta diferit. Aceste interpretri sunt fcute de programul care folosete datele. De exemplu octetul 10010100 poate reprezenta numrul zecimal pozitiv 148, numrul zecimal negativ 108 sau numrul zecimal pozitiv 94, dup cum se lucreaz cu sistemul de reprezentarefrsemn,cusemnsau,respectiv,cusistemulBCD.

1.3.3Reprezentareanumerelorreale
Numerele reale (fracionare) se pot reprezenta n dou moduri distincte, care suntnumitereprezentarenvirgulfixireprezentarenvirgulmobil. Reprezentareanvirgulfix n reprezentarea n virgul fix, se consider un numr finit de cifre semnificative, att pentru partea ntreag a numrului, ct i pentru cea fracionar. Considernd baza de numeraie b, n cifre pentru partea ntreag i m cifre pentru partea fracionar, un numr fracionar x se reprezint prin expresia: x=inbn+...+i1b1+i0b0+f1b1+...+fmbm n care cifrele in...i0 reprezint partea ntreag, iar cifrele f 1...fm reprezint partea fracionar a numrului x. Cifrele sunt considerate n baza b. Un asemenea numrsescriepoziionalnforma: in...i1i0.f1...fm(b) (n tehnica de calcul, virgula se noteaz cu un punct). Exemple de astfel de numerefracionarepotfi: 123.25(10)1AB34.FF52(16)1000110.11011(2) ntro reprezentare intern concret (pe un sistem de calcul), baza b i numrul de cifre de la stnga i de la dreapta virgulei (n i m) sunt fixate aprioric. De exemplu, lucrnd cu baza 10 i presupunnd c o precizie de 0.001 este suficient, se vor memora doar 3 cifre dup virgul. Similar, dac se presupune c numerele care trebuie reprezentate nu depesc valoarea 10000, se vor

10 Capitolul1
aloca 4 cifre la stnga virgulei. Se vor reprezenta astfel numere zecimale n domeniul0.001...9999.999,cuopreciziede0.001. Cifrele respective vor fi numite mii, sute, zeci, uniti, zecimi, sutimi, miimi etc. i se vor reprezenta fie pe cte un octet, fie pe cte 4 bii. Memorarea semnului unui astfel de numr se face ntrun cmp separat. Tabelul 1.4 exemplific reprezentarea n virgul fix a numerelor 1.130, 1230.192 i 10.000.
Semn + + Mii 0 1 0 Sute 0 2 0 Zeci 0 3 1 Unit i 1 0 0 Zecimi 0 1 0 Sutimi 1 9 0 Miimi 3 2 0

Tabelul 1.4 Reprezentarea n virgul fix (b = 10, n = 4, m = 3) Se observ c punctul zecimal nu se reprezint, deoarece poziia sa este cunoscut (este fix, ntre coloanele unitilor i ale zecimilor). De altfel, numelemetodeidereprezentareprovinedelaaceastproprietate. Uneori, se reprezint numrul real respectiv nmulit cu 10 la o putere egal cu numrul de cifre de dup virgul. De exemplu, numrul 1.130 se poate reprezenta intern ca numrul ntreg 1130, iar numrul 1230.192 ca numrul ntreg 1230192 (n complement fa de 2, pentru a memora i semnul). n operaiile aritmetice care se vor face, se va ine seama de faptul c numerele sunt nmulite cu 1000 i se va reprezenta punctul zecimal dup a treiacifrdeladreaptalastnga. Trebuie remarcat c, ntro astfel de reprezentare cu numr fix de cmpuri, nu se poate reprezenta dect un subset finit al numerelor reale, n exemplul de mai sus acest subset fiind cuprins ntre 9999.999 i +9999.999, cu pasul 0.001. Trebuie reinut, de asemenea, c toate valorile din subsetul respectiv sunt reprezentateexact. De asemenea, este evident faptul c operaiile aritmetice de nmulire i mprire se fac ntrun mod aproximativ. nmulind 1.121 cu 2.250 se obine valoarea teoretic 2.52225, dar aceasta nu se poate reprezenta n sistemul cu 3 cifre dup punctul zecimal. Ca atare, rezultatul este rotunjit la valoarea cea mai apropiat care se poate reprezenta, anume 2.522. Operaiile de adunare i scdere se fac exact, cu condiia ca rezultatul s nu depeasclimiteledomeniuluidereprezentare. n concluzie, reprezentarea n virgul fix este caracterizat de numrul de cifre reprezentateidenumruldecifrededupvirgul(poziiavirgulei).

Programarenlimbajdeasamblare 11 Reprezentarea n virgul fix se folosete n unele sisteme de conducere cu calculator a mainilorunelte industriale (sisteme de poziionare) i foarte importantnsistemeledeprogramefinanciareicontabile. La acestea din urm, reprezentarea n virgul fix are avantajul c toate puterile lui 10 (pozitive i negative) care fac parte din domeniul de valori sunt reprezentateexact. De exemplu, pentru a reprezenta sume de bani, este suficient s avem dou cifre dup virgul. La un bilan financiar, cnd se adun sau se scad sume de bani,esteesenialcaoperaiiledeadunareiscderessefacexact. Din motivele prezentate, n programele aplicative pentru finane (n general pentrudomeniuleconomic)sefolosetesistemuldereprezentarenvirgulfix. Reprezentareanvirgulmobil Reprezentarea n virgul mobil se folosete cu precdere n domeniile tiinifice i tehnice (sau, altfel spus, n toate domeniile n afar de cele economicofinanciare). naceastreprezentare,numerelesuntconsideratedeforma: (1)SMBE unde: S este numit bit de semn i este 1 pentru numere negative i 0 pentru numerepozitive M este numit mantis (sau fracie) i este un numr pozitiv subunitar reprezentatnbazaB Bestenumitbaz(uzualeste2sau16) Eestenumitexponentiesteunnumrntregcusemn. Mantisa M se numete normalizat dac prima cifr dup virgul este cifr semnificativ(estediferitdezero). Majoritatea sistemelor actuale folosesc baza B = 2. n acest caz, faptul c prima cifr a mantisei este diferit de 0 nseamn c aceasta este obligatoriu 1. Astfel,mantisaMverificcondiia(scrisnbaza2): 0.1(2)M<1 sau,nbaza10: 0.5(10)M<1 Exponentul se reprezint de obicei deplasat, n sensul c se memoreaz un numr de forma E + K, unde K este o constant astfel aleas nct E + K s fie totdeauna pozitiv. n felul acesta se rezolv problema memorrii semnului exponentului. De cele mai multe ori, deoarece prima cifr semnificativ a mantisei M este 1, aceast valoare nu se mai reprezint, ctignduse astfel unbitnspaiuldememorare(ncaresepoatememorabituldesemnS).

12 Capitolul1
Cea mai des folosit reprezentare standardizat este cea numit n simpl precizie, descris n cele ce urmeaz. n acest sistem, mantisa M are 24 de bii, iar exponentul E are 8 bii i se reprezint intern deplasat (adunat) cu 127. Mantisa este normalizat i nmulit cu 2, astfel nct condiia de normalizareeste1M<2. Bitul cel mai semnificativ al mantisei nu se mai reprezint intern, deoarece este totdeauna 1. Astfel, un numr real n simpl precizie se reprezint pe 32 de bii(4octei). Notnd cu f mantisa (fracia) care se reprezint intern, cu e exponentul deplasaticusbituldesemn,valoareaunuinumrrealestedatderelaia: (1)s1.f22f21...f1f02e127 n care s este bitul de semn, e = e7e6...e1e0 este exponentul deplasat cu 127, iar f = f22f21...f1f0 este mantisa (fracia) normalizat. Bitul cu valoarea 1 din formula de mai sus (bitul 23 al mantisei) nu se reprezint intern. Cei patru octei sunt reprezentai n Tabelul 1.5, n ordinea aezrii lor n memorie (n sens cresctoraladreselordememorie). Nu toate combinaiile posibile de bii din tabel sunt reprezentri valide. Astfel, numrul 0.0 se reprezint n mod unic prin s = 0, f = 0 i e = 0, aceasta fiind singura valoare pentru care e sau f pot fi nule. n afara valorii reale 0.0, exponentuldeplasattrebuiesfiecuprinsntre1i254. Exponentul 0 este permis numai pentru reprezentarea valorii reale 0.0 (deci i cu f = 0 i s = 0). Exponentul 255 (0FFH) este folosit pentru reprezentarea unor valori de excepie. Astfel, reprezentrile cu e = 0FFH, f = 7FFFFFH (toi biii 1) i s = 0 sau 1 sunt folosite pentru valorile notate +INF i -INF, care sunt cazuri de excepie (depiri aritmetice). Orice alte valori cu exponent 0 sau 255 sunt incorecte. Aceste valori incorecte mai sunt numite i NAN (de la Not A Number). Funcie de bitul de semn, pot exista valori +NAN sau NAN.
f7 f15 e0 s f6 f14 f22 e7 f5 f13 f21 e6 f4 f12 f20 e5 f3 f11 f19 e4 f2 f10 f18 e3 f1 f9 f17 e2 f0 f8 f16 e1

Tabelul 1.5 Reprezentarea n virgul mobil n simpl precizie

Altevalorireprezentativesunt:

Programarenlimbajdeasamblare 13 cel mai mic numr pozitiv reprezentabil este caracterizat de s = 0, f = 0, e = 1iarevaloareaaproximativ1.171038 cel mai mare numr pozitiv reprezentabil este caracterizat de s = 0, f = 7FFFFF,e=0FEHiarevaloareaaproximativ3.41038. Sconsidermctevaexempledereprezentare. Numrulreal0.0sereprezintprin4octeinuli. Numrul real 1 se exprim prin semnul s = 0, mantisa 1.0 i exponentul 0 (1 = (1)0 1.0 20). Fracia intern este f = 0, iar exponentul deplasat estee=127(saue=7FH). Numrul real 2 se exprim prin semnul s = 0, mantisa 1.0 i exponentul 1 (2 = (1)0 1.0 21). Fracia intern este f = 0, iar exponentul deplasat estee=128(saue=80H). Numrul real 0.5 se exprim prin semnul 0, mantisa 1.0 i exponentul 1 (0.5 = (1)0 1.0 21). Fracia intern este f = 0, iar exponentul deplasat estee=126(saue=7EH). Numrul real 1 se exprim prin semnul 1, mantisa 1.0 i exponentul 0 (1 = (1)1 1.0 20). Fracia intern este f = 0, iar exponentul deplasat este e=127(saue=7FH). Scriind bitul s, biii fraciei f i ai exponentului deplasat e ca n Tabelul 2.4, se obinreprezentrilepe4octeidemaijos: 0.0=00000000(s=0,f=0,e=0) 1.0=0000803F(s=0,f=0,e=7FH) 2.0=00000040(s=0,f=0,e=80H) 0.5=0000003F(s=0,f=0,e=7EH) 1.0=000080BF(s=1,f=0,e=7FH) Reprezentarea n virgul mobil este caracterizat prin numrul de cifre al mantisei(fraciei)inumruldecifrealexponentului. S observm c, la aceeai mantis, putem avea exponeni diferii ceea ce nseamn c virgula nu mai este pe o poziie fix, ci se deplaseaz dup ct de mare este exponentul. Acest fapt a condus la numele reprezentrii (virgul mobil). Avantajul acestei reprezentri este domeniul foarte mare. n simpl precizieputemreprezentanumerecuprinseaproximativntre1038i1038. Trebuie, de asemenea, remarcat c se reprezint corect numai numerele care se pot exprima ca sume de puteri (pozitive sau negative) ale lui 2 (n general ale bazei B). Exemplele de mai sus sunt din aceast categorie. Numerele 0.1, 0.01, 0.3 nu se reprezint exact n virgul mobil cu baza 2. De aceea, acest sistemnusefolosetenprogramepentrudomeniileeconomicofinanciare. Calculele aritmetice sunt aproximative, dar precizia este de cele mai multe ori suficient pentru aplicaiile uzuale. n reprezentarea n simpl precizie (pe 4 octei),preciziaasiguratestede107.

14 Capitolul1
Reprezentarea n precizie dubl (8 octei) este caracterizat de o mantis normalizat pe 53 de bii i un exponent pe 11 bii (deplasat cu 1023). Valoareaunuinumrrealndublprecizieestedatdeexpresia:
(1)s1.f51f50...f1f02e1023

n care s este bitul de semn, e = e10e9...e1e0 este exponentul deplasat cu 1023, iar f = f51f50...f1f0 este mantisa (fracia) normalizat. Bitul cu valoarea 1 din formula de mai sus (bitul 52 al mantisei) nu se reprezint intern. Structura celor 8octei(nordineacresctoareaadreselor)esteceadinTabelul1.6. Valorile corecte pentru exponentul deplasat sunt cuprinse ntre 1 i 1022. Numrul 0.0 se prezint n mod unic cu s = f = e = 0, iar valorile cu exponent 1023suntfolositepentru+INFiINF.
f7 f15 f23 f31 f39 f47 e3 s f6 f14 f22 f30 f38 f46 e2 e10 f5 f13 f21 f29 f37 f45 e1 e9 f4 f12 f20 f28 f36 f44 e0 e8 f3 f11 f19 f27 f35 f43 f51 e7 f2 f10 f18 f26 f34 f42 f50 e6 f1 f9 f17 f25 f33 f41 f49 e5 f0 f8 f16 f24 f32 f40 f48 e4

Tabelul 1.6 Reprezentarea n virgul mobil n dubl precizie Reprezentarea n precizie extins (10 octei) este caracterizat de o mantis normalizat pe 64 de bii i un exponent pe 15 bii (deplasat cu 16383). Valoareaunuinumrrealnprecizieextinsestedatdeexpresia: (1)s1.f62f61...f1f02e16383 n care s este bitul de semn, e = e14e13...e1e0 este exponentul deplasat cu 16383, iar f = f62f61...f1f0 este mantisa (fracia) normalizat. Bitul cu valoarea 1 din formula de mai sus (bitul 63 al mantisei) se reprezint intern ca un bit totdeauna egal cu 1, cu excepia valorii zero, cnd acest bit este 0. Structura celorzeceoctei(nordineacresctoareaadreselor)esteceadinTabelul1.7.

Programarenlimbajdeasamblare 15

f7 f15 f23 f31 f39 f47 f55 1 e7 s

f6 f14 f22 f30 f38 f46 f54 f62 e6 e14

f5 f13 f21 f29 f37 f45 f53 f61 e5 e13

f4 f12 f20 f28 f36 f44 f52 f60 e4 e12

f3 f11 f19 f27 f35 f43 f51 f59 e3 e11

f2 f10 f18 f26 f34 f42 f50 f58 e2 e10

f1 f9 f17 f25 f334 f41 f49 f57 e1 e9

f0 f8 f16 f24 f32 f40 f48 f56 e0 e8

Tabelul 1.7 Reprezentarea n virgul mobil n precizie extins Microprocesoarele din familia 80x86 sunt dotate cu circuite specializate (coprocesoare matematice) care folosesc cele trei tipuri de reprezentri n virgul mobil de mai sus. De asemenea, limbajul de asamblare specific acestor procesoare dispune de directive pentru definirea de constante reale n toateceletreiprecizii.

1.3.4Reprezentareadatelornenumerice
Pe lng date numerice, n memoria calculatorului trebuie reprezentate i alte tipuri de date. Un exemplu important l reprezint caracterele alfabetice (litere mari i mici), caracterele numerice (cifre zecimale), semnele de punctuaie i aanumitele caractere de control (folosite pentru comanda diverselor echipamenteperiferice). Dei exist mai multe sisteme de codificare a acestor tipuri de date, pe majoritatea calculatoarelor actuale (inclusiv pe IBMPC) se folosete codul standard ASCII. Denumirea sa provine din iniialele de la American Standard Code for Information Interchange (Codul Standard American pentru Schimb de Informaii). Codul ASCII standard este un cod pe 7 bii, deci cuprinde 128 de caractere distincte. Un caracter ASCII se reprezint pe un octet, n care bitul cel mai semnificativ este 0. Domeniul de valori este deci de la 0 la 127 (n zecimal) sau dela00la7F(nhexazecimal). Dintre cele 128 de caractere, 32 sunt caractere de control i nu au reprezentri grafice (nu sunt afiabile). Restul de 96 de caractere pot fi afiate pe ecranul calculatorului, la imprimant etc. Caracterele afiabile se noteaz de obicei prin scrierea simbolului grafic respectiv ntre apostrofuri. De exemplu, 'A' nseamn

16 Capitolul1
codul ASCII corespunztor literei A mare, '!' nseamn codul ASCII pentru semn deexclamareetc. Calculatorul IBMPC lucreaz cu un aanumit cod ASCII extins, n care se folosesc toi cei 8 bii ai unui octet. Setul ASCII standard este un subset al acestuicodASCIIextins. Tabelul 1.8 cuprinde toate codurile ASCII. Coloanele corespund primei cifre hexa, iar liniile, celei dea doua cifre. Primele dou coloane (n afar de codul 20H)iultimulcod(DELsau7F)reprezintcele32decaracteredecontrol. Deoarece caracterele de control nu au reprezentri grafice, ele au nume speciale (exprimate de obicei prin prescurtri de 2 sau 3 litere). Dintre caractereledecontroluzuale,potfiamintite: CR (Carriage Return). Este interpretat de perifericele de ieire, provocnd mutarea cursorului pe ecran la nceputul liniei curente. La imprimant, provoacmutareacaruluidetiprirelanceputulliniei LF (Line Feed). Provoac trecerea la linie nou (att la imprimant, ct i peecran) TAB (Horizontal Tabulation). Provoac deplasarea cursorului pe ecran sau a carului de tiprire cu un numr predefinit de poziii la dreapta sau ntr opoziiepredefinit BS (Backspace). Provoac deplasarea cursorului cu o poziie napoi (la stnga)sautergereacaracteruluidelastngacursorului DEL(Delete).Provoactergereacaracteruluiindicatdecursor BEL(Bel).Provoacemitereaunuisunetdeavertizare FF (Form Feed). Provoac avansul hrtiei (formularului) la pagin nou (la imprimant). O serie de coduri de control se folosesc n transmisiile de date, avnd semnificaii specifice. De exemplu, ACK (Acknowledge) se folosete pentru confirmarea transmisiei corecte a unui bloc de date, iar NAK (Negative Acknowledgement) pentru semnalarea unei transmisii incorecte. Dintrecaractereletipribileuzuale,sepotaminti: Literelemari'A'...'Z' Literelemici'a'...'z' Cifrelezecimale'0'...'9' Spaiul (SP), care are codul 20H i este tiprit ca un spaiu liber (de fapt nu se tiprete nimic, ci se las o pauz) caracterul SP (spaiu, ' ') se numeteiblank. Valorile numerice ale codurilor ASCII se exprim prin 2 cifre hexazecimale, n careprimacifrestelimitatla7F).

Programarenlimbajdeasamblare 17
24 25 26 23 22 21 20

0 NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI

1 DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US

2 SP ! # $ % & ' ( ) * + , . /

3 0 1 2 3 4 5 6 7 8 9 : < = > ?

4 @ A B C D E F G H I J K L M N O

5 P Q R S T U V W X Y Z [ \ ] ^ _

6 ` a b c d e f g h i j k l m n o

7 p q r s t u v w x y z { | } ~ DEL

0 1 2 3 4 5 6 7 8 9 A B C D E F

Tabelul 1.8 Codul ASCII standard

1.4Tipuridedateutilizatenlimbajdeasamblare
Limbajul de asamblare 80x86 opereaz cu anumite tipuri de date de baz. Aceste tipuri sunt recunoscute de ctre procesor i fac parte integrant din formatul anumitor instruciuni main. De asemenea, limbajul dispune de directivespecificepentrudefinireaacestortipuridedate. Caracteristic pentru un tip de date este domeniul de valori, care rezult att din tipul de date n sine, ct i dintro eventual interpretare funcie de context. Tipurilededatesunt: BYTE (1 octet) Acest tip de date ocup 1 octet i poate fi reprezentat att n memoria intern, ctintrunregistrude8biialprocesorului.Interpretriletipuluibytepotfi: ntregpe8biicusaufrsemn caracterASCII. DirectivapentrudefinireadatelordeacesttipesteDB(DefineByte).

WORD (2 octei)

18 Capitolul1
Acest tip de date ocup 2 octei i poate fi reprezentat att n memoria intern, ct i ntrun registru de 16 bii al procesorului. Interpretrile tipului wordpotfi: ntregpe16biicusaufrsemn secvendedoucaractereASCII adresdememoriede16bii. Directiva pentru definirea datelor de acest tip este DW (Define Word). Partea mai puin semnificativ este memorat la adrese mici. De exemplu, dac presupunem ntregul 1234H la adresa 1000H, atunci octetul 34H se va gsi la adresa 1000H, iar octetul 12H la adresa 1001H. Similar, se memoreaz i secvenelededoucaractereASCII. DOUBLE-WORD (4 octei) Acest tip de date ocup 4 octei i poate fi reprezentat att n memoria intern, ct i ntro pereche de registre de 16 bii sau ntrun registru de 32 de bii(laprocesoarelede32debii).Interpretriletipuluidwordpotfi: ntregpe32debiicusaufrsemn numrrealnsimplprecizie adresdememoriede32debii. Directiva pentru definirea datelor de acest tip este DD (Define DoubleWord). Valorile mai puin semnificative se memoreaz la adrese mici. n cazul adreselor pe 32 de bii, adresa de segment este memorat la adrese mari, iar deplasamentul(offsetul),laadresemici. QUAD-WORD (8 octei) Acest tip de date ocup 8 octei i poate fi reprezentat att n memoria intern, ct i ntro pereche de registre de 32 de bii (numai la procesoarele de32debii).Interpretriletipuluiqwordpotfi: ntregpe64debiicusaufrsemn numrrealndublprecizie DirectivapentrudefinireadatelordeacesttipesteDQ(DefineQuadWord). TEN-BYTES (10 octei) Acest tip de date ocup 10 octei i poate fi reprezentat att n memoria intern, ct i ntrunul din registrele coprocesoarelor matematice 80x87. Interpretriletipuluitbytepotfi: numr ntreg reprezentat ca secven de cifre BCD (mpachetate), cu semnmemoratexplicit numrrealnprecizieextins. DirectivapentrudefinireadatelordeacesttipesteDT(DefineTenBytes). n reprezentarea ntregilor, se consider numere cu maxim 19 cifre zecimale. Un grup de dou cifre se reprezint pe 1 octet, partea mai puin semnificativ

Programarenlimbajdeasamblare 19 fiind la adrese mici. n cadrul unui octet, cifra BCD mai semnificativ este n partea high a octetului. Cele 19 cifre BCD ocup aadar 76 de bii. Ultimul grup de 4 bii (partea high a octetului aflat la adresa cea mai mare) este destinat memorrii semnului. De fapt, semnul se memoreaz doar pe bitul cel mai semnificativ al acestui ultim octet. Asambloarele accept i numere cu 20 de cifre zecimale, att timp ct cifra cea mai semnificativ, care se va reprezentapeultimulgrupde4bii,nuintrnconflictcubituldesemn. Teoretic,valoareamaximcorectreprezentabileste:
+ 9999 99999 99999 99999

iarvaloareaminimeste:
- 9999 99999 99999 99999

darseacceptivaloridegenul:
+ 79999 99999 99999 99999 - 79999 99999 99999 99999

ncarecifraceamaisemnificativestereprezentatdoarpe3bii. Din motive de siguran, este bine s ne limitm la valorile garantate, adic la celmult19cifrezecimaleisemn. Sconsidermurmtorulexempludeprogram:
.model small .data b1 db b3 db b2 db w1 w2 d1 d2 d3 q1 q2 t1 t2 t3 t4 t5 t6 t7 end dw dw dd dd dd dq dq dt dt dt dt dt dt dt

-1, 10, 17H, 0FFH 'a', 'b' abcdef, 0 1234H, -1, 'AB' w1 12345678H, -1 1.0, -1.0, 0.5 d1 1000000000000002H, -1 1.0, -1.0 1234567890000012345 -1234567890000012345 9999999999999999999 -9999999999999999999 7999999999999999999 -7999999999999999999 1.0

n acest exemplu, este definit doar un modul de date, folosind directivele i tipurile de date existente n limbaj. Liniile care ncep cu un punct sunt directive

20 Capitolul1
care stabilesc modelul de memorie (.model) i, respectiv, definesc un segment dedate(.data).Directivaendmarcheazsfritulprogramului. Se definesc date cu cele 5 tipuri de directive (db, dw, dd, dq, dt), asociinduse acestora i nume simbolice (b1, w2 etc.). Fiierul listing obinut n urma asamblriiacestuiprogramare(ntrealtele)urmtorulconinut:
Turbo Assembler Version 2.0 A.ASM 1 0000 2 0000 3 0000 FF 0A 17 FF 4 0004 61 62 5 0006 61 62 63 64 65 66 00 6 7 000D 1234 FFFF 4142 8 0013 000Dr 9 10 0015 12345678 FFFFFFFF 11 001D 3F800000 BF800000+ 12 3F000000 13 0029 00000015sr 14 15 002D 1000000000000002+ 16 FFFFFFFFFFFFFFFF 17 003D 3FF0000000000000+ 18 BFF0000000000000 19 20 004D 01234567890000012345 21 0057 81234567890000012345 22 0061 09999999999999999999 23 006B 89999999999999999999 24 0075 79999999999999999999 25 007F F9999999999999999999 26 0089 3FFF8000000000000000 27 end 03/31/96 23:08:59 Page 1 .model small .data b1 db -1, 10, 17H, 0FFH b3 db 'a', 'b' b2 db abcdef, 0 w1 w2 d1 d2 d3 q1 q2 t1 t2 t3 t4 t5 t6 t7 dw dw dd dd dd dq dq dt dt dt dt dt dt dt 1234H, -1, 'AB' w1 12345678H, -1 1.0, -1.0, 0.5 d1 1000000000000002H, -1 1.0, -1.0 1234567890000012345 -1234567890000012345 9999999999999999999 -9999999999999999999 79999999999999999999 -79999999999999999999 1.0

Prima coloan listeaz numrul liniei din fiierul surs. Apoi este listat adresa i coninutul cmpului de date corespunztor unei linii surs. Dac acest coninut este listat pe mai multe linii, se folosete semnul + pentru a indica aceasta. Se remarc reprezentrile numerelor reale i ale ntregilor negativi. Simbolurile r i s indic faptul c este vorba de o adres relativ (deplasament) sau de segment. De exemplu, variabila d3 conine adresa de segment 0000 i deplasamentul 0015H, adic adresa relativ (pe 32 de bii) a variabilei d1. La ntregii BCD pe 10 octei, se observ memorarea explicit a bitului de semn: reprezentrilepentrut1it2diferdoarprinacestbit. Listingul nu indic i poziia fizic a octeilor n memorie. Urmtorul listing reprezintzonadememoriecorespunztoaremodululuidedatedemaisus:
ds:0000 FF 0A 17 FF 61 62 61 62 63 64 65 66 00 34 12 FF

Programarenlimbajdeasamblare 21
ds:0010 ds:0020 ds:0030 ds:0040 ds:0050 ds:0060 ds:0070 ds:0080 FF 3F 00 00 00 81 99 99 42 00 00 00 00 99 99 99 41 00 00 00 89 99 99 99 0D 80 00 F0 67 99 99 99 00 BF 10 3F 45 99 89 99 78 00 FF 00 23 99 99 99 56 00 FF 00 01 99 99 99 34 00 FF 00 45 99 99 99 12 3F FF 00 23 99 99 F9 FF 15 FF 00 01 99 99 FF 00 FF 00 00 09 99 FF 68 FF F0 00 99 99 FF 53 FF BF 89 99 99 00 02 00 45 67 99 99 00 00 00 23 45 99 79 80 00 00 01 23 99 99

Din examinarea acestui listing, se observ, de exemplu, reprezentarea intern a variabilei doubleword d1, aflat la adresa 0015H: secvena de octei este 78 56 34 12, deci la adrese mici se gsete partea mai puin semnificativ. Similar, variabila de tip word 'AB' (aflat la adresa 11H), este memorat prin secvena de octei 42H 41H. Acest listing este obinut la ncrcarea modului de date n memorie, cnd adresele de segment sunt relocate, deci corespund unor adrese fizice concrete. Adresa variabilei d1 (coninut n d3) apare aici n forma (5368:0015). Pentru valorile reale, se regsesc reprezentriledescrisen1.3.3. Variabila t1 (aflat la adresa 004DH) este reprezentat prin secvena de octei: 45 23 01 00 00 89 67 45 23 01, deci cifrele mai puin semnificative sunt la adrese mici, iar n cadrul unui octet, cifra mai semnificativ este n partea high. Variabila t2 (aflat la adresa 0057H) este reprezentat prin secvena: 45 23 01 00 00 89 67 45 23 81, ceea ce arat c bitul de semn (reprezentatprincifra8)estenparteahighaultimuluioctetdinreprezentare. Valorile maxime i minime sunt reprezentate la adresele 0061H i 006BH, prin secvenele: 99 99 99 99 99 99 99 99 99 09, respectiv: 99 99 99 99 99 99 99 999989. Se observ i reprezentarea valorilor t5 i t6, n forma 99 99 99 99 99 99 99 99 99 79 i, respectiv, 99 99 99 99 99 99 99 99 99 F9, n care apare cifraceamaisemnificativ7,cubituldesemn0sau1. Trebuie precizat c formatele de reprezentare pentru date numerice (ntregi sau reali)seregsescnaceeaiforminlimbajeledenivelnalt. n implementarea Borland PASCAL, exist caractere i ntregi pe 2, 4 i 8 octei, care corespund tipurilor de date byte, word, double word i quadword. De asemenea, exist tipuri de date n virgul mobil pe 4, 8 i 10 octei, n aceeaiformdereprezentareinterncaceadescrisn1.3.3. n implementarea Borland C exist tipul char (1 octet), tipuri ntregi pe 2 i 4 octei, cu sau fr semn (int, long, unsigned int, unsigned long) i tipuri n virgul mobil pe 4, 8 i 10 octei (float, double, long double), cu aceleai reprezentriinternecaceledin1.3.3.

1.4Arhitecturaprocesorului8086.Formareaadreseifizice

22 Capitolul1
Arhitectura procesorului 8086, din punctul de vedere al programului utilizator, este ilustrat schematic n Figura 1.2. Sunt figurate registrele accesibile prin program.

Figura 1.2 Registrele procesorului 8086 Toate registrele sunt de 16 bii. O serie de registre (AX, BX, CX, DX) sunt disponibile i la nivel de octet, prile mai semnificative fiind AH, BH, CH i DH, iar cele mai puin semnificative, AL, BL, CL i DL. Denumirile registrelor sunt: AXregistruacumulator BXregistrudebazgeneral CXregistrucontor DXregistrudedate BPregistrudebazpentrustiv(basepointer) SPregistruindicatordestiv(stackpointer) SIregistruindexsurs DIregistruindexdestinaie Registrul notat FLAGS cuprinde flagurile procesorului sau ale bistabililor de condiie,iarregistrulIP(instructionpointer)estecontorulprogram. Denumirileregistrelordesegmentsunt: CSregistrudesegmentdecod(codesegment) DSregistrudesegmentdedate(datasegment) SSregistrudesegmentdestiv(stacksegment)

Programarenlimbajdeasamblare 23 ESregistrudesegmentdedatesuplimentar(extrasegment) Se observ c denumirile registrelor de segment corespund zonelor principale ale unui program executabil. Astfel, perechea de registre (CS:IP) va indica totdeauna adresa urmtoarei instruciuni care se va executa, iar perechea (SS:SP) indic totdeauna adresa vrfului stivei. Registrele DS i ES sunt folositepentruaaccesadate. Procesorul 8086 dispune de adrese pe 20 de bii, fiind capabil s adreseze 1 megaoctet de memorie (220). Se pune problema cum se formeaz adresa fizic pe 20 de bii (deci pe 5 cifre hexa), deoarece toate registrele procesorului sunt de 16 bii, putnd codifica adrese n domeniul 00000FFFFH (pe 4 cifre hexa), decintrunspaiudemaxim64KO. Memoria unui sistem cu procesor 8086 este divizat n segmente. Un segment este o zon continu de memorie, de lungime maxim de 64 KO, care ncepe la o adres fizic multiplu de 4. Acest fapt nseamn c ultima cifr hexa a adresei de nceput a unui segment este totdeauna 0. Ca atare, aceast cifr se poate omite i adresa de segment se poate reprezenta tot pe 16 bii. Adresele de nceput ale segmentelor se vor gsi ntotdeauna ntrunul din cele 4 registre de segment. Adresarea n interiorul unui segment se realizeaz printrun deplasament (offset) relativ la nceputul segmentului. Deoarece un segment nu poate depi 64 KO, deplasamentul se poate memora tot pe 16 bii. Deplasamentul poate fi oconstantsauconinutulunuiregistrucarepermiteadresareamemoriei. n concluzie, pentru adresarea unui octet de memorie, se folosesc dou cantiti pe 16 bii: o adres de segment (coninut obligatoriu ntrun registru de segment) i un deplasament. Deoarece ambele cantiti sunt pe 16 bii, se vorbete de adrese (sau pointeri) de 32 de bii, dei adresa fizic estedoarpe20debii. Formarea adresei fizice (pe 20 de bii) este realizat automat (prin hardware) dectreocomponentaprocesorului,conformFigurii1.3. Concret, adresa fizic se obine prin deplasarea adresei de segment cu 4 bii la stnga i prin adunarea deplasamentului. Pentru specificarea unei adrese complete (de 32 de bii), se folosete notaia (segment:offset) sau (registru_segment:offset). De exemplu, putem specifica o adres prin (18A3:5B27)sauprin(DS:5B27). Trebuie remarcat faptul c asocierea (segment:offset) adres fizic nu este biunivoc, deoarece la o aceeai adres fizic pot s corespund mai multe perechi (segment:offset). De exemplu, perechile (18A3:5B27) i (18A2:5B37) reprezint aceeai adres fizic. n situaia n care deplasamentul este redus la minim, adic n domeniul 0F, corespondena devine biunivoc. Adresele deacesttipsenumescadresenormalizatesaupointerinormalizai.

24 Capitolul1

Figura 1.3 Formarea adresei fizice O adres complet de 32 de bii este memorat cu offsetul la adrese mici i cu adresa de segment la adrese mari. Adresele complete se pot obine cu directivaDD(DefineDoubleWord). Registrul de flaguri (bistabili de condiie) al procesorului 8086 are configuraia din Figura 1.4. O serie de flaguri sunt flaguri aritmetice: acestea sunt poziionate la 0 sau la 1 ca urmare a unor operaii aritmetice sau logice. Celelalteflaguricontroleazanumiteoperaiialeprocesorului. Semnificaiaflaguriloresteurmtoarea: CF (Carry Flag, bistabil de transport) semnific un transport sau un mprumut din/n bitul cel mai semnificativ al rezultatului, de exemplu la operaiideadunaresaudescdere. PF (Parity Flag, flag de paritate) este poziionat n aa fel nct numrul de bii egali cu 1 din octetul cel mai puin semnificativ al rezultatului, mpreun cu flagul PF, s fie impar altfel formulat, suma modulo2atuturorbiilordinoctetulc.m.p.s.ialuiPFsfie1. AF (Auxiliarry Carry Flag, bistabil de transport auxiliar) indicuntransportsauunmprumutdin/nbitul4alrezultatului.

Programarenlimbajdeasamblare 25 ZF (Zero Flag, bistabil de zero) este poziionat la 1 dac rezultatuloperaieieste0. SF (Sign Flag, bistabil de semn) este poziionat la 1 dac b.c.m.s.alrezultatului(bituldesemn)este1. OF (Overflow Flag, bistabil de depire) este poziionat la 1 dac operaia a condus la o depire de domeniu a rezultatului (la operaiicusaufrsemn).

Figura 1.4 Registrul de flaguri al procesorului 8086 TF (Trap Flag, bistabil de urmrire) dac este poziionat la 1, se foreaz o ntrerupere, pe un nivel predefinit, la execuia fiecrei instruciuni acest fapt este util n programele de depanare, n care este posibilrulareapascupasaunuiprogram. IF (Interrupt Flag, bistabil de ntreruperi) dac este poziionat la 1, procesorul ia n consideraie ntreruperile hardware externe altfel, acesteasuntignorate. DF (Direction Flag, bistabil de direcie) precizeaz sensul (cresctor sau descresctor) de variaie al adreselor la operaiile cu irurideocteisaudecuvinte. Flagurile CF, PF, AF, ZF, SF i OF sunt numite flaguri aritmetice. Flagurile TF, IFiDFsuntnumiteflaguridecontrol.

1.5Modurideadresare
Pentru a scrie un program ASM ntro form ct mai simpl, se pot folosi directivelesimplificatededefinireasegmentelor.Acesteasunt: .modelsmall(precizeazunmodeldememorie) .code(definiredesegmentdecod) .stackn(definiredesegmentdestiv) .data(definiredesegmentdedate) endetichet(sfritlogicalprogramului) n principiu, segmentul de cod va cuprinde programul executabil (instruciuni), iar segmentul de date va cuprinde date definite de utilizator. Segmentul de stiv nu este folosit explicit. Comentariile se scriu folosind simbolul . Ceea ce urmeazduppnlasfritullinieicurenteesteconsideratcomentariu.

26 Capitolul1
Instruciunile procesorului 8086 pot avea unul sau doi operanzi, care pot fi registre sau operanzi aflai n memorie. Cnd exist doi operanzi, unul este obligatoriuunregistru(decinupotfidoioperanzinmemorie). Modurile de adresare specific modul n care se calculeaz adresa operandului aflat n memorie. Se folosesc denumirile de adres de segment (AS) pentru adresa de nceput a segmentului n care se gsete operandul i adres efectiv (AE), pentru deplasamentul operandului n cadrul segmentului respectiv. Adresa de segment i adresa efectiv formeaz adresa fizic (AF), conform mecanismului descris n 1.4. Adresa de segment este furnizat deunuldincele4registredesegment. Operanzii pot fi de tip octet sau de tip word, iar operaiile se pot face numai ntre operanzi de acelai tip. Tipul operandului aflat n memorie rezult, de obicei, din context (din registrele folosite). n situaiile n care acest lucru nu este posibil, se folosete operatorul ptr al limbajului de asamblare, n forma byte ptrsauwordptr,pentruaexplicitatipuloperandului. Adresare imediat nacestmoddeadresare,operandulaparechiarninstruciune.Deexemplu:
mov add ax, 1 bx, 2 ; Pune in AX valoarea 1 ; Aduna 2 la BX

Adresare direct Adresa efectiv a operandului este furnizat printrun deplasament n interiorul segmentuluicurent(veziFigura1.5).
.data VAL .code mov bx, VAL ; ; ; ; ; ; Pune in BX continutul locatiei VAL in formatul instructiunii, expresia VAL se va inlocui cu deplasamentul in cadrul segmentului de date Deplasament explicit dw 1

add

cx, [100]

Programarenlimbajdeasamblare 27 Figura 1.5 Adresare direct Prima instruciune nseamn pune coninutul locaie VAL n BX, ceea ce va conduce la o valoare a registrului BX egal cu 1. A doua instruciune nseamn adun la CX coninutul locaiei de memorie de la adresa efectiv 100. De observat prezena parantezelor drepte: fr ele, instruciunea ar fi nsemnat adun valoarea 100 la registrul CX. n ambele instruciuni, operandulaflatnmemorieesteconsideratdetipword. AcestmoddeadresarefoloseteregistrulDScaregistruimplicitdesegment. Adresare indirect (prin registre) Adresa efectiv a operandului este dat de coninutul registrelor BX, SI sau DI (veziFigura1.6).RegistrulimplicitdesegmentesteDS.

Figura 1.6 Adresare indirect ntextulsurssescrie,deexemplu:


mov mov add ax, [bx] [di], cx byte ptr [si], 2 ; ; ; ; ; ; ; ; Pune in AX continutul locatiei de memorie de la adresa data de BX Pune continutul lui CX in locatia de la adresa data de DI. Aduna 2 la octetul aflat la adresa data de SI

n primele dou instruciuni, operandul aflat n memorie este considerat de 16 bii (datorit celuilalt operand, care este un registru de 16 bii). Dac a treia instruciunearfiscris:
add [si], 2

28 Capitolul1
asamblorul nu ar ti tipul operandului din memorie. Instruciunea poate fi interpretat ca adun 2 la octetul de la adresa dat de SI sau adun 2 la cuvntul de la adresa dat de SI i sar obine un mesaj de eroare la asamblare.Folosireaoperatoruluiptreliminaceastambiguitate. Adresare bazat sau indexat Adresa efectiv se obine adunnd la unul din registrele de baz (BX sau BP) sau la unul din registrele index (SI sau DI) un deplasament constant pe 8 sau 16 bii (vezi Figura 1.7). Registrul de segment implicit este DS (dac se folosescBX,SIsauDI)i,respectiv,SS(dacsefoloseteBP). Forma de memorare a deplasamentului (pe 8 sau 16 bii) este determinat de asamblor.ntextulsurs,sescriepurisimpluundeplasamentconstant.

Figura 1.7 Adresare bazat sau indexat Se pot folosi diverse forme de scriere, ca n exemplul de mai jos, n care bx este (din punct de vedere al mecanismului de adresare) adres de baz, iar VAL este un deplasament constant. Din punct de vedere al programului, care i propune s acceseze elementele tabloului de octei VAL, semnificaia este exact invers: VAL este adresa de nceput a tabloului (deci o adres de baz), iarbxesteunindice(undeplasament).
.data VAL .code mov mov mov mov mov bx, ax, ax, ax, ax, 5 VAL[bx] bx[VAL] [bx+VAL] [bx].VAL dw 10 dup (0) ; Definire de tablou de 10 ; octeti

Programarenlimbajdeasamblare 29 Este posibil i alt mod de acces, n care se ncarc registrul BX cu deplasamentul tabloului VAL (folosind operatorul offset) i se folosete un indiceexplicit.
mov mov mov mov mov bx, ax, ax, ax, ax, offset VAL 5[bx] bx[5] [bx+5] [bx].5

n aceast situaie, adresa de baz (coninut n BX) este adresa de nceput atablouluiVAL. Trebuie remarcat c, n textul surs, toate formele de adresare se scriu cu operatoruldeindexare(parantezedrepte).Deexemplu,sepoatescrie:
mov mov mov ax, [bx] ax, [100] ax, [bx+100] ; Adresare indirecta ; Adresare directa ; Adresare bazata

De remarcat c folosirea registrului BP cu un deplasament nul permite o form de scriere asemntoare cu adresarea indirect, dar codificat intern ca adresarebazat:
mov mov ax, [bx] ax, [bp] ; Adresare indirecta ; Adresare bazata cu ; deplasament nul

Adresare bazat i indexat Adresa efectiv este format prin adunarea unuia din registrele de baz (BX sau BP) cu unul din registrele index (SI su DI) i cu un deplasament de 8 sau 16bii(veziFigura1.8).

Figura 1.8 Adresare bazat i indexat

30 Capitolul1
Registrele de segment implicite sunt DS (dac se folosete BX cu SI sau cu DI) i, respectiv, SS (dac se folosete BP cu SI sau cu DI). Deplasamentul poate fi inul.ntextulsurssefoloseteoperatoruldeindexare[]:
mov mov mov mov ax, ax, ax, ax, [bx][si] [bx+si+7] [bx+si].7 [bp][di][7]

n descrierea modurilor de adresare, sa precizat de fiecare dat registrul implicit de segment care particip la formarea adresei fizice a operandului aflat n memorie. Acest registru implicit este DS n toate modurile de adresare care nu implic registrul BP i, respectiv, SS, n modurile de adresare n care participregistrulBP. Aceste reguli implicite pot fi modificate prin folosirea prefixelor de segment. Un prefix de segment este un octet care apare naintea codului instruciunii main i care identific explicit registrul de segment folosit. n textul surs, se scrieunregistrudesegment,urmatde:,nainteaoperanduluiaflatnmemorie:
mov mov mov bx, ds:[bp+7] ax, cs:[si][bx+3] ax, ss:[bx]

Evident, gestiunea a ceea ce se gsete n segmentele adresate n acest fel cadensarcinaprogramatorului.

1.6Codificareainternainstruciunilor
Instruciunile procesorului 8086 pot fi codificate pe un numr de octei cuprins ntre 1 i 6. Codificarea cuprinde codul instruciunii (tipul operaiei), modul de adresare, deplasamentul operandului aflat n memorie (pe 8 sau 16 bii) sau adresa efectiv (n cazul adresrii directe), date (operanzi) imediate, pe 8 sau 16 bii. Pe lng formatul propriuzis, mai poate exista un prefix de segmentsauunprefixderepetare. Formatulgeneralalinstruciunilor8086esteilustratnFigura1.9. La instruciunile cu doi operanzi, un operand este obligatoriu de tip registru i este codificat de cmpul REG, iar cellalt este registru sau operand n memorie i este codificat de cmpul R/M sau de cmpurile R/M i MOD. Semnificaia cmpurilordinFigura1.9esteurmtoarea: Cmpul D (destinaie)codificsensuloperaiei: D=0 R/MR/MoperaieREG D=1 REGREGoperaieR/M Deexemplu,codificrileinstruciunilor:
add [bx], si

Programarenlimbajdeasamblare 31
add si, [bx]

vor diferi numai prin cmpul D (aceeai operaie i aceiai operanzi, dar difer sensul). Cmpul W (word)codificlungimeaoperanzilor(octetsaucuvnt): W=0 operaielaniveldeoctet W=1 operaielaniveldecuvnt Deexemplu,instruciunile:
add add ax, bx al, bl

vordiferidoarprincmpulW. Cmpul REGidentificoperanduldetipregistru. Cmpul R/M identific al doilea operand de tip registru sau un registru care particip la formarea adresei efective a operandului aflat n memorie. Cmpul MODcodificmoduldeadresare: MOD = 11 nseamn c al doilea operand este tot de tip registru(codificatdecmpulR/M). MOD = 00 nseamn adresare direct (R/M = 6), indirect (R/M = 4, 5, 6) sau adresare bazat i indexat cu deplasament nul (R/M = 0, 1, 2, 3). n aceste moduri de adresare, octeii 3 i 4 din Figura 1.9 lipsesc din formatul instruciunii (cu excepia cazului R/M = 6, adic al adresrii directe). MOD = 01 nseamn adresare bazat (R/M = 6, 7), indexat (R/M = 4, 5) sau bazat i indexat (R/M = 0, 1, 2, 3), toate cu un deplasament de 8 bii. n aceste moduri de adresare, octetul 4 din Figura 1.9 lipsete dinformatulinstruciunii.

32 Capitolul1

Figura 1.9 Formatul instruciunilor 8086 MOD = 10 este asemntor cu MOD = 01, dar deplasamentele sunt pe 16 bii. n aceste moduri de adresare, octeii 3 i 4 din Figura 1.9 sunt prezeninformatulinstruciunii.

SituaiiledemaisussuntdescrisesinteticnTabelul1.10.

Programarenlimbajdeasamblare 33

MOD R/M 0 1 2 3 4 5 6 7 W=0 AL CL DL BL AH CH DH BH

11 W=1 AX CX DX BX SP BP SI DI

00

01

11

(BX)+(SI) (BX)+(DI) (BP)+(SI) (BP)+(DI) (SI) (DI) direct (BX)

(BX)+(SI)+d8 (BX)+(DI)+d8 (BP)+(SI)+d8 (BP)+(DI)+d8 (SI)+d8 (DI)+d8 (BP)+d8 (BX)+d8

(BX)+(SI)+d16 (BX)+(DI)+d16 (BP)+(SI)+d16 (BP)+(DI)+d16 (SI)+d16 (DI)+d16 (BP)+d16 (BX)+d16

Tabelul 1.10 Codificarea modurilor de adresare

Capitolul2
Setuldeinstruciuni8086
Procesoarele din familia Intel dispun de un set puternic de instruciuni aritmetice, logice, de transfer i de control, ceea ce permite ncadrarea acestor procesoarenclasaCISC (Complex Instruction Set Computer). n cadrul acestui capitol, sunt prezentate n detaliu instruciunile de baz ale familiei de procesoare Intel. n general, pentru toate tipurile de instruciuni, se poate folosi orice mod de adresare (inclusiv cu prefixe de segment) expuse n capitolul anterior. Acolo unde este cazul, se specific tipurile interzise de adresare. Setuldeinstruciuniestegrupatn6clase: instruciuni de transfer, care deplaseaz date ntre memorie sau porturi de intrare/ieire i registrele procesorului, fr a executa nici un fel deprelucrareadatelor instruciuni aritmetice i logice, care prelucreaz date n format numeric instruciuni pentru iruri, specifice operaiilor cu date alfanumerice instruciuni pentru controlul programului, care n esen se reduclasalturiilaapelurideproceduri instruciuni specifice ntreruperilorhardisoft instruciuni pentru controlul procesorului. Aceast mprire este realizat dup criterii funcionale. De exemplu, instruciunile PUSH i POP sunt considerate ca instruciuni de transfer, dei, la prima vedere, ar putea fi considerate instruciuni specifice procedurilor. Acelai lucru despre instruciunile IN i OUT, care interfaeaz procesorul cu lumea exterioar: ele sunt considerate instruciuni de transfer, dei ar putea fi considerate instruciuni de intrare/ieire. Intrrile i ieirile sunt ns cazuri particularedetransfer. Fiecare categorie de instruciuni este nsoit de specificarea explicit a bistabililordecondiiecaresuntmodificainurmaexecuiei.

35Capitolul2

2.1Instruciunidetransfer
Instruciunile de transfer presupun o copiere a unui octet sau a unui cuvnt de la o surs la o destinaie. Aceast copiere (atribuire) va fi desemnat uneori printro sgeat, de la surs ctre destinaie. Destinaia poate fi un registru, o locaie de memorie sau un port de ieire, iar sursa poate fi un registru, o locaie de memorie, date imediate (constante) sau un port de intrare. Cu excepia cazului important al instruciunilor PUSH i POP (2.1.1), sursa i destinaianupotfisimultanlocaiidememorie. Instruciunile de transfer se clasific n instruciuni generale, specifice acumulatorului,specificeadreselorispecificeflagurilor. n specificarea destinaiei i a sursei, se vor folosi notaiile segment:offset pentru adrese i notaia (x), pentru a desemna coninutul lui x. Notaia cu paranteze se poate extinde pe mai multe nivele. De exemplu, (BX) nseamn coninutul registrului BX, iar ((BX)) nseamn coninutul locaiei de memorie adresate de BX (implicit prin DS). Similar ES:((BX)) va nsemna coninutullocaieidememorieadresatederegistreleESiBX. Cu excepia instruciunilor SAHF i POPF (2.1.4), nici o instruciune de transfernumodificvreunbistabildecondiie.

2.1.1InstruciunidetransfergeneraleMOV,PUSH,POP,XCHG
InstruciuneaMOV(MoveDataTransferdate) Formatulgeneraleste:
MOV destinatie, sursa ; (destinatie) sursa

n care surs i destinaie (operanzii) sunt octei sau cuvinte respectnd reguliledescrisemaisus. Urmtoareleoperaiisuntilegale: sursaidestinaianupotfiambeleoperanzinmemorie nupotfifolositeregistreleFLAGSiIP operanziinupotaveadimensiunidiferite registrulCSnupoateapreacadestinaie. Procesoruloriginal8086arerestriciilesuplimentare: nupotfitransferatedateimediatentrunregistrudesegment operanziinupotfisimultanregistredesegment. Aceste ultime dou restricii au fost relaxate la variantele ulterioare (80286 i peste).Exempledeinstruciunicorecte:
MOV MOV MOV AX, BX AL, CH VAL[BX][SI], AL

Programarenlimbajdeasamblare36
MOV byte ptr [BX+100], 5

Ultima instruciune de mai sus ar fi fost ambigu fr utilizarea operatorului ptr: MOV [BX+100], 5 se poate interpreta ca pune valoarea 5 n octetul de la adresa DS:BX+100 sau, la fel de bine, pune valoarea 5 la cuvntul de la adresa DS:BX+100. Forma byte ptr precizeaz c este vorba de un transfer peoctet. Exempledeinstruciuniincorecte:
MOV MOV MOV AL, BX [BX], [SI] CS, AX ; operanzi de lungime diferita ; ambii operanzi in memorie ; registrul cs apare ca destinatie

Dereinutcoinstruciunedeforma:
.data ALFA .code MOV AL, ALFA DB 1

ncarc n AL coninutul locaiei de memorie ALFA. Dac se dorete ncrcarea adresei efective a variabilei ALFA, se poate folosi operatorul OFFSET:
MOV BX, OFFSET ALFA

sauinstruciuneaLEA(2.1.3). InstruciuneaPUSH(PushDataSalveazdatenstiv) Formageneraleste:


PUSH sursa

n care surs este un operand pe 16 bii (registru general de 16 bii, registru de segment sau locaie de memorie), iar semnificaia este copiaz surs n vrfulstivei.Concret,execuiainstruciuniisefacedupsecvena:
(SP) (SP) - 2 SS : ((SP)+1 : (SP)) sursa

ceea ce nseamn c se decrementeaz SP cu 2 i n octeii de la adresele (SP)+1 i (SP) din segmentul de stiv se copiaz operandul surs. Copierea respect regula de memorare a cantitilor pe mai muli octei i anume, partea mai puin semnificativ (partea low) se memoreaz la adrese mici. O exprimaredetaliatainstruciuniiarputeafi:
(SP) (SP) - 2 SS : ((SP)+1) SS : ((SP)) high (sursa) low (sursa)

37Capitolul2
Exempledeinstruciunicorecte:
PUSH PUSH PUSH PUSH PUSH BX ES [BX] [BP+5] ES:[BX][SI+4]

Exempludeinstruciuniincorecte:
PUSH AL ; Operand pe 1 octet

InstruciuneaPOP(PopDataRefdatedinstiv) Formageneraleste:
POP destinatie

n care destinaie este un operand pe 16 bii (registru general de 16 bii, registru de segment sau locaie de memorie), iar semnificaia este copiaz coninutul vrfului stivei n destinaie. Registrul CS nu poate aprea ca destinaie.Concret,execuiainstruciuniisefacedupsecvena:
destinatie (SP) SS : ((SP)+1 : (SP)) (SP) + 2

ceea ce nseamn c se transfer octeii de la adresele (SP)+1 i (SP) din segmentul de stiv n operand (destinaie) i apoi se incrementeaz SP cu 2. Oexprimaredetaliatainstruciuniiarputeafi:
high (destinatie) low (destinatie) (SP) SS : ((SP)+1) SS : ((SP)) (SP) + 2

Exempledeinstruciunicorecte:
POP POP POP POP POP BX ES ES:[DI] [BP+5] SS:[BX+4]

Exempledeinstruciuniincorecte:
POP POP AL CS ; Operand pe 1 octet ; Registrul cs

Din analiza instruciunilor PUSH i POP, reiese c o secven de refaceri ale unor cantiti salvate n stiv (de exemplu, coninutul unor registre) trebuie scrisnordineinvers.Dacsecvenadesalvareafost:
PUSH PUSH AX BX

Programarenlimbajdeasamblare38
PUSH CX

atuncisecvenaderefaceretrebuiesfie:
POP POP POP CX BX AX

Dac registrele de mai sus conin valorile AX = 1234H, BX = 5678H i CX = 9ABCH, iar registrul SP conine (nainte de salvri) valoarea 1288H, atunci imagineastiveivaficeadinFigura2.1.

Figura 2.1 Imaginea stivei dup o secven de instruciuni PUSH i POP La operaiile cu stiva, trebuie avut grij ca o secven de refacere s aduc indicatorul SP la valoarea de dinainte de secvena de salvare. Acest lucru nseamn c, de regul, numrul operaiilor POP trebuie s coincid cu cel al operaiilorPUSH. Tot ca regul general, nu este indicat s se modifice explicit locaiile aflate n josul stivei, adic la valori mai mari sau egale cu valoarea curent a registrului SP. n acele locaii se pot afla informaii a cror alterare ar putea compromite definitiv execuia programului. Trebuie, deci, folosite cu atenie secveneledegenul:
MOV MOV BX, SP SS:[BX], AX

39Capitolul2
MOV byte ptr SS:[BX+2], 1

Instruciunile PUSH i POP se mai pot folosi la transferul indirect al unor registre.Secvena:
PUSH POP DS ES

copiazconinutulregistruluiDSnES,lsndindicatorulSPneschimbat. Instruciunile PUSH i POP realizeaz de fapt un transfer din memorie n memorie. Dac operandul din cele dou instruciuni este o locaie de memorie,ceeacetransferlaPUSHesteconinutulaceleizone.Secvena:
.data X .code PUSH X dw 100

va pune n vrful stivei valoarea 100 (coninutul lui X). Dac se dorete punerea n stiv a adresei efective sau complete a variabilei X, se va folosi instruciunea MOV i operatorul OFFSET sau instruciunea LEA (vezi 2.1.3), respectiv registrul de segment care adreseaz curent segmentul respectiv. Dac segmentul n care e definit variabila nu este adresat n mod curent de nici un registru de segment, se poate folosi operatorul SEG, care furnizeaz segmentulncareestedefinitoperandul:
.code LEA PUSH PUSH ; ; ; Sau ... MOV PUSH MOV PUSH AX, OFFEST X AX AX, SEG X AX ; Offset-ul lui X ; Adresa de segment a lui X AX, X AX DS ; Offset-ul la adrese mici ; Apoi segmentul

InstruciuneaXCHG(ExchangeDataInterschimbdate) Formageneraleste:
XCHG destinatie, sursa

iar semnificaia este cea de interschimbare a sursei cu destinaia. Registrele de segment nu pot aprea ca operanzi i, bineneles, cel puin un operand trebuiesfieregistru. Exempledeinstruciunicorecte:
XCHG XCHG AL, AH BX, SI

Programarenlimbajdeasamblare40
XCHG ES:[BX], AX

Exempledeinstruciuniincorecte:
XCHG XCHG AL, BX ES, AX ; Operanzi de lungime diferita ; Registru de segment

Instruciunea XCHG este util la interschimbarea a dou cantiti aflate n memorie. Dac op1 i op2 sunt doi operanzi aflai n memorie, care trebuie interschimbai, secvena standard de interschimbare (folosind un registru generalreg)este:
MOV XCHG MOV reg, op1 reg, op2 op1, reg

2.1.2InstruciunidetransferspecificeacumulatoruluiIN.OUT,XLAT
InstruciuneaIN(InputDataCitetedatedelaportdeintrare) Formageneraleste:
IN destinatie, port

n care destinaie este registrul AL sau AX, iar port este fie o constant cuprins ntre 0 i 255, fie registrul DX. Variantele noi de procesoare accept orice registru n locul lui AL sau AX. Semnificaia este c se execut o citire de la portul de intrare specificat, pe 8 sau 16 bii, dup cum sa specificat registrul AL sau AX. La variantele noi de procesoare (80286 i peste), registrele ALsauAXpotfisubstituitecuoriceregistregenerale. InstruciuneaOUT(OutputDataScriedatelaportdeieire) Formageneraleste:
OUT destinatie, port

n care destinaie este registrul AL sau AX, iar portul de ieire este specificat lafelcalainstruciuneaIN. Instruciunile IN i OUT sunt singurele instruciuni propriuzise care pot realiza interaciunea procesorului cu alte dispozitive. Unele arhitecturi de calculatoare au organizat memoria n aa fel nct zone din spaiul adresabil sunt dedicate unor echipamente periferice, i nu unor zone propriuzise de memorie. Accesul la zonele respective de memorie va nsemna de fapt un acces la echipamentul periferic. Asemenea sisteme de intrri/ieiri se numesc detipmemorymapped(intrriieiriorganizatecaspaiudememorie). S considerm c un echipament periferic necesit un port de stare i un port de date, ambele pe 8 bii. ntrun sistem de intrriieiri obinuit, vor exista dou porturi de intrare, de exemplu, 0F8H i 0F9H, dedicate perifericului

41Capitolul2
respectiv. ntrun sistem de tip memorymapped, vor exista dou adrese, de obicei adiacente, de exemplu c800:0000 i c800:0001, corespunztoare porturilor de stare i de date. Secvenele de citire stare, respectiv date, n cele doutipurideintrri/ieirivorfi:
IN IN MOV MOV MOV AL, AL, ES, AL, AL, 0F8H 0F9H 0C800H ES:[0] ES:[1] ; Citire stare ; Citire date ; Citire stare ; Citire date

InstruciuneaXLAT(TranslateTranslateaz) Instruciuneanuareoperanzi,iarsemnificaiaeste:
(AL) DS : ((BX) + (AL))

adic se aduce n AL coninutul octetului de la adresa (BX)+(AL). Aceast instruciune este folosit mpreun cu tabele de translatare (de unde i numele), utile n conversia unor tipuri de date. De exemplu, dac dorim s convertim o valoare numeric ntre 0 i 15 la cifra hexa corespunztoare, putem folosisecvena:
.data TABELA .code MOV XLAT BX, OFFSET TABELA DB '0123456789ABCDEF'

prin care se ncarc n BX offsetul tabelei de octei i se face apoi translatarea.

2.1.3InstruciunidetransferspecificeadreselorLEA,LDS,LES
Aceste instruciuni transfer o adres efectiv ntrun registru general sau o adrescompletpe32debiintroperechederegistre. InstruciuneaLEA(LoadEffectiveAddressncarcadresaefectiv) Formageneraleste:
LEA registru, sursa

n care sursa este un operand aflat n memorie, specificat printrun mod oarecare de adresare. Efectul este copierea adresei efective a operandului (offsetulncadrulsegmentului)nregistrulgeneralspecificat.Exemple:
LEA LEA BX, ALFA DI, ALFA [BX] [SI]

Programarenlimbajdeasamblare42 Un calcul similar al adresei efective se obine i cu operatorul OFFSET i instruciunea MOV, calcul care se face ns la asamblare. Astfel, instruciuneaLEApermiteimodurideadresarebazati/sauindexat. Instruciunea LEA se folosete pentru ncrcarea registrelor de baz sau de segment cu adresele efective ale unor operanzi din memorie, n vederea unor adresriulterioare.Secvena:
.data VECTOR .code LEA MOV MOV BX, VECTOR SI, 4 AX, [BX][SI] DW 10, 20, 30, 40, 50

vancrcanAXaltreileaelementaltablouluiVECTOR. Instruciunile LDS (Load Data Segment ncarc DS) i LES (Load Extra Segment ncarcES) Formageneraleste:
LDS LES reg, sursa reg, sursa

n care reg este un registru general de 16 bii, iar sursa este un operand de tip doubleword aflat n memorie, care conine o adres complet de 32 de bii. Efectulinstruciuniieste:
(reg) (DS)/(ES) ((sursa)) ((sursa)+2)

adic se ncarc perechea DS:reg, respectiv ES:reg, cu o adres complet de 32 de bii. De obicei, instruciunea LDS se folosete mpreun cu directiva DefineDoubleWord,canexemplulurmtor:
.data x y adr_x adr_y .code LDS LES MOV MOV SI, adr_x DI, adr_y byte ptr [SI], 20 byte ptr ES:[DI], 30 db db dd dd 10 15 x y

Variabilele adr_x i adr_y, care conin adresele far ale variabilelor x i y, sunt ncrcate n DS:SI i ES:DI. Se acceseaz apoi variabilele x i y, folosind adresareaindexat. Urmtorul exemplu utilizeaz o tabel de adrese. S presupunem c avem 8 variabile word diferite, numite V_0, ..., V_7 i dorim s ncrcm n AX variabila

43Capitolul2
a crui indice este dat de registrul CX. Cu alte cuvinte, dac CX=0, ncrcm V_0, dac CX=1, ncrcm V_1 etc. Definim n acest scop tabela de adrese TAB_ADRifolosimadresareaindexat.
.data TAB_ADR .code MOV ADD ADD LES MOV BX, BX, BX, DI, AX, CX BX BX TAB_ADR[BX] ES:[DI] dd V_0, V_1, V_2, V_3, V_4, V_5, V_6, V_7

Deoarece o poziie din tabel ocup 4 octei, valoarea indicelui din CX trebuie nmulit cu 4. Acest lucru se obine prin dou instruciuni ADD BX, BX,careadunBXlaelnsui.

2.1.4Instruciunidetransferspecificeflagurilor(LAHF,SAHF,PUSHF, POPF)
InstruciuneaLAHF(LoadAHwithFLAGSncarcAHcuFLAGS) Instruciunea nu are operanzi, iar semnificaia este dat de denumire: se ncarcregistrulAHcuparteamaipuinsemnificativaregistruluideflaguri:
AH FLAGS0:7

InstruciuneaSAHF(StoreAHintoFLAGSDepuneAHnFLAGS) EsteperecheainstruciuniiLAHF,semnificaiafiind:
FLAGS0:7 AH

InstruciuneaPUSHF(PushFlagsSalveazFLAGSnstiv) Nu are operanzi, iar efectul este plasarea registrului FLAGS n vrful stivei (salvareaflagurilornstiv):
(SP) (SP) - 2 SS:((SP) + 2 : (SP)) FLAGS

InstruciuneaPOPF(PopFlagsRefaceFLAGSdinstiv) EsteperecheainstruciuniiPUSHF:
FLAGS (SP) SS:((SP) + 1 : (SP)) (SP) + 2

Instruciunile LAHF i SAHF citesc i scriu explicit partea mai puin semnificativ a registrului de flaguri. Partea mai semnificativ poate fi citit i modificatprinmiciartificiicuinstruciunilePUSHFiPOPF.Secvena:

Programarenlimbajdeasamblare44

PUSHF POP AX

va ncrca n AX registrul de flaguri, deci n AH vom avea partea mai semnificativ,iarsecvena:


PUSH POPF AX

vancrcaAXnregistruldeflaguri. Cu excepia instruciunilor explicite SAHF i POPF, nici o instruciune de transfernumodificbistabiliidecondiie.

2.2Instruciuniaritmeticeilogice
A doua categorie important de instruciuni o constituie instruciunile aritmetice i logice. Rezultatul operaiei este totdeauna depus ntrunul din operanzi. La instruciunile cu doi operanzi, rezultatul este depus n primul operand. Instruciunile modific flagurile CF, AF, ZF, SF, PF i OF, motiv pentrucareacesteamaisuntnumiteiflaguriaritmetice.

2.2.1Semnificaiaflaguriloraritmetice
Flagul Carry = 1 semnific un transport/mprumut din/n bitul cel mai semnificativ (b.c.m.s.) al rezultatului, unde b.c.m.s. poate fi bitul 7 sau bitul 15. Interpretarea acestui transport sau mprumut este cea de depirelaoperaiiledeadunare/scderecuoperanzifrsemn. Flagul Auxiliarry Carry = 1 semnific un transport/mprumut din/n bitul4alrezultatului,fiindutilizatlaoperaiilecunumereBCD. Flagul Zeroeste1dacrezultatuloperaieiestenul. Flagul Sign este 1 dac bitul de semn al rezultatului (bitul 7 sau 15) este 1. Flagul Parity este 1 dac suma modulo 2 a celor 8 bii mai puin semnificativiairezultatuluieste0. Flagul Overflow este 1 dac operaia a condus la un transport nspre b.c.m.s., dar nu din b.c.m.s. al rezultatutului, sau invers. Altfel, OF se poziioneaz la zero. Similar, n cazul mprumutului: OF = 1 dac a avut loc un mprumut dinspre b.c.m.s., dar nu din exterior, sau invers. SituaiiledescrisesuntilustratenFigura2.2. Interpretarea flagului OF este aceea de depire la operaiile de adunare/scderecuoperanzicusemn. S considerm valoarea pe 1 octet 0FFH i s adunm 1 la aceast valoare. Rezultatul este 0 i transport att din bitul 7, ct i din bitul 6 n bitul 7. Astfel, CF = 1 i OF = 0. Considernd operanzii fr semn (255 i 1), adunarea lor

45Capitolul2
provoac depire, ceea ce corespunde cu CF = 1. Dac se consider operanziicusemn,(1i1),adunarealornuprovoacdepireiOF=0. S considerm, n mod similar, valorile 70H i 10H i suma acestora. Rezultatul este 80H i nu apare transport din bitul 7, dar este transport din bitul 6 n bitul 7. Ca atare, CF = 0 i OF = 1. n interpretarea fr semn, valorile operanzilor sunt 112 i 16, suma lor fiind 128, deci nu apare depire (CF = 0). n interpretarea cu semn, valorile sunt tot 112 i 16, dar suma lor depete domeniul admisibil alocteilorcusemniOF=1.

Figura 2.2 Poziionarea bistabilului Overflow n fine, s considerm operanzii 0FDH i 02H i suma lor. La adunare, se obine valoarea 0FFH i nu apare transport nici din bitul 7, nici din bitul 6. Ca atare, CF = 0 i OF = 0. Valorile fr semn sunt 253 i 2, iar suma lor (255) este n domeniul admisibil, deci CF = 0. Valorile cu semn sunt 3 i 2, iar suma lor(1)estendomeniuldereprezentarealnumerelorcusemn,deciOF=0. La fiecare instruciune aritmetic sau logic, se vor preciza explicit flagurile afectate, adic flagurile care se poziioneaz conform rezultatului. Un flag neafectat rmne la vechea valoare. Exist i situaii n care unele flaguri au valorinedefinite.

2.2.2Instruciunispecificeadunrii(ADD,ADC,INC,DAA,AAA)
InstruciuneaADD(AddAdun) Areformageneral:
ADD destinatie, sursa

Programarenlimbajdeasamblare46 n care destinaie poate fi un registru general sau o locaie de memorie, iar surs poate fi un registru general, o locaie de memorie sau o valoare imediat. Cei doi operanzi nu pot fi simultan locaii de memorie. Semnificaia este:
(destinatie) (destinatie) + (sursa)

Flaguriafectate:AF,CF,PF,SF,ZF,OF(toate). Operanzii pot fi pe 8 sau 16 bii i trebuie s aib aceeai dimensiune. n caz de ambiguitate n ceea ce privete lungimea operanzilor, se folosete operatorulptr.Iatctevaexemple:
ADD ADD ADD ADD ADD ADD AX, BX AX, 1 AL, 1 word ptr [DI], -1 ALFA, 3 byte ptr ALFA, 3 ; ; ; ; ; ; ; Lungime 16 biti Lungime 8 biti Dest. in memorie, sursa imediata ALFA este definit cu DW Fortare instructiune pe octet

InstruciuneaADC(AddwithCarryAduncutransport) Formageneraleste:
ADC destinatie, sursa

Formatul este similar cu instruciunea ADD, ceea ce difer fiind adunarea bistabiluluiCF:
(destinatie) (destinatie) + (sursa) + (CF)

Flaguriafectate:AF,CF,PF,SF,ZF,OF(toate). Adunarea cu Carry se folosete la adunri de operanzi pe mai multe cuvinte, n care poate aprea un transport intermediar. De exemplu, secvena de adunareadounumerepe4octeieste:
.data ALFA BETA REZ .code MOV ADD MOV MOV ADC AX, word ptr ALFA AX, word ptr BETA word ptr REZ, AX AX, word ptr ALFA+2 AX, word ptr BETA+2 ; ; ; ; ; ; ; ; Cuvintele m.p.s. la adr. mici Aici poate aparea transport Cuvintele m.s. la adr. mari Se ia in considerare transportul precedent dd dd dd 145A789FH 92457ABCH ?

47Capitolul2
MOV word ptr REZ+2, AX

InstruciuneaINC(IncrementIncrementeaz) Areformageneral:
INC destinatie

n care destinaie este un registru sau un operand n memorie, de tip octet sau cuvnt.Semnificaiaeste:
(destinatie) (destinatie) + 1

Flaguriafectate:AF,PF,SF,ZF,OF(frCF). Instruciunea DAA (Decimal Adjust for Addition Corecie zecimal dup adunare) Instruciunea nu are operanzi i efectueaz corecia zecimal a acumulatorului AL, dup o adunare cu operanzi n format BCD despachetat. Semnificaiaeste:
daca (AL0:3) > 9 sau (AF) = 1, atunci { (AL) (AL) + 6 (AF) 1 } daca acum (AL4:7) > 9 sau CF = 1, atunci { (AL) (AL) + 60H (CF) 1 }

Flaguriafectate:CF,AF,CF,PF,SF,ZF.FlagulOFestenedefinit. Dac cifra BCD mai puin semnificativ (AL0:3) este mai mare dect 9, deci este incorect, sau dac a avut loc un transport din bitul 3 n bitul 4, se corecteaz aceast cifr prin adunarea valorii 6. Dac cifra BCD mai semnificativ este acum mai mare dect 9, se corecteaz similar aceast cifr. n ambele situaii, se poziioneaz corespunztor AF i CF, pentru a indica depireacareaavutloc. S considerm, de exemplu, adunarea valorilor BCD 65 i 17. Aceste valori se reprezint prin octeii 65H i 17H. n urma adunrii, se obine rezultatul 7CH, care este incorect ca rezultat BCD. Operaia de corecie (DAA) conduce la rezultatul 82H, ceea ce reprezint suma BCD a celor dou valori. Secvena de adunaretrebuiesfie:
.data BCD1 BCD2 REZ .code MOV AL, BCD1 db 65H db 17H db ?

Programarenlimbajdeasamblare48
ADD DAA MOV AL, BCD2 REZ, AL

Instruciunea AAA (ASCII acumulatorului)

Adjust for

Addition

Corecie

ASCII a

Instruciunea nu are operanzi i efectueaz corecia acumulatorului AX, dup operaii de adunare cu operanzi BCD despachetai (o cifr BCD pe un octet).Semnificaiaesteurmtoarea:
dac (AL0:3) > (AL) (AH) (AF) (CF) (AL) } 9 sau (AF) = 1, atunci { (AL) + 6 (AH) + 1 1 1 (AL) AND 0FH

Flaguriafectate:AF,CF,restulnedefinite. Corecia se face tot prin adugarea valorii 6 la (AL), dar se face i o incrementare a registrului (AH), n ideea c acolo sar putea ine cifra BCD despachetat mai semnificativ. Totodat se terg biii 4:7 ai registrului AL, pentru a avea o cifr BCD despachetat. S considerm c registrele AX i BX conin valorile 0309H i 0104H, ceea ce ar corespunde valorilor BCD despachetate 39 i 14. n urma adunrii, se obine rezultatul 040DH, care este incorect. Instruciunea AAA, corecteaz acest rezultat la 0503H, care este sumacorectacelordouvaloriiniiale:
MOV MOV ADD AAA AX, 0309h BX, 0104H AX, BX

; AX = 040DH ; AX = 0503H

2.2.3Instruciunispecificescderii(SUB,SBB,DEC,NEG,CMP,DAS, AAS)
InstruciuneaSUB(SubtractScade) Areformageneral:
SUB destinatie, sursa

unde destinatie i sursa sunt la fel ca la instruciunea ADD. Semnificaia este:


(destinatie) (destinatie) - (sursa)

49Capitolul2
Flaguriafectate:AF,CF,PF,SF,ZF,OF(toate). Scderea poate fi privit ca o adunare cu complementul fa de 2 al operandului surs, dar cu inversarea rolului bistabilului CF, n sensul c, dac la aceast adunare echivalent apare transport, atunci CF = 0 i reciproc. S considermsecvenadeinstruciuni:
MOV SUB AL, 1 AL, 05EH

Rezultatul este 0A3H i exist mprumut, deci CF = 1. Dac lum complementul fa de 2 al sursei, obinem valoarea 0A2H, care, adunat la destinaie (adic la 1), conduce la valoarea 0A3H. La aceast adunare echivalent nu exist transport, deci, conform regulii de mai sus, operaia de scdere de la careampornitvaconducelaCF=1. InstruciuneaSBB(SubtractwithBorrowScadecumprumut) Areformageneral:
SBB destinatie, sursa

n care destinatie i sursa sunt la fel ca la instruciunea ADD. Semnificaia este:


(destinatie) <-- (destinatie) - (sursa) - (CF)

deciseianconsiderareuneventualmprumutanterior. Flaguriafectate:AF,CF,PF,SF,ZF,OF(toate). Instruciunea SBB se utilizeaz la scderi de operanzi pe mai multe cuvinte, canexemplulurmtor:
.data ALFA BETA REZ .code MOV SUB MOV MOV SBB MOV AX, word ptr ALFA AX, word ptr BETA word ptr REZ, AX AX, word ptr ALFA+2 AX, word ptr BETA+2 word ptr REZ+2, AX ; ; ; ; ; ; ; ; Cuvintele m.p.s. la adr. mici Aici poate aparea imprumut Cuvintele m.s. la adr. mari Se ia in considerare imprumutul precedent dd 145A789FH dd 92457ABCH dd ?

InstruciuneaDEC(DecrementDecrementeaz) Areformageneral:

Programarenlimbajdeasamblare50
DEC destinatie

ncaredestinaieestelafelcalainstruciuneaINC.Semnificaiaeste:
(destinatie) (destinatie) - 1

Flaguriafectate:AF,PF,SF,ZF,OF(frCF). InstruciuneaNEG(NegateSchimbsemnul) Areformageneral:


NEG destinatie

n care destinaie este un registru sau o locaie de memorie, pe 8 sau pe 16 bii.Semnificaiaeste:


(destinatie) 0 - (destinatie)

decisefaceoschimbareasemnuluioperandului. Flaguriafectate:AF,CF,PF,SF,ZF,OF(toate). De observat c schimbarea semnului poate conduce uneori la aceeai valoare, ncazuldepiriidomeniuluiadmisibil.Deexemplu,secvena:
MOV NEG AL, -128 AL

va lsa registrul AL neschimbat (80H), deoarece 128 i 128 au aceeai reprezentareintern. InstruciuneaCMP(CompareCompar) Areformageneral:
CMP destinatie, sursa

iar semnificaia este execuia unei scderi temporare (destinaie) (surs), frasemodificavreunoperand,darcupoziionareabistabililordecondiie. Flaguriafectate:AF,CF,PF,SF,ZF,OF(toate). Testnd bistabilii de condiie, putem deduce relaia dintre cei doi operanzi. De exemplu, instruciunea CMP AX, BX va provoca o scdere temporar (AX) (BX). Dac ZF = 1 nseamn c (AX) = (BX). Dac CF = 1 nseamn c la scdere a aprut un mprumut, deci (AX) < (BX), dac sunt considerate ca numerefrsemn. Instruciunea CMP se folosete, de obicei, mpreun cu instruciuni de salt condiionat(vezi2.4.3).

51Capitolul2
Instruciunea DAS (Decimal Adjust for Subtraction Corecie zecimal dup scdere) Instruciunea nu are operanzi i execut corecia zecimal a acumulatorului AL, dup operaii de scdere cu numere n format BCD mpachetat. Semnificaiaeste:
daca (AL0:3) > 9 sau (AF) = 1, atunci { (AL) (AL) - 6 (AF) 1 } daca acum (AL4:7) > 9 sau CF = 1, atunci { (AL) (AL) - 60H (CF) 1 }

Flaguriafectate:AF,CF,PF,SF,ZF.FlagulOFestenedefinit. Explicaia operaiilor de mai sus este similar cu cea de la instruciunea DAA.Deexemplu,nurmasecvenei:
.code MOV SUB DAS AL, 52H AL, 24H ; AL = 2EH ; AL = 28H

seobinenALrezultatulcorect28H(28=5224). InstruciuneaAAS(ASCIIAdjustforSubtractionCorecieASCIIdupscdere) Instruciunea nu are operanzi i efectueaz corecia acumulatorului AX, dup operaii de scdere cu operanzi BCD despachetai (o cifr BCD pe un octet).Semnificaiaesteurmtoarea:
daca (AL0:3) > (AL) (AH) (AF) (CF) (AL) } 9 sau (AF) = 1, atunci { (AL) - 6 (AH) - 1 1 1 (AL) AND 0FH

Flaguriafectate:AF,CF,restulnedefinite. Se observ analogia cu instruciunea AAA, specific adunrii n format BCD despachetat.

Programarenlimbajdeasamblare52

2.2.4 Instruciunispecificenmulirii(CBW,CWD,MUL,IMUL, AAM)


Operaiile de nmulire se fac ntre acumulator i un al doilea operand. Rezultatul operaiei este pe 16 sau, respectiv, 32 de bii. Se folosesc urmtoarelenoiuni,definitediferitlaoperaiide8sau16bii: acumulatorregistrulAL,respectiv,AX acumulatorextinsregistrulAX,respectivperecheaderegistreDX:AX extensiaacumulatoruluiregistrulAH,respectivDX extensia de semn a acumulatorului coninutul registrului AL, respectiv AX, reprezentat, ca numr cu semn, pe o lungime dubl (16, respectiv 32 debii). InstruciuneaCBW(ConvertBytetoWordConverteteoctetlacuvnt) Estefroperanziiareurmtoareasemnificaie:
daca (AL7) = 0, atunci (AH) 0 altfel (AH) 1

Flaguriafectate:niciunul. Practic, se extinde bitul de semn din AL la ntreg registrul AH. Acest lucru este echivalent cu reprezentarea lui AL n complement fa de 2, pe un numr dublu de bii. De exemplu, dac AL = 3 (0FDH), atunci instruciunea CBW va fora n AX valoarea 0FFFDH, care este chiar reprezentarea n complementfade2avalorii3. Instruciunea CWD (Convert Word to DoubleWord Convertete cuvnt la dublu cuvnt) Estefroperanziiareurmtoareasemnificaie:
daca (AX15) = 0, atunci (DX) 0 altfel (DX) 1

Flaguriafectate:niciunul. Se extinde bitul de semn din AX la ntreg registrul DX, obinnduse astfel o reprezentarealuiAXpe32debii. Prin instruciunile CBW i CWD, se obin extensiile de semn ale acumulatoruluinacumulatorulextins.

InstruciuneaMUL(Multiplynmuletefrsemn)

53Capitolul2
Areformageneral:
MUL sursa

n care surs poate fi un registru sau o locaie de memorie de 8 sau 16 bii. Variantele noi de procesoare accept i date imediate ca operand surs. Rezultatul se obine pe un numr dublu de bii (16 sau 32). Semnificaia este:
(acumulator extins) (acumulator) * (sursa)

ncareambiioperanziseconsidernumerefrsemn. Maiprecis,dacsursestepeoctet:
(AH:AL) (AL) * (sursa)

iardacsursestepecuvnt:
(DX:AX) (AX) * (sursa)

Flaguri afectate: dac extensia acumulatorului (adic AH sau DX) este diferit de 0, atunci CF i OF sunt 1, altfel CF i OF sunt 0. Restul flagurilor sunt nedefinite.Exemple:
.data ALFA BETA .code MOV MUL MOV MUL MOV MOV MUL AL, 10H ALFA AX, 20H BETA AX, 100H BX, 20H BX ; (AX) (AL) * ALFA ; (DX:AX) (AX) * BETA ; (DX:AX) (AX) * (BX) db 10H dw 200H

n situaia n care un operand este de tip byte, iar cellalt de tip word, se convertete operandul de tip byte la word, ca numr fr semn, deci cu partea mai semnificativ 0. De exemplu, pentru a nmuli valorile ALFA i BETA, se poatescrie:
MOV MOV MUL AL, ALFA AH, 0 BETA ; (AX) = 0010H ; (DX:AX) = 2000H

Se observ c instruciunea MUL nu poate conduce la depiri. nmulind fr semn cele mai mari valori posibile pe 8/16 bii, se obin valori corecte pe 16/32 de bii. De exemplu, (216 1)(2161) = 232 217 + 1, care este o valoare reprezentabilpe32debii. InstruciuneaIMUL(IntegerMultiplynmuletecusemn)

Programarenlimbajdeasamblare54 Areformageneral:
IMUL sursa

fiind similar cu instruciunea MUL. Deosebirea este c operaia de nmuliresefaceconsiderndoperanziinumerecusemn. Flaguri afectate: dac extensia acumulatorului reprezint extensia de semn a acumulatorului, atunci CF i OF se poziioneaz la 0. Altfel, CF i OF devin 1. Restulflagurilorsuntnedefinite. Nu pot aprea situaii de depire. nmulind cele mai mari valori n modul, se obin valori corect reprezentabile. De exemplu, 127127 = 16129, care se reprezintcorectcanumrcusemnpe16bii.Similar,(128)(128)=16384. Dac sunt necesare conversii de la byte la word, se va folosi instruciunea CBW,cansecvenaurmtoare:
.data ALFA BETA REZ .code MOV CBW MUL MOV MOV AL, ALFA BETA word ptr REZ, AX word ptr REZ+2, DX ; ; ; ; ; ; Conversie la word Inmultire pe 16 biti Partea m.p.s. la adrese mici Partea m.s. la adrese mari db -113 dw -147 dd ?

Instruciunea AAM (ASCII Adjust for Multiply Corecie ASCII dup nmulire) Instruciunea nu are operanzi i efectueaz o corecie a acumulatorului AX, dup o nmulire pe 8 bii cu numere n format BCD despachetat. Semnificaiaeste:
(AH) (AL)/10 (AL) (AL) MOD 10

Flaguriafectate:PF,SF,ZF,restulnedefinite. Deexemplu,sconsidermsecvena:
MOV MOV MUL AAM AL, 5 CL, 9 CL

n urma nmulirii, registrul AX va conine valoarea 2DH (45). Corecia prin AAM conduce la AH = 4 i AL = 5, deci AX = 0405H, adic reprezentarea BCD despachetatpentruvaloareazecimal45.

55Capitolul2 2.2.5Instruciunispecificempririi(DIV,IDIV,AAD)
mprirea presupune c dempritul este pe o lungime dubl dect mpritorul. Prin mprire se obin ctul i restul, de lungime egal cu a mpritorului. InstruciuneaDIV(Dividempartefrsemn) Areformageneral:
DIV sursa

n care surs e un operand (registru sau locaie de memorie) pe octet sau pe cuvnt. Procesoarele moderne accept i date imediate ca operand surs. Semnificaiaesteurmtoarea:
(acumulator) (acumulator extins) / (sursa) (extensia acumulatorului) (acumulator extins) (sursa) MOD

Detaliindoperaiile,seobine,ncazulncaresursaestepeoctet:
(AL) (AX) / (sursa) (AH) (AX) MOD (sursa)

iardacsursaestepecuvnt:
(AX) (DX:AX) / (sursa) (DX) (DX:AX) MOD (sursa)

Flaguriafectate:toateflagurilesuntnedefinite. mprirea poate conduce la depiri. n situaia n care ctul rezult mai mare dect valoarea maxim reprezentabil pe 8, respectiv 16 bii, sau dac mpritorul este 0, rezultatele sunt nedefinite i se genereaz o ntrerupere soft pe nivelul 0 (Divide Overflow Depire la mprire). De exemplu, n secvena:
MOV MOV DIV AX, 1000 BL, 2 BL

ctul ar trebui s fie 500, valoare care nu se poate reprezenta pe un octet. Ca atare, apare depire i se va genera o ntrerupere pe nivelul 0. Rutina afectat acestui nivel de ntrerupere oprete de obicei programul executabil i afieaz unmesajdeeroarelaconsol. S considerm cteva exemple de operaii de mprire fr semn, care ilustreaz pregtirea operanzilor n situaiile care nu corespund celor dou tipuridebaz(mprirecuvntlaoctetimpriredublucuvntlacuvnt):
.data

Programarenlimbajdeasamblare56
B1 B2 W1 W2 D1 .code ; impartire MOV MOV DIV ; ; impartire MOV DIV ; ; impartire MOV MOV DIV ; ; impartire MOV MOV DIV ; ; impartire MOV MOV MOV MOV DIV db db dw dw dd ? ? ? ? ?

octet la octet AL, B1 AH, 0 B2 cuvant la octet AX, W1 B1

; AL = cat, AH = rest

; AL = cat, AH = rest

dublu-cuvant la cuvant AX, word ptr D1 DX, word ptr D1 + 2 W1 ; AX = cat, DX = rest cuvant la cuvant AX, W1 DX, 0 W2

; AX = cat, DX = rest

dublu-cuvant la byte AX, word ptr D1 DX, word ptr D1 + 2 BL, B1 BH, 0 BX ; AX = cat, DX = rest

InstruciuneaIDIV(IntegerDividempartecusemn) Areformageneral:
IDIV sursa

n care sursa este la fel ca la instruciunea DIV. Semnificaia este aceeai ca la instruciunea DIV, cu diferena c operanzii sunt considerai cu semn, iar mprireasefacecusemn. Flaguriafectate:toateflagurilesuntnedefinite. n situaia n care ctul rezult n afara domeniului reprezentabil pe 8, respectiv 16 bii, sau dac mpritorul este 0, rezultatele sunt nedefinite i se genereaz o ntrerupere soft pe nivelul 0. Concret, ctul trebuie s fie ndomeniul [128, +127] la mprire pe octet, respectiv n domeniul [32768, +32767] la mprirepecuvnt.Deexemplu,nsecvena:
MOV MOV AX, 400 BL, 2

57Capitolul2
IDIV BL

ctul ar trebuie s rezulte 200, valoare care nu se poate reprezenta ca numr cusemnpeunoctet.Caatare,vaapreaontreruperepenivelul0. n ceea ce privete calculul restului la mprirea cu semn, acesta este totdeaunacalculatastfelnctsfiendeplinitidentitateaurmtoare:
a = b*(a/b) + a MOD b

n care a/b i a MOD b sunt ctul i restul calculate de instruciunea IDIV. De exemplu,nsecvena:
MOV MOV IDIV AX, -10 BL, -3 BL

; AL = 3, AH = 0FFH

ctul rezult +3, iar identitatea de mai sus conduce la restul 1. Aadar (10) MOD(3)=1inregistrulAHsevagsi0FFH(1reprezentatpeunoctet). Tipurile posibile de mpriri sunt aceleai ca la instruciunea DIV, cu observaia c operanzii trebuie pregtii folosind instruciunile CBW i CWD.ConsidermaceleaidefiniiidedatecalainstruciuneaDIV:
.code ; impartire MOV CBW IDIV ; ; impartire MOV IDIV ; ; impartire MOV MOV IDIV ; ; impartire MOV CWD IDIV ; ; impartire MOV CBW MOV MOV MOV IDIV octet la octet AL, B1 B2 cuvant la octet AX, W1 B1 dublu-cuvant la cuvant AX, word ptr D1 DX, word ptr D1 + 2 W1 cuvant la cuvant AX, W1 W2 dublu-cuvant la byte AL, B1 BX, AX AX, word ptr D1 DX, word ptr D1 + 2 BX ; BX = Deimpartit ; DX:AX = impartitor ; AX = cat, DX = rest ; AX = cat, DX = rest ; AL = cat, AH = rest

; AL = cat, AH = rest

; AX = cat, DX = rest

Programarenlimbajdeasamblare58 O aplicaie tipic a instruciunilor de mprire este conversia unui cuvnt de 16 bii, cu sau fr semn, la un ir de caractere (cifre) n baza 10. Dac presupunem c n este variabila care conine numrul, iar sir este variabila unde se depun cifrele generate, algoritmul poate fi descris (ntro notaie specificlimbajuluiC),nfelulurmtor:
adrsir = sir; do { rest = n % 10; n = n/10; *sir++ = rest + '0'; } while (n != 0); *sir = 0; inverseaza(adrsir);

Interpretm numrul n fr semn. n bucla de program cu test la partea inferioar, se calculeaz restul i ctul mpririi lui n la 10. Ctul furnizeaz cifra curent, creia i se adun codul ASCII al cifrei 0. Se avanseaz adresa sir laurmtorulcaracter,buclaterminndusecndndevine0. Se observ c acest algoritm furnizeaz cifrele numrului n ordine invers ca atare, rutina inverseaza(sir), trebuie s inverseze ordinea caracterelor din irul generat. De exemplu, dac n = 1234, atunci prima iteraie produce rest = 4in=123,adouaiteraieproducerest=3in=12etc. Simplementmacestalgoritmprintrosecvennlimbajdeasamblare.
.data n sir .code lea mov mov mov mov _do: div add mov inc mov cmp jne mov bx ; AX = cat, DX (DL) = rest dl, '0' [si], dl si dx, 0 ax, 0 _do ; Salt daca AX diferit de 0 byte ptr [si], 0 si, ax, dx, bl, bh, sir n 0 10 0 dw ? db 20 dup (?)

; ; Inverseaza ; mov di, si dec di lea si, sir _test:

; DI indica ultimul caracter util ; SI indica primul caracter

59Capitolul2
cmp jae mov xchg mov inc dec jmp _gata: si, di _gata al, [si] al, [di] [si], al si di _test ; Salt daca SI >= DI ; Interschimba octetii de la ; adresele din SI si DI

Declaraia sir db 20 dup (?) rezerv o zon de 20 de octei n segmentul de date. Simbolurile _do:, _test:, _gata: sunt etichete folosite la instruciuni desalt. Dei avem de fcut o mprire la 10 (deci la o cantitate care se poate reprezenta pe un octet), iar dempritul este un cuvnt, vom folosi totui mprirea dublucuvnt la cuvnt, pentru a evita depirile. Se pregtete deci dempritul n DX:AX i ctul n BX. Pentru accesul la irul de caractere, folosim registrul SI. Aadar, variabilele n i sir din algoritm vor fi inute n registreleAXiSI. Prin mprire, se obine ctul n AX i restul n DX. De fapt, fiind o mprire la 10, restul nu poate depi valoarea 9, deci l vom gsi, de fapt, n DL. Adugm '0' i depunem caracterul la adresa dat de SI, incrementm SI i pregtim dempritul pentru pasul urmtor (adic form DX = 0). Se testeaz acum AX (adic variabila n), prin comparaie cu 0. Instruciunea JNZ nseamn Jump on Not Equal, deci salt dac operanzii din ultima comparaiesuntdiferii.Acestsaltcondiionatreiabucladeprogram. Pentru a inversa caracterele generate, se poziioneaz registrele SI i DI pe primul i, respectiv, pe ultimul caracter util din ir, dup care se execut o bucl de inversare, care continu ct timp SI < DI. Instruciunea JAE nseamn Jump if Above or Equal, deci salt dac la ultima comparaie primul operand a fost mai mare sau egal cu al doilea. n bucla respectiv, se interschimb caractereledelaadreseleDIiSI,prindouMOVuriiunXCHG. Instruciunea AAD (ASCII Adjust for Division Corecie ASCII nainte de mprire) Instruciunea nu are operanzi i efectueaz o corecie a acumulatorului AX, interpretatcadoucifreBCDdespachetate.Semnificaiaesteurmtoarea:
(AL) (AH) (AH) * 10 + (AL) 0

Flaguriafectate:PF,SFiZF,restulnedefinite. Operaia de corecie trebuie fcut nainte de mprirea unui numr pe dou cifre BCD, reprezentat pe un cuvnt, la o cifr BCD reprezentat pe un octet.

Programarenlimbajdeasamblare60 De exemplu, dac AX = 0305H, adic valoarea BCD 35 i BL = 2, secvena demprirevafi:


AAD DIV BL ; AX = 23H ; AL = 11H, AH = 1

Instruciunea AAD ncarc AX cu valoarea 23H (35) i mprirea se face corect,obinndusectul11H(17)irestul1.

2.2.6Instruciunilogice(NOT,AND,TEST,OR,XOR)
Instruciunile logice realizeaz funciile logice de baz, pe octet sau pe cuvnt. Operaiile se fac la nivel de bit, deci se aplic funcia logic respectiv tuturor biilor sau perechilor de bii corespunztori din operanzi. InstruciuneaNOTareunsinguroperand,celelalteavndfiecaredoioperanzi. InstruciuneaNOT(NotNegarelogicbitcubit) Formageneraleste:
NOT destinatie

n care destinatie poate fi un registru sau o locaie de memorie de 8 sau 16 bii. Instruciunea provoac negarea tuturor biilor operandului, deci calculul complementuluifade1. Flaguriafectate:niciunul. InstruciuneaAND(Andilogicbitcubit) Areformageneral:
AND destinatie, sursa

n care destinaie poate fi un registru sau o locaie de memorie de 8 sau 16 bii, iar surs poate fi un registru, o locaie de memorie sau o constant, pe 8 sau16bii.Semnificaiaeste:
(destinatie) (destinatie) AND (sursa)

Flaguriafectate:SF,ZF,PF,CF=0,OF=0,AFnedefinit. InstruciuneaTEST(TestTesteaz) Areformageneral:


TEST destinatie, sursa

n care destinatie i sursa sunt la fel ca la instruciunea AND. Efectul este execuia unei operaii AND ntre cei doi operanzi, fr a se modifica destinaia,darcupoziionareaflagurilorlafelcalainstruciuneaAND. Flaguriafectate:SF,ZF,PF,CF=0,OF=0,AFnedefinit.

61Capitolul2
Aceast instruciune i raportul ei cu instruciunea AND sunt similare cu instruciuneaCMPiraportulcuinstruciuneaSUB. InstruciuneaOR(OrSaulogicbitcubit) Areformageneral:
OR destinatie, sursa

n care destinatie i sursa sunt la fel ca la instruciunea AND. Semnificaia este:


(destinatie) (destinatie) OR (sursa)

Flaguriafectate:SF,ZF,PF,CF=0,OF=0,AFnedefinit. InstruciuneaXOR(ExclusiveOrSauexclusivbitcubit) Areformageneral:


XOR destinatie, sursa

n care destinatie i sursa sunt la fel ca la instruciunea AND. Semnificaia este:


(destinatie) (destinatie) XOR (sursa)

Flaguriafectate:SF,ZF,PF,CF=0,OF=0,AFnedefinit. Funcia sauexclusiv este 1 cnd operanzii si sunt unul 0, iar cellalt 1 i este 0 cnd operanzii sunt ambii 0 sau ambii 1. Din acest motiv, funcia sau exclusivsemainumeteianticoinciden. Instruciunile logice sunt folosite frecvent pentru anumite operaii tipice, cum arfi: tergerearapidaunuiregistru,cupoziionareaflagurilor
XOR XOR AX, AX CL, CL

forareaunorbiilavaloarea1,restulrmnndneschimbai
MASCA EQU 01101101B OR AL, MASCA

Pseudoinstruciunea EQU definete constante simbolice, iar prefixul B nseamn numr scris n baza 2. n secvena de mai sus, biii cu valoarea 1 din MASCA vor fi forai la 1 n registrul AL, iar biii cu valoarea 0 din MASCAvorrmneneschimbai. forareaunorbiilavaloarea0cuceilalineschimbai
AND AL, MASCA

Programarenlimbajdeasamblare62 Biii cu valoarea 0 din MASCA vor deveni 0 n AL, iar cei cu valoarea 1 n MASCAvorrmneneschimbai. testareaunuisingurbitdintrunoperand
TEST JZ AL, 01000000B eticheta ; sau JNZ

poziionareaflagurilorframodificaoperandul
OR AND TEST AX, AX AX, AX AX, AX ; ; ; ; Pozitioneaza FLAGS conform AX Similar Similar

complementareaunuigrupdebii,cuceilalineschimbai Presupunem constanta MASCA, definit ca mai sus, i operandul aflat n AL. Dorim ca biii cu valoarea 1 din MASCA s fie complementai n AL, iar ceilalisrmnneschimbai.
MASCA EQU 01110110B MOV BL, AL AND AL, MASCA NOT XCHG AND OR AL AL, BL AL, NOT MASCA AL, BL ; ; ; ; ; ; ; ; Salvare Selectie biti care se modifica Complementare Refacere Selectie biti care nu se modifica Rezultat final

Expresia NOT MASCA este evaluat la asamblare, producnduse o constant cutoibiiinegai.

2.2.7Instruciunidedeplasare(SHL,SAL,SHR,SAR)iderotaie(ROL, RCL,ROR,RCR)
Acest grup de instruciuni realizeaz operaii de deplasare i de rotaie la nivel de bit. Instruciunile au doi operanzi: primul este operandul propriuzis, iar al doilea este numrul de bii cu care se deplaseaz sau se rotete primul operand. Ambele operaii se pot face la dreapta sau la stnga. Deplasare nseamn translatarea tuturor biilor din operand la stnga/dreapta, cu completarea unei valori fixe n dreapta/stnga i cu pierderea biilor din stnga/dreapta. Deplasarea cu un bit la stnga este echivalent cu nmulirea operanduluicu2,iardeplasarealadreapta,cumprireaoperanduluila2. Rotaie nseamn translatarea tuturor biilor din operand la stnga/dreapta, cucompletareandreapta/stngacubiiicaresepierdnparteaopus. Ambele operaii se fac cu modificarea bistabilului CF, care poate chiar participalaoperaiilederotaie. Formageneralainstruciuniloreste:

63Capitolul2
OPERATIE OPERAND, CONTOR

n care OPERAND este un registru sau o locaie de memorie de 8 sau 16 bii, iar CONTOR (numrul de bii) este fie constanta 1, fie registrul CL, care conine numrul de bii cu care se deplaseaz/rotete operandul. Procesoarele de generaie nou (80286 i peste) accept un numr oarecare debii,specificatiprintroconstantntreag. Flagurile sunt afectate n felul urmtor. La operaiile de deplasare, se modific toate flagurile conform rezultatului, n afar de AF, care este nedefinit. La operaiilederotaie,semodificnumaiCFiOF. Modificarea flagului OF se face printrun algoritm destul de complicat. Pentru a nu repeta acest algoritm, considerm urmtoarele secvene definite n pseudocod:
pozit_OF_left { daca CONTOR = 1, atunci daca b.c.m.s. din OPERAND este diferit de CF, atunci OF 1 altfel OF 0 altfel OF nedefinit } pozit_OF_right { daca CONTOR = 1, atunci daca cei doi biti mai semnif. din OPERAND sunt diferiti OF 1 altfel OF 0 altfel OF nedefinit }

Se vede deci c flagul OF este poziionat numai dac se face o operaie de deplasare/rotaiede1bit. Descrierea instruciunilor se va face ntrun format de tip pseudocod, cu evideniereaoperaiiloraritmeticeechivalente. La instruciunile de deplasare, se consider deplasri logice i aritmetice, care sepotutilizadupnaturaoperanzilor.

Instruciunea SHL/SAL (Shift Logic/Arithmetic Left Deplaseaz logic/aritmetic la stnga) Areformageneral:


SHL/SAL OPERAND, CONTOR

Programarenlimbajdeasamblare64 Dei exist dou mnemonice (SHL i SAL), n fapt este vorba de o unic instruciune.Semnificaiaesteurmtoarea:
temp CONTOR cat timp temp != 0 { CF b.c.m.s din OPR OPR 2*OPR (operatie fara semn) temp temp - 1 } pozit_OF_left

Aceast descriere nu spune altceva dect c bitul cel mai semnificativ al operandului trece n CF, dup care toi biii se deplaseaz la stnga cu o poziie (vezi Figura 2.3). Operaia se repet de attea ori ct este valoarea luiCONTOR(1sauconinutulregistruluiCL). InstruciuneaSHR(ShiftLogicRightDeplaseazlogicladreapta) Areformageneral:
SHR OPERAND, CONTOR

Semnificaiaesteurmtoarea:
temp CONTOR cat timp temp != 0 { CF b.c.m.p.s din OPR OPR OPR/2 (operatie fara semn) temp temp - 1 } pozit_OF_right

Descrierea de mai sus spune c bitul cel mai puin semnificativ din OPERAND trece n CF, dup care se deplaseaz toi biii cu o poziie la dreapta (mprire la 2). Faptul c operaia de mprire se execut fr semn nseamn c se completeaz cu un bit 0 dinspre stnga (vezi Figura 2.3). Operaia se repet de attea ori ct este valoarea lui CONTOR (1 sau coninutulregistruluiCL). InstruciuneaSAR(ShiftArithmeticRightDeplaseazaritmeticladreapta) Areformageneral:
SAR OPERAND, CONTOR

Semnificaiaesteurmtoarea:
temp CONTOR cat timp temp != 0 { CF b.c.m.p.s din OPR

65Capitolul2
OPR OPR/2 (operatie cu semn) temp temp - 1 } pozit_OF_right

Singura diferen fa de deplasarea logic la dreapta este realizarea mpririi la 2, lund n considerare semnul operandului. Aceasta nseamn c se conserv bitul de semn, mai precis, completarea dinspre stnga se face cu bituldesemn(veziFigura2.3). Aceste dou tipuri de deplasare la dreapta se reflect i n implementrile limbajelor de nivel nalt. De exemplu, standardul ANSI al limbajului C las neprecizat faptul c deplasarea la dreapta a unui ntreg de tip signed se face cu completare dinspre stnga cu 0 sau cu bitul de semn (deci operaie de tip SHR sau SAR) aceast alegere revine implementrii. Totui, la deplasarea cantitilor de tip unsigned, se completeaz ntotdeauna dinspre stnga cu 0 (deci se face deplasare logic). Acest fapt este important mai ales n cazul tipului char, care nu este specificat n standardul ANSI ca fiind cu semn sau frsemn. InstruciuneaROL(RotateLeftRotetelastnga) Areformageneral:
ROL OPERAND, CONTOR

Semnificaiaesteurmtoarea:
temp CONTOR cat timp temp != 0 { CF b.c.m.s. din OPERAND OPR 2*OPERAND + CF temp temp - 1 } pozit_OF_left

Descrierea de mai sus spune c bitul cel mai semnificativ din OPERAND trece att n CF, ct i n bitul cel mai puin semnificativ din OPERAND, dup ce toi biii acestuia sau deplasat la stnga cu o poziie (vezi Figura 2.3). Operaia se repet de attea ori ct este valoarea lui CONTOR (1 sau coninutulregistruluiCL). InstruciuneaRCL(RotateLeftthroughCarryRotetelastngaprincarry) Areformageneral:
RCL OPERAND, CONTOR

Semnificaiaesteurmtoarea:
temp CONTOR

Programarenlimbajdeasamblare66
cat timp temp != 0 { temp_cf CF CF b.c.m.s. din OPERAND OPR 2*OPERAND + temp_cf temp temp - 1 } pozit_OF_left

Descrierea de mai sus spune c bitul cel mai semnificativ din OPERAND trece n CF, se deplaseaz toi biii din OPERAND cu o poziie la stnga, iar CF original trece n bitul cel mai puin semnificativ din OPERAND. Cu alte cuvinte, CF particip efectiv la rotaie (vezi Figura 2.3). Operaia se repet de attea orictestevaloarealuiCONTOR(1sauconinutulregistruluiCL). InstruciuneaROR(RotateRightRoteteladreapta) Areformageneral:
ROR OPERAND, CONTOR

Semnificaiaeste:
temp CONTOR cat timp temp != 0 { CF b.c.m.p.s din OPERAND OPR OPR/2 (operaie fara semn) b.c.m.s. din OPERAND <--- CF temp temp - 1 } pozit_OF_right

Descrierea de mai sus spune c bitul cel mai semnificativ din OPERAND trece att n CF, ct i n bitul cel mai puin semnificativ, dup ce toi biii sau deplasat la dreapta cu o poziie (vezi Figura 2.3). Operaia se repet de atteaorictestevaloarealuiCONTOR(1sauconinutulregistruluiCL). InstruciuneaRCR(RotateRightthroughCarryRoteteladreaptaprincarry) Areformageneral:
RCR OPERAND, CONTOR

Semnificaiaesteurmtoarea:
temp CONTOR cat timp temp != 0 { temp_cf CF CF b.c.m.p.s. din OPERAND OPR OPR/2 (operatie fara semn) b.c.m.s. din OPERAND temp_cf temp temp - 1

67Capitolul2
} pozit_OF_right

Descrierea de mai sus spune c bitul cel mai puin semnificativ din OPERAND trece n CF, se deplaseaz toi biii din OPERAND cu o poziie la dreapta, iar CF original trece n bitul cel mai semnificativ din OPERAND. Cu alte cuvinte, CF particip efectiv la rotaie (vezi Figura 2.3). Operaia se repet de attea orictestevaloarealuiCONTOR(1sauconinutulregistruluiCL). Semnificaiile celor 7 instruciuni de deplasare i rotaie sunt ilustrate n Figura2.3. Sconsidermctevaexemplederotaiiideplasri. nmulirea/mprirea cu puteri ale lui 2. Operaiile de asemenea tip se executmultmaieficientprindeplasrilastnga/dreapta.Secvena:
MOV MOV SHL CL, 4 AH, 0 AX, CL

realizeaz nmulirea lui AL cu valoarea 16. Rezultatul se regsete n AX. Secvena:


MOV SAL CL, 3 BX, CL

realizeazmprirealuiBX(consideratnumrcusemn)lavaloarea8. Similar, se realizeaz i nmuliri cu valori care se pot exprima prin sume cu un numr redus de termeni de puteri ale lui 2. Secvena urmtoare realizeaz nmulirea unei valori N presupuse iniial n AL cu valoarea 13, prin deplasri iadunrirepetate.RezultatulseregsetenBX.
MOV MOV MOV MOV SHL ADD AH, BX, DX, CL, AX, BX, 0 AX AX 3 3 AX ; Salvare N ; Salvare N ; AX <--- N * 8 ; BX <--- N * 8 + N

Programarenlimbajdeasamblare68

Figura 2.3 Semnificaia operaiilor de deplasare i de rotaie


MOV MOV SHL ADD AX, CL, AX, BX, DX 2 CL AX ; Refacere N ; AX <--- N * 4 ; BX <--- N * 8 + N * 4 + N

2.3.Instruciunipentruoperaiicuiruride caractere/cuvinte
Acest grup de instruciuni implementeaz un set puternic de operaii cu iruri de octei sau de cuvinte. Prin ir se nelege o secven de octei sau de cuvinte, aflate la adrese succesive de memorie. Setul de instruciuni cuprinde

69Capitolul2
operaii primitive (la nivel de un octet sau un cuvnt) i prefixe de repetare, care pot realiza repetarea operaiilor primitive de un numr fix de ori sau pn landeplinireauneicondiiidetipcomparaie.

2.3.1Operaiiprimitive
Operaiile primitive se grupeaz n patru categorii, fiecare putnd fi pe octet sau pe cuvnt. Denumirea instruciunilor la nivel de octet se termin cu litera B,iaracelorlaniveldecuvntculiteraW.Acesteinstruciuninuauoperanzi. MoveString(Copiazir) MOVSB,MOVSW CompareString(Compariruri) CMPSB,CMPSW LoadString(ncarcirnAL/AX) LODSB,LODSW StoreString(DepuneAL/AXnir) STOSB,STOSW ScanString(ComparircuAL/AX) SCASB,SCASW Toate operaiile primitive folosesc registrele DS:SI ca adres surs i/sau ES:DI ca adres destinaie. De asemenea, toate operaiile primitive actualizeazadreseleimplicatenoperaie,nfelulurmtor: dac flagul DF = 0, adresele (registrul SI i/sau DI) sunt incrementate cu 1 sau cu 2, dup cum operaia primitiv este la nivel de octet sau de cuvnt dac flagul DF = 1, adresele (registrul i/sau DI) sunt decrementate cu 1 sau cu 2, dup cum operaia primitiv este la nivel de octet sau de cuvnt. Vomutilizanotaiile:
(SI) (SI) + delta (DI) (DI) + delta

unde delta este 1 sau 2, dup starea bistabilului DF sau a tipului operaiei (octetsaucuvnt). Starea flagului DF poate fi controlat prin instruciunile (fr operanzi) CLD (Clear Direction) i STD (Set Direction), care terg, respectiv seteaz acest bistabil. InstruciunileMOVSB,MOVSW Semnificaiaeste:
((ES:DI) ((DS:SI)) (SI) (SI) + delta (DI) (DI) + delta

Se transfer deci un octet (MOVSB) sau un cuvnt (MOVSW) de la adresa dat de(DS:SI)laadresadatde(ES:DI),dupcareseactualizeazadresele.

Programarenlimbajdeasamblare70 InstruciunileCMPSB,CMPSW Semnificaiaeste:


((DS:SI) - ((ES:DI)) (SI) (SI) + delta (DI) (DI) + delta

Se calculeaz temporar (fr a se modifica vreun operand) diferena dintre octeii (cuvintele) de la adresele (DS:SI) i (ES:DI), dup care se actualizeaz adresele. Bistabilii de condiie se poziioneaz conform operaiei de scdere.Instruciunilesefolosesclatestareaegalitii/inegalitiiirurilor. InstruciunileLODSB,LODSW Semnificaiaeste:
(acumulator) ((DS:SI)) (SI) (SI) + delta

Se ncarc deci n AL, respectiv AX, octetul, respectiv cuvntul de la adresa (DS:SI),dupcareseactualizeazaceastadres. InstruciunileSTOSB,STOSW Semnificaiaeste:
((ES:DI)) (acumulator) (DI) (DI) + delta

Se depune coninutul registrului AL, respectiv AX n octetul, respectiv cuvntul delaadresa(ES:DI),dupcareseactualizeazaceastadres. InstruciunileSCASB,SCASW Semnificaiaeste:
(acumulator) - ((ES:DI)) (DI) (DI) + delta

Se calculeaz temporar (fr a se modifica vreun operand) diferena dintre registrul AL, respectiv AX i octetul, respectiv cuvntul de la adresa (ES:DI), dup care se actualizeaz aceast adres. Bistabilii de condiie se poziioneaz conform operaiei de scdere. Instruciunile se folosesc la testarea/cutareaunuianumitoctet(cuvntntrunir). Pe lng formele fr operanzi, descrise mai sus, asamblorul mai recunoate i forme n care operanzii apar explicit. Semnificaia adreselor implicate n aceste instruciuni nu poate fi ns schimbat (se vor folosi tot registrele SI i DI). Singura raiune pentru aceste forme este specificarea unui prefix de segment pentru adresa surs. n acest caz, mnemonica instruciunii se scrie

71Capitolul2
fr litera B sau W de la sfrit, dar este obligatorie specificarea tipului operaiei prin operatorul PTR. Nu se recomand utilizarea acestor prefixe de segmentdinurmtoarelemotive: nu se poate schimba registrul de segment al adresei destinaie (acesta estetottimpulES) n condiiile folosirii prefixelor de repetare (vezi 2.3.2), instruciunea rezultat ar avea att prefix de repetare, ct i prefix de segment, ceea ce poate conduce la funcionri defectuoase, ntrun context n care pot apreantreruperiexterne.

2.3.2Prefixederepetare(REP/REPE/REPZ,REPNE/REPNZ)
Prefixele de repetare permit execuia repetat a unei operaii primitive cu iruri de octei sau de cuvinte, funcie de un contor de operaii sau de un contor i o condiie logic. Aceste prefixe nu sunt instruciuni n sine, ci particip la formarea unor instruciuni compuse, alturi de operaiile primitive descrisemaisus. Prefixul de repetare REP/REPE/REPZ (Repeat - Repet) Cele trei mnemonice identific de fapt un unic prefix de repetare. Forma generalauneiinstruciunicuacestprefixeste:
REP/REPE/REPZ op_primitiva

Semnificaiaeste:
cat timp CX != 0 { trateaza o eventuala intrerupere externa op_primitiva CX CX - 1 daca op_primitiva este CMPS/SCAS i ZF = 0, se iese din bucla }

Se vede, deci, c operaia primitiv se execut de un numr maxim de ori dat de coninutul registrului CX. Dac CX este iniial 0, operaia nu se execut nici o dat. n cazul operaiilor primitive CMPS i SCAS (care poziioneaz ZF), se iese forat din bucl dac ZF = 0, adic dac rezultatul operaiei primitiveestenenul.Buclaseexecutdecicttimpacestrezultateste0. De obicei, scrierea cu REP se folosete la primitivele de tip MOVS, LODS i STOS,iarscriereacuREPEsauREPZlaprimitiveledetipCMPSiSCAS. Sconsidermdouexemple. Secvena de mai jos transfer 100 de octei de la adresa SURSA la adresa DESTINATIE,ambelepresupusensegmentulcurentadresatprinDS.
.data SURSA db 100 dup (?) DEST db 100 dup (?)

Programarenlimbajdeasamblare72
.code CLD MOV MOV LEA LEA MOV REP AX, DS ES, AX SI, SURSA DI, DEST CX, 100 MOVSB ; ; ; ; ; ; ; Directie ascendenta Pregatire Adrese Adresa sursa Adresa destinatie Contor Instructiune compusa

Secvena urmtoare identific primul octet diferit de un octet dat dintrun ir delungime200deoctei.
.data SIR .code MOV MOV LEA CLD MOV MOV REPE AX, DS ES, AX DI, SIR AL, 'A' CX, 200 SCASB ; ; ; ; Se cauta primul octet diferit de 'A' Numar maxim de iteratii Bucla de cautare DB 200 dup (?)

Examinnd bistabilul ZF la ieirea din aceast secven, putem deduce rezultatul cutrii. Dac ZF = 0 nseamn c a avut loc o ieire forat din bucl, deci comparaia a dat rezultatul 0. Registrul DI, decrementat cu o unitate, furnizeaz adresa primului octet diferit de octetul din AL. Dac ZF = 1, nseamnctoiocteiiparcurisuntidenticicuoctetuldatnAL. La prima vedere, sar prea c, la fel de bine, am putea examina coninutul registrului CX la ieirea din bucl (0 sau diferit de 0), pentru a deduce dac octetul cutat a fost indentificat sau nu. Acest test este incorect, deoarece sar putea ca primul octet diferit de cel din AL s fie chiar ultimul. n acest caz, se iese din bucl cu CX = 0, la fel ca n situaia n care toi octeii parcuri sunt identicicuceldinAL. Prefixul de repetare REPNE/REPNZ (Repeat While Not Equal/Not Zero - Repet ct timp diferit/diferit de zero) Cele dou mnemonice identific un singur prefix de repetare. Forma general este:
REPNE/REPNZ operatie_primitiva

Semnificaiaeste:
cat timp CX != 0 { trateaza o eventuala intrerupere externa op_primitiva CX CX - 1 daca op_primitiva este CMPS/SCAS si ZF = 1, se iese din bucla }

73Capitolul2
Diferena fa de prefixul precedent este condiia de ieire forat din bucl: se iese dac ZF = 1, deci dac rezultatul operaiei primitive a fost 0. Ca atare, bucla se execut ct timp acest rezultat este nenul, dar nu mai mult de CXori. Practic, acest prefix de repetare se folosete numai cu operaiile primitive CMPS i SCAS. Pentru celelalte operaii primitive, n care nu se ia n considerare bistabilul ZF, se prefer scrierea cu prefixul REP. La ieirea din bucl, se poate examina bistabilul ZF, deducnduse dac a fost sau nu o ieire forat. Urmtoarea secven determin ultimul caracter egal cu un caracter dat, prin parcurgereairuluinsensinvers.
.data SIR .code LEA ADD MOV STD MOV DI, SIR DI, 29 CX, 30 AL, '?' ; Se cauta primul octet = 'x', de ; la dreapta la stanga db 30 (?)

REPNE SCASB

2.3.3Operaiicomplexeasuprairurilor
S considerm unele operaii complexe asupra irurilor de caractere. Vom considera c irurile au, ca ultim caracter, octetul 0, pe post de terminator de ir.
Compararea lexicografic a dou iruri

Acest algoritm primete ca date de intrare adresele a dou iruri de caractere terminate cu 0 i ntoarce diferena primilor octei care difer n cele dou iruri sau 0 dac cele dou iruri coincid. Urmtoarea secven de program ntoarce n AL rezultatul cerut. (Presupunem c DS i ES sunt iniializate corespunztor.)
.data SIR_1 DB 'Un exemplu de sir terminat cu zero', 0 SIR_2 DB 'Un exemplu de sir terminat cu octetul nul', 0 .code CLD LEA LEA IAR: LODSB TEST AL, AL JZ GATA ; (AL) = (SIR_1) ; Test terminator SI, SIR_1 DI, SIR_2

Programarenlimbajdeasamblare74
SCASB JE IAR DEC DI GATA: SUB AL, ES:[DI] ; ; ; ; ; Compara (AL) cu (SIR_2) Daca sunt egale, se reia bucla Daca nu, se revine pe caracterul anterior Se face diferenta

Copierea unui ir n alt ir

Urmtoarea secven copiaz un ir n alt ir. Copierea nceteaz dup copierea terminatorului din irul surs. Se presupune c la adresa destinaie se gsete suficient spaiu rezervat. Se presupune c registrele DS i ES indicsegmentulcurentdedate.
.data SURSA DB 'Un sir care trebuie copiat',0 DEST DB 80 DUP (?) .code LEA LEA CLD BUCLA: LODSB STOSB TEST AL,AL JNZ BUCLA Calculul lungimii unui ir ; ; ; ; (AL) <--- (SURSA) (DEST) <--- (AL) Test terminator Reluare SI, SURSA DI, DEST

Urmtoarea secven determin n AX numrul de caractere utile din irul SURSA.Terminatorul0nusenumr.


.code CLD LEA MOV MOV XOR REPNZ DEC SUB MOV DI, SURSA CX, 0FFFFH BX, DI AL, AL SCASB DI DI, BX AX, DI ; ; ; ; ; ; ; ; Numarul maxim posibil Salvare adresa inceput Octet cautat Repeta cat timp e diferit de 0 inapoi pe terminator Adresa terminator - Adresa de inceput = Lungime

Copierea a N caractere dintr-un ir n alt ir

Se copiaz un numr de N caractere din irul SURSA n irul DEST. Dac SURSA are mai puin de N caractere, se completeaz DEST cu 0, pn la N caractere.
.code CLD LEA SI, SURSA

75Capitolul2
LEA MOV OR JZ BUCLA: LODSB STOSB DEC JZ TEST JNZ REP GATA: CX GATA AL, AL BUCLA STOSB ; ; ; ; ; Bucla de copiere pana la terminator inclusiv, dar nu mai mult de CX caractere DI, DEST CX, N CX, CX GATA

; Completare eventual cu 0

Dac N este 0, nu se copiaz nimic. Se execut o bucl de copiere, n care se decrementeaz CX. Dac CX = 0, totul se termin. Dac sa copiat terminatorul, se iese din bucla de copiere. n acest moment, AL = 0 i, dac CX > 0, se execut depunerea lui AL n DEST, de attea ori ct este valoarea curentaluiCX.

2.4Instruciunideapeldeproceduridesalt(CALL,RET, JMP)
Procedurilesedefinescntextulsursdupablonul:
nume_proc PROC [ FAR | NEAR ] . . . RET nume_proc ENDP

unde nume_proc este numele procedurii, iar parametrii FAR sau NEAR (opionali)indictipulprocedurii. Procedurile sunt de dou tipuri: FAR i NEAR. O procedur FAR poate fi apelat i din alte segmente de cod dect cel n care este definit, pe cnd o procedur NEAR poate fi apelat numai din segmentul de cod n care este definit. Dac se omit parametrii FAR sau NEAR, tipul procedurii este dedus din directivele simplificate de definire a segmentelor (modelul de memorie folosit). De exemplu, modelul LARGE presupune c toate procedurile sunt implicit de tip FAR. n mod corespunztor, exist apeluri de tip FAR, respectiv NEAR, precum i instruciunidereveniredetipFAR,respectivNEAR. Instruciunea RET (Return) provoac revenirea n programul apelant. Putem scrie o instruciune Return explicit, n formele RETN (Return Near) sau RETF (Return Far), sau RET pur i simplu, caz n care tipul instruciunii Return este dedusdintipulprocedurii(FARsauNEAR).

Programarenlimbajdeasamblare76

2.4.1Apelulprocedurilorirevenireadinproceduri
InstruciuneaCALL(Apeldeprocedur) Poateaveaunadinformele: CALLnume_proc CALLFARPTRnume_proc CALLNEARPTRnume_proc n primul caz, tipul apelului este dedus din tipul procedurii, iar n celelalte, este specificatexplicit(FARsauNEAR). Tipul apelului trebuie s coincid cu tipul procedurii i cu tipul instruciunilor Return din interiorul procedurii, altfel se ajunge la funcionri defectuoase ale programului. SemnificaiainstruciuniiCALLesteurmtoarea:
CALL de tip NEAR (SP) (SP) - 2 SS:((SP) + 1 : (SP)) (IP) (IP) offset-ul primei instructiuni din procedura

Descrierea de mai sus spune c se salveaz n stiv contorul program curent, ntro manier similar instruciunii PUSH (se decrementeaz registrul SP cu 2 i se nscrie coninutul lui IP n vrful stivei). Registrul IP conine totdeauna adresa instruciunii care urmeaz (n memorie), dup instruciunea care se excut n mod curent. Practic, se salveaz n stiv adresa instruciunii de dup instruciuneaCALL.Aceastadresestenumitadresderevenire. Dup aceast salvare, se ncarc n IP adresa (deplasamentul) primei instruciuni din procedur, ceea ce nseamn un transfer al controlului ctre procedur. Este important de reinut c, n momentul intrrii n procedur, n vrful stivei exist adresa de revenire. Aceast adres nu trebuie modificat n nici un fel, n cazcontrar,revenireanprogramulapelantnemaifiindposibil. De observat c, n secvena de apel a procedurii, registrul CS nu se modific, ceeacenseamncsermnenacelaisegmentdecod.
CALL de tip FAR (SP) (SP) - 2 SS:((SP) + 1 : (SP)) (CS) (SP) (SP) - 2 SS:((SP) + 1 : (SP)) (IP) (CS) adresa de segment a primei instructiuni din procedura

77Capitolul2
(IP) offset-ul primei instructiuni din procedura

Ceea ce este diferit fa de apelul de tip NEAR este faptul c se salveaz adresa complet de revenire (pe 32 de bii), prin plasarea n stiv att a registrului IP, ct i a registrului CS. Similar, transferul controlului se face prin modificareaexplicitaperechiideregistre(CS:IP). De observat c instruciunea CALL de tip FAR este una din puinele instruciunicaremodificexplicitregistrulCS. InstruciuneaRET(ReturnReveniredinprocedur) Exist Return de tip FAR i Return de tip NEAR. Formele posibile ale instruciuniisunt: RETN[N] RETF[N] RET[N] ncareparantezeledreptespuncNesteoconstantntreagopional. n cea dea treia form, tipul instruciunii (NEAR sau FAR) este dedus din tipul procedurii. Semnificaiaesteurmtoarea:
Return de tip NEAR (IP) SS:((SP) + 1 : (SP)) (SP) (SP) + 2 [ (SP) (SP) + N ]

Se observ c se reface registrul (IP), prin copierea vrfului stivei i incrementarea registrului SP cu 2. Dac SP are aceeai valoare ca la intrarea n procedur i coninutul stivei nu a fost alterat ntre timp, atunci se copiaz practic n IP adresa de revenire, ceea ce provoac transferul controlului la instruciunea care urmeaz instruciunii CALL care a provocat apelul procedurii. Dac n formatul instruciunii RET exist constanta opional N, atunci se adun aceast constant la registrul SP. Acest tip de Return se numete Returncudescrcareastivei.
Return de tip FAR (IP) SS:((SP) + 1 : (SP)) (SP) (SP) + 2 (CS) SS:((SP) + 1 : (SP)) (SP) (SP) + 2 [ (SP) (SP) + N ]

Se reface din stiv perechea de registre (CS:IP), cu actualizarea registrului SP i,dacesteprezentconstantaN,seadunNlaSP.

Programarenlimbajdeasamblare78 Este important de reinut c instruciunile CALL i RET sunt instruciuni pereche: ele salveaz, respectiv refac adresa de revenire. Pentru ca mecanismul de apel/revenire s funcioneze corect, trebuie ndeplinite condiiile: tipul instruciunii CALL i tipul instruciunii RET trebuie s coincid (FAR sauNEAR) registrul SP din momentul execuiei instruciunii RET s aib aceeai valoarecalaintrareanprocedur(sindiceadresaderevenire) adresadereveniresalvatnstivsnufifostalteratdectreprocedur. nclcarea unora din cele trei condiii de mai sus constituie o eroare frecvent de programare. n astfel de cazuri, funcionarea programului este compromis, deoarece se plaseaz n CS i/sau IP o adres incorect, unde probabil nici nu exist vreun program cu sens. Acest tip de eroare se numete execuie de date, adic procesorul ajunge s execute nu instruciuni cu sens(definitentrunsegmentdecod),ciozonoarecaredememorie(date). Recunoaterea acestei erori este destul de uoar: se blocheaz tastatura, pe ecranul calculatorului apar tot felul de caractere ciudate, difuzorul ncepe s iuieetc.Singurasoluieestenacestcazunresetgeneralalcalculatorului. Putem, deci, enuna o regul de aur a programrii n limbaj de asamblare: Verificai controlul stivei !

2.4.2Instruciuneadesalt(JMP)
Areformageneral:
JMP tinta

n care tinta specific adresa de salt (punctul n care se va da controlul). Specificarea intei se poate face printro etichet sau printro expresie (vezi 2.4.3).Eticheteleauasociatuntip(NEARsauFAR)ipotfi: unnumedeprocedur oetichetdefinitcu:(detipNEAR) oetichetdefinitcudirectivaLABEL. Exempledeetichete:
et1: aici: et3 LABEL FAR gata LABEL NEAR

ExisttreitipurideinstruciuniJMP: de tip SHORT adresa int este situat la o adres n domeniul [128, +127]fadeadresainstruciuniiJMP

79Capitolul2
de tip NEAR adresa int este n acelai segment de cod cu instruciuneaJMP de tip FAR adresa int poate fi n alt segment de cod fa de instruciuneaJMP. TipuriledesaltpotfiexplicitateprinoperatorulPTR,ntrunadinformele:
JMP JMP JMP SHORT PTR tinta NEAR PTR tinta FAR PTR tinta

sau se deduc din atributele expresiei care precizeaz inta. n cazul etichetelor,tipuletichetei(FARsauNEAR)furnizeaztipulsaltului. SemnificaiainstruciuniiJMPeste:
JMP de tip SHORT (IP) (IP) + distanta dintre offset-ul curent si cel tinta JMP de tip NEAR (IP) offset-ul adresei tinta JMP de tip FAR (IP) offset-ul adresei tinta (CS) segmentul adresei tinta

Din punctul de vedere al programatorului, faptul c la saltul de tip SHORT se adun la IP o diferen este similar cu modificarea explicit a lui IP de la JMP detipNEAR. Ceeacediferestecodificareainternacelordouinstruciuni: la salt de tip SHORT, codul instruciunii conine diferena dintre offset ul curent i cel al intei. Aceast diferen se memoreaz intern pe un octet,deunderestriciadedomeniu[128,+127] lasaltdetipNEAR,codulinstruciuniiconineexplicitoffsetulintei. Se observ c salturile de tip NEAR i FAR sunt similare cu apelurile de procedur de tip NEAR sau FAR, fr ns a se salva adresa de revenire i identificndnumeleproceduriicuoetichet.

2.4.3Tipuridesalt/apel
Tipurile de instruciuni de salt i de apel specific modul de determinare a adresei int, respectiv al adresei procedurii. Deoarece aceste tipuri sunt identice pentru instruciunile JMP i CALL, vor fi prezentate mpreun. Prin instruciuni de salt nelegem aici cele de tip NEAR sau FAR (salturile de tip SHORT sunt implicit directe). De asemenea, n cele ce urmeaz identificm etichetelecunumeledeproceduri. JMP/CALLdetipdirect

Programarenlimbajdeasamblare80 Operandul care apare n formatul instruciunii este o etichet care identific punctulncaresedcontrolul(adresaint).Salturile/apeluriledirectepotfi: salturi/apeluri directe intrasegment (NEAR) eticheta este n acelaisegmentdecodcuinstruciuneaJMP/CALL salturi/apeluri intersegment (FAR) eticheta poate fi definit i n altsegmentdecoddectcelcareconineinstruciuneaJMP/CALL. Exemplu:
.code ALFA: ........ LABEL FAR ........ GAMMA PROC FAR ........... GAMMA ENDP ........... JMP/CALL ALFA JMP/CALL BETA JMP/CALL FAR PTR GAMMA BETA

; NEAR ; FAR implicit ; FAR explicit

JMP/CALLdetipindirect Operandul care apare n formatul instruciunii JMP/CALL reprezint un cuvnt (sau un dublucuvnt) din memorie, care conine adresa NEAR (sau FAR) undesevadacontrolul. Salturile/apelurileindirectepotfi: Salt/apel indirect intrasegment (NEAR) Formageneraleste:
JMP/CALL expr

ncareexprpoatefi: a)unregistrucareconineoffsetulintei b)ovariabildetipWORDcareconineoffsetulintei c) o expresie cu indici reprezentnd un cuvnt din memorie care conine offsetulintei d) o referire anonim la un cuvnt din memorie care conine offsetul intei. Sconsidermctevaexemple:
.data W_ALFA W_TAB_PROC dw dw dw dw N_ETIC N_PROC_0 N_PROC_1 N_PROC_2

81Capitolul2
.code N_ETIC: ; ........... N_PROC_i PROC NEAR ; ........... N_PROC_i ENDP ........... LEA BX, N_PROC_1 JMP/CALL BX ; JMP/CALL W_ALFA ; JMP/CALL W_TAB_PROC [SI] ; LEA BX, W_TAB_PROC JMP/CALL WORD PTR [BX] [SI]; LEA BX, W_ALFA JMP/CALL WORD PTR [BX] ; Eticheta NEAR i = 0, 1, 2

Tipul a) Tipul b) Tipul c); SI = 0, 2, 4 Tipul d); SI = 0, 2, 4 Tipul d)

Formele cu referiri anonime la memorie trebuie nsoite de operatorul WORD

PTR. Ultimele dou exemple de salt/apel (tipul d) pun n eviden dou nivele de indirectare (vezi Figura 2.4): de la BX la variabila W_ALFA i de la W_ALFA laetichetaN_ETIC. Figura 2.4 Cele dou nivele de indirectare la CALL WORD PTR [BX] Salt/apel indirect intersegment (FAR) Formageneraleste:
JMP/CALL expr

ncareexprpoatefi: a)ovariabildetipDWORDcareconineadresacompletaintei

Programarenlimbajdeasamblare82 b) o expresie cu indici reprezentnd un dublu cuvnt din memorie care conineadresacompletaintei c) o referire anonim la un dublu cuvnt de memorie care conine adresa intei. Sconsidermctevaexemple:
.data D_ALFA D_TAB_PROC dd dd dd dd F_ETIC F_PROC_0 F_PROC_1 F_PROC_2 Eticheta FAR ; i = 0, 1, 2

.code F_ETIC LABEL FAR ; ........... F_PROC_i PROC FAR ........... F_PROC_i ENDP ........... JMP/CALL D_ALFA ; JMP/CALL D_TAB_PROC [SI] ; LEA BX, D_TAB_PROC JMP/CALL DWORD PTR [BX][SI]; LEA BX, D_ALFA JMP/CALL DWORD PTR [BX] ;

Tipul a) Tipul b); SI = 0, 4, 8 Tipul c); SI = 0, 4, 8 Tipul c)

Formele cu referiri anonime la memorie trebuie nsoite de operatorul DWORD PTR. Ultimele dou exemple de salt/apel (tipul c) pun n eviden dou nivele de indirectare (vezi Figura 2.5): de la BX la variabila DALFA i de la DALFA la etichetaETIC. Apelurile indirecte de proceduri trebuie s respecte tipul procedurii. Astfel, o instruciune de forma CALL WORD PTR [BX] trebuie folosit numai cu proceduri de tip NEAR, iar una de tip CALL DWORD PTR [BX] numai cu proceduridetipFAR.

83Capitolul2
Figura 2.5 Cele dou nivele de indirectare la CALL DWORD PTR [BX] S considerm un exemplu de utilizare a tabelelor de adrese. Presupunem dezvoltarea unui meniu de comenzi, fiecare comand fiind reprezentat de un caracter alfabetic (de la 'A' la 'Z') Unele caractere pot s nu fie utilizate n meniu. De asemenea, presupunem caracterul n registrul AL i existena, pentrufiecarecomand,auneiproceduridetratare. O soluie evident, dar ineficient este compararea lui AL cu toate caracterele meniuluiicuapeluricorespunztoaredeproceduri,decicevadegenul:
CMP JZ CMP JZ AL, 'A' et_A AL, 'B' et_B ; etc.

Evident c, dac meniul este mare, o asemenea secven de program este greu de ntreinut. Adugarea sau eliminarea unei comenzi presupune parcurgereacuatenieacoduluisurs. Soluia adecvat a problemei const n definirea unei tabele cu adresele procedurilor de tratare, n ordinea alfabetic a comenzilor. Pentru literele de alfabet care nu sunt alocate nici unei comenzi, se scrie o procedur special PROC_NULL. La execuie, se va calcula poziia respectiv din tabel, chiar pebazacaracteruluidinALisevageneraunapelindirectdeprocedur.
.data TAB_CMD DW DW DW DW PROC_A PROC_B PROC_NULL PROC_D ; Comanda 'C' nu exista ; DW PROC_Z .code ; SUB ADD ADD MOV XOR CALL AL, 'A' AL, AL AL, AL BL, AL BH, BH WORD PTR TAB_CMD[BX] ; ; ; ; AL = 0...27 AL <-- 2*AL Se pune in cazul procedurilor FAR etc.

; BX = intrare ; in tabela

n cazul procedurilor far, se definete tabela TAB_CMD cu directiva Define DoubleWordisecalculeazBX4*AL,nlocdeBX2*AL. Aceast implementare este foarte uor de ntreinut. Eliminarea unei comenzi se face punnd adresa procedurii POC_NULL pe poziia corespunztoare.

Programarenlimbajdeasamblare84 Adugarea unei comenzi se face nlocuind procedura PROC_NULL cu proceduradetratareanoiicomenzi. Nici un tip de instruciune de salt sau de apel de procedur nu modific vreun bistabildecondiie.

2.4.4Instruciunidesaltcondiionat
Instruciunile din aceast categorie implementeaz salturi condiionate de valoarea unor bistabili de condiie. Prin extensie, instruciunile de salt obinuite (JMP) se mai numesc i salturi necondiionate. Instruciunile de saltcondiionatauurmtoarelecaracteristici: toate instruciunile de salt condiionat sunt de tip SHORT (deci directe), ceea ce nseamn c adresa int trebuie s fie la o distan cuprins ntre127i+128deocteifadeinstruciuneadesalt existmaimultemnemonicepentruaceeaiinstruciune dac condiia nu este ndeplinit, saltul nu are loc, deci execuia continucuinstruciuneaurmtoare existinstruciuniattpecondiiadirect,ctipecondiianegat bistabiliidecondiienusuntafectai. n Tabelul 2.6, se prezint instruciunile de salt condiionat. Prima coloan listeaz mnemonicele instruciunilor, coloana a doua listeaz condiia de salt, iar coloana a treia, interpretarea condiiei respective. Primele opt linii reprezint salturile pe condiiile directe, iar celelalte opt, salturile pe condiiile corespunztoarenegate. Denumirileinstruciunilorsecitescnforma: Jump (Salt) on (pe) <Interpretare> unde<Interpretare>estetextuldincoloanaatreia. Instruciunile de salt condiionat se utilizeaz dup o instruciune care modific bistabilii de condiie. Cea mai des ntlnit situaie este instruciuneadecomparaieCMP. Se observ c exist dou categorii de instruciuni pentru noiunile de mai mic i mai mare: cele care conin cuvintele above sau bellow i cele care conin cuvintele less sau greater. Primele se folosesc n situaia comparaiei a dou cantiti fr semn, iar ultimele, n situaia comparaieiunorcantiticusemn. S considerm urmtoarele secvene de program, n care se compar valorile 0FFHi1:
MOV MOV CMP JA AL, 0FFH BL, 1 AL, BL ET_1 MOV MOV CMP JG AL, 0FFH BL, 1 AL, BL ET_1

85Capitolul2
Se observ c (AL) > (BL) dac interpretm cele dou valori fr semn (255 > 1) i c (AL) < (BL) dac interpretm cele dou valori cu semn (1 < 1). Astfel, nprimulexemplu,saltullaetichetaET_1areloc,pecndnceldealdoileanu. Condiiile asupra bistabililor n cele dou tipuri de instruciuni i semnificaia bistabililor respectivi (vezi 2.2.1) explic cele dou tipuri de condiii. Reinemdeciurmtoarelereguli: Lacomparaiicusemn,folosimGREATERiLESS Lacomparaiifrsemn,folosimABOVEiBELLOW

Instruciune (mnemonic) JE,JZ JL,JNGE JLE,JNG JB,JNAE,JC JBE,JNA JP,JPE JO JS JNE,JNZ JNL,JGE JNLE,JG JNB,JAE,JNC JNBE,JA JNP,JPO JNO JNS

Condiie de salt ZF=1 SFOF SFOFsauZF=1 CF=1 CF=1sauZF=1 PF=1 OF=1 SF=1 ZF=0 SF=OF SF=OFiZF=0 CF=0 CF=0iZF=0 PF=0 OF=0 SF=0

Interpretare Zero,Equal Less,NotGreaterorEqual LessorEqual,NotGreater Below,NotAboveorEqual,Carry BeloworEqual,NotAbove Parity,ParityEven Overflow Sign NotZero,NotEqual NotLess,GreaterorEqual NotLessorEqual,Greater NotBelow,AboveorEqual,NotCarry NotBeloworEqual,Above NotParity,ParityOdd NotOverflow NotSign

Tabelul 2.6 Instruciunile de salt condiionat Uneori este necesar s scriem instruciuni de salt condiionat la etichete care ies n afara domeniului [128, +127] fa de instruciunea curent. n aceast situaie, folosim urmtoarea schem, prin care nlocuim saltul pe o condiie direct departe cu un salt pe condiia negat aproape i cu un salt necondiionatdeparte.
Salt conditionat pe conditie directa la ET_1 ; Eticheta ET_1 e prea departe ET_1:

Programarenlimbajdeasamblare86 Formaechivalenteste:
Salt conditionat pe conditie negata la ET_2 Salt neconditionat la ET_1 ET_2:

Deexemplu,instruciunea:
JE ET_1

sesubstituiecu:
JNE JMP ET_2: ET_2 ET_1

n schema echivalent, eticheta ET_1 poate fi la orice distan fa de punctuldesalt.

2.4.5Instruciunipentrucontrolulbuclelordeprogram(JCXZ,LOOP, LOOPZ/LOOPE,LOOPNZ/LOOPNE)
InstruciuneaJCXZ(JumpifCXisZeroSaltdacCXestezero) Areformageneral:
JCXZ etic

unde etic este o etichet aflat n domeniul [128, +127] fa de instruciunea curent(lafelcalasalturiledetipSHORT). Semnificaiaesteevident:
daca (CX) = 0 (IP) (IP) + distanta dintre offset-ul curent si cel tinta

adicsesarelaetichetaspecificatdacCXconinevaloarea0. Instruciunideciclare(LOOPxxCicleaz) Aceste instruciuni sunt, de fapt, salturi condiionate de valoarea registrului CX i de bistabilul ZF. La fel ca prefixele de repetare, cu care, de altfel, se aseamn oarecum, exist cte dou mnemonice pentru aceeai instruciune. Formalorgeneraleste:
LOOPxx etic

unde etic este o etichet aflat n domeniul [128, +127] fa de instruciunea curent. ToateacesteinstruciuniutilizeazregistrulCXcanumrdeiteraii. InstruciuneaLOOP

87Capitolul2
Semnificaiaesteurmtoarea:
CX CX - 1 daca CX != 0, atunci (IP) (IP) + distanta dintre offset-ul curent si cel tinta

Cu alte cuvinte, se decrementeaz CX i, dac acesta este diferit de zero, se sarelaetichetaspecificat. Urmtoarea secven calculeaz suma (pe 16 bii) a elementelor unui tablou TABDE100dentregiiodepunenvariabilaSUMA.
.data TAB SUMA .code XOR MOV MOV NEXT: ADD ADD LOOP MOV AX, TAB [SI] SI, 2 NEXT SUMA, AX ; ; ; ; Calcul suma Actualizare indice Cicleaza Depune rezultat AX, AX CX, 100 SI, AX ; Initializeaza suma ; Numar de iteratii ; Initializeaza indice DW 100 DUP (0) DW ?

Forma general a unei bucle de program realizat cu instruciunea LOOP este:


start_bucla: ; ; ; Corp bucla ; ; ; LOOP start_bucla

Corpul buclei se va executa de attea ori ct este coninutul iniial al registrului CX (presupunnd c acesta nu este modificat explicit n interiorul buclei). Trebuie observat c registrul CX este mai nti decrementat i apoi testat. Ca atare, dac (CX) este iniial 0, bucla de program se va executa de 65535 de ori. Protecia fa de o asemenea situaie se realizeaz prin instruciunea JCXZ.Formacorectabucleideprogramvafi:
JCXZ end_bucla start_bucla: ; ; ; Corp bucla ; ; ; LOOP start_bucla end_bucla:

Programarenlimbajdeasamblare88 n forma de mai sus, dac (CX) este iniial 0, corpul buclei nu se execut niciodat. n situaia n care corpul buclei ocup mai mult de 128 de octei, trebuie s renunm la JCXZ i LOOP i s le nlocuim cu comparaii i cu salturi explicite.Bucladeprogramvaaveaformageneral:
TEST CX, CX JNZ start_bucla JMP end_bucla start_bucla: ; ; ; Corp bucla ; ; ; DEC CX TEST CX, CX JZ end_bucla JMP start_bucla end_bucla:

Urmtorul exemplu calculeaz primele 20 de numere Fibonacci (fib(n), n =1,...,20),definiterecursivprin: f(0)=0,f(1)=1 f(k)=f(k1)+f(k2),dacn>1 i le depune n tabloul FIBO. Cele trei valori (f(k), f(k1) i f(k2)) care intervin n calculsuntinutenregistreleAX,BXiDX.
.data FIBO DW 20 DUP (?) .code MOV MOV MOV MOV bucla: MOV AX, BX ADD AX, DX ; f(k) <-- f(k-1) + f(k-2) MOV FIBO [DI], AX ; Depune rezultat ADD DI, 2 ; Actualizeaza indice MOV DX, BX ; f(k-1) devine f(k-2) MOV BX, AX ; f(k) devine f(k-1) LOOP bucla ; Cicleaza BX, DX, CX, DI, 0 1 20 0 ; ; ; ; f(0) f(1) Contor Indice in tabloul

Instruciunea LOOPZ/LOOPE (Loop While Zero/Equal Cicleaz ct timp este zero/egal) Semnificaiaesteurmtoarea:
CX CX - 1 daca CX != 0 si ZF = 1, atunci (IP) (IP) + distanta dintre offset-ul curent si cel tinta

89Capitolul2

Se decrementeaz deci CX i, dac acesta este diferit de zero i bistabilul ZF este 1 (adic rezultatul ultimei operaii aritmetice a fost zero), se sare la eticheta specificat. De obicei, pentru poziionarea bistabilului ZF se utilizeaz oinstruciunedecomparaie. Exemplul urmtor determin primul ntreg diferit de zero dintrun tablou TABL de100dentregi.
.code MOV CX, 100 LEA BX, TABL MOV SI, -2 next: ADD SI, 2 CMP WORD PTR [BX][SI], 0 LOOPZ next JNZ gasit

Dac bistabilul ZF este 0 la ieirea din bucl nseamn c sa identificat primul ntreg diferit de 0, iar SI conine adresa acestui ntreg. n caz contrar, toate cele100deelementealetablouluisuntnule. Instruciunea LOOPNZ/LOOPNE (Loop While Not Zero/Not Equal Cicleaz ct timpestediferitdezero/diferit) Semnificaiaesteurmtoarea:
CX CX - 1 daca CX != 0 si ZF = 0, atunci (IP) (IP) + distanta dintre offset-ul curent si cel tinta

Condiia asupra bistabilului ZF este negata condiiei de la LOOPZ/LOOPE. Efectul este c se cicleaz ct timp rezultatul ultimei operaii aritmetice este diferitdezero,darnudemaimulteorictesteconinutuliniialalluiCX. De remarcat asemnrile i deosebirile care exist ntre instruciunile de ciclareiprefixelederepetaredelaoperaiicuiruri(vezi2.3.2).

2.5.ntreruperi
Noiunea de ntrerupere presupune (aa cum i arat i numele) ntreruperea programului n curs de execuie i transferul controlului la o anumit rutin specific, numit rutin de tratare, dictat de cauza care a generat ntreruperea. Mecanismul prin care se face acest transfer este, n esen, de tip apel de procedur, ceea ce nseamn revenirea n programul ntrerupt, dup terminarea rutineidetratare.

Programarenlimbajdeasamblare90

2.5.1ntreruperihardwareisoftware.Tabeladentreruperi
ntreruperile se pot clasifica dup mai multe criterii, rezultnd tipurile ilustrate n Figura2.7.

Figura 2.7 Clasificarea ntreruperilor ntreruperile software apar ca urmare a execuiei unor instruciuni, cum ar fi INT,INTO,DIV,IDIV ntreruperile hardware externe sunt provocate de semnale electrice care se aplicpeintrriledentreruperiINTiNMIaleprocesorului ntreruperile hardware interne apar ca urmare a unor condiii speciale de funcionareaprocesorului(cumarfiexecuiapascupasaprogramelor) ntreruperile dezactivabile sunt provocate de semnalul electric aplicat pe linia (intrarea)INTisuntluatenconsiderarenumaidacbistabilulIFeste1. ntreruperile nedezactivabile sunt provocate de semnalul electric aplicat pe linia NMIisunttotdeaunaluatenconsiderare. ntreruperile hardware dezactivabile sunt controlate de unul sau mai multe circuite specializate (controlere de ntreruperi 8259A), care accept fiecare cel mult opt cereri de ntreruperi, pe care le transmit ctre linia INT a procesorului. Dac bistabilul IF este 1, procesorul rspunde printro secven de semnale electrice INTA (Interrupt Acknowledge), asemntoare unei secvene de citire a codului unei instruciuni. Pe durata unuia din aceste semnale, controlerul

91Capitolul2
care a iniiat cererea de ntrerupere plaseaz pe magistrala de date octetul care identific nivelul ntreruperii. Un asemenea sistem se numete sistem vectorizatdentreruperi(veziFigura2.8).

Figura 2.8 ntreruperi hardware vectorizate ntrun sistem cu procesor 8086, pot exista maxim 256 de ntreruperi (nivele) distincte. Fiecare din aceste nivele poate avea asociat o procedur de tip far, numit rutin de tratare. Adresele acestor rutine sunt trecute ntro aa numit tabel de ntreruperi, aflat la adresele fizice 00000003FFH, ocupnd deci 1024 de octei. Fiecare nivel ocup 4 octei, primii reprezentnd offsetul, iar urmtoriiadresadesegmentaprocedurii(veziFigura2.9). Laapariiauneintreruperi,aulocurmtoareleaciuni: sesalveaznstivregistreleFLAGS,CSiIP(naceastordine) setergbistabiliiIFiTF se furnizeaz procesorului un ntreg pe 8 bii (deci n gama 0 255), numit ivectordentrerupere,careidentificnivelulasociatntreruperii se execut un salt indirect intersegment la adresa de nceput a rutinei de tratare,prinintermediultabeleidentreruperi. Vectoruldentreruperepoatefifurnizatprocesoruluinurmtoarelemoduri: n cazul ntreruperilor hardware interne, nivelul este implicit de exemplu, pentru ntreruperea de execuie pas cu pas (generat dac bistabilul TF=1),seutilizeaztotdeaunanivelul1 n cazul ntreruperilor hardware externe, nivelul este plasat pe magistrala de date, n cadrul ciclului main (Interrupt Acknowledge), care urmeaz

Programarenlimbajdeasamblare92 dup luarea n considerare a ntreruperii de ctre dispozitivul care a generatntreruperea ncazulntreruperilorsoftware,nivelulesteconinutninstruciune.

Figura 2.9 Tabela de ntreruperi Se observ c, exceptnd salvarea flagurilor i tergerea bistabililor IF i TF, secvena de tratare a unei ntreruperi se reduce la un apel indirect de procedurfar,prinintermediultabeleidentreruperi.

2.5.2Instruciunispecificentreruperilor(INT,IRET,INTO)
InstruciuneaINT(Interruptntreruperesoftware) Areformageneral:
INT n

undenesteoconstantntreagngama0255. Semnificaiaesteurmtoarea:
(SP) (SP) - 2 SS:((SP) + 1 : (SP)) (FLAGS) IF 0, TF 0 (SP) (SP) - 2

93Capitolul2
SS:((SP) + 1 : (CS) (4*n + (SP) (SP) SS:((SP) + 1 : (IP) (4*n) (SP)) (CS) 2) 2 (SP)) (IP)

Se ncarc, deci, n CS i IP coninutul de la adresele fizice 4n+2 i 4n, adicceipatruocteicorespunztoriniveluluindintabeladentreruperi. InstruciuneaIRET(InterruptReturnReveniredinntrerupere) Datorit aciunilor care au loc la apariia unei ntreruperi, o procedur de tratare nu se poate ncheia cu o instruciune RETF, deoarece trebuie refcut i registrul de flaguri. Ca atare, procedurile de tratare a ntreruperilor se ncheie totdeaunacuinstruciuneaIRET. Instruciunea,careestefroperanzi,aresemnificaiaurmtoare:
(IP) (SP) (CS) (SP) (FLAGS) (SP) SS:((SP) + 1 : (SP)) (SP) + 2 SS:((SP) + 1 : (SP)) (SP) + 2 SS:((SP) + 1 : (SP)) (SP) + 2

Se observ c bistabilii IF i TF, care au fost teri la apariia ntreruperii, sunt refcui aa cum erau nainte de ntrerupere, o dat cu ceilali bistabili din registrulFLAGS. InstruciuneaINTO(InterruptifOverflowntreruperencazdedepire) Instruciunea,careestefrparametri,aresemnificaiaurmtoare: dac OF = 1, atunci se execut secvena corespunztoare unei instruciuniINT4. Codificarea instruciunilor INT este pe doi octei, cu excepia instruciunii INT 3, la care codificarea este pe un singur octet. Acest fapt nu este ntmpltor, deoarece nivelele 2 i 3 sunt, n general, utilizate de programele de depanare(debuggere). Astfel, rularea pas cu pas a unui program se face setnd bistabilul TF i scriind pe nivelul 1 al tabelei de ntreruperi adresa unei rutine proprii de tratare. La execuia fiecrei instruciuni, se va da controlul rutinei proprii, care va afia corespunztor starea programului. Rularea pn la o adres dat (breakpoint) se realizeaz prin nlocuirea octetului de la adresa respectiv cu codul unei instruciuni INT 3. Astfel, cnd programul care se execut ajunge la acea adres,sedcontrolulrutineidetratarepenivelul3. Nivelelepredefinitedentreruperesunt,deci: 0depirelamprire(cauzeposibile:instruciunileDIVsauIDIV)

Programarenlimbajdeasamblare94 1execuiepascupas(cauzposibil:bistabilulTF=1) 2 ntrerupere extern nedezactivabil (cauz posibil: semnal electric pe liniadentreruperenedezactivabilNMI) 3execuiepascupas(cauzposibil:instruciuneaINT3) 4depire(cauzposibil:instruciuneaINTO). La calculatoarele de tip IBMPC, se mai pot cita ntreruperile hardware de la ceasuldetimpreal(nivelul8)idelatastatur(nivelul9). ntreruperile software n gama 20H2FH sunt folosite de sistemul de operare DOS,iarcelengama10H1AHdectresubsistemuldeintrriieiriBIOS.

2.6Instruciunipentrucontrolulprocesorului
Toateinstruciuniledeacestgensuntfroperanzi. O prim categorie de instruciuni se refer la controlul explicit al unor bistabili decondiie(CLC,STC,CMC,CLD,STD,CLIiSTI). Instruciunile CLC (Clear Carry Flag), STC (Set Carry Flag) i CMC (Complement Carry Flag) efectueaz operaiile de tergere, setare i, respectiv,complementareabistabiluluiCF. Instruciunile CLD (Clear Direction Flag) i STD (Set Direction Flag) terg,respectiv,seteazbistabilulDF. Instruciunile CLI (Clear Intrerrupt Flag) i STI (Set Interrupt Flag) terg, respectiv, seteaz bistabilul IF. Cnd IF = 0, ntreruperile externe nedezactivabile nu sunt luate n considerare. Astfel, o aa numit secven critic de program (care nu dorim s fie ntrerupt) se protejeaz printro instruciune CLI nainte i o instruciune STI dup. O secven critic tipic estemodificareaexplicitatabeleidentreruperi. O alt serie de instruciuni (HALT, LOCK, WAIT) realizeaz unele operaii specialeasupraprocesorului. Astfel, instruciunea HALT (Oprire procesor) foreaz procesorul ntro stare special de inactivitate, din care se poate iei doar prin ntreruperi externe sauprinresetgeneral. Prefixul LOCK (Blocare magistral) se poate folosi naintea oricrei instruciuni, efectul fiind c pe durata instruciunii, accesul unui alt dispozitiv la magistrala sistemului hardware este blocat. ntrun sistem multiprocesor, nu este suficient s protejm secvenele critice prin instruciuni CLI/STI, deoarece controlul magistralei ar putea fi preluat de un alt procesor. De aici, utilitateaprefixuluiLOCK. Instruciunea WAIT (Ateapt) este folosit pentru a sincroniza activitatea procesorului cu cea a unui alt dispozitiv, de obicei un coprocesor matematic.

95Capitolul2
Execuia unei instruciuni matematice este preluat de coprocesor totui, procesorul de baz nu poate continua programul pn nu primete un semnal de la coprocesor, prin care se anun sfritul operaiei executate. Aceast sincronizare se realizeaz printrun semnal electric aplicat pe linia TEST a procesorului de baz. Ca atare, instruciunea WAIT va fora procesorul de baz ntro stare de inactivitate, pn la apariia unui semnal electric pe linia TEST. n fine, exist i o instruciune care nu face nimic: instruciunea NOP (No Operation). Scopul unei asemenea instruciuni este de a introduce o ntrziere n program. Asamblorul recunoate mnemonica NOP, dar codificarea intern este aceeai cu a instruciunii XCHG AX, AX, care, evident, nu face nimic.

2.7Dezvoltareaprogramelornlimbajdeasamblare
Acum, dup ce am parcurs setul de instruciuni al procesorului, putem trece la prezentarea unui cadru de dezvoltare al programelor n limbaj de asamblare. Contextul ales este cel al calculatorului de tip IBMPC sub sistemul de operare DOS i al produselor software Borland: asamblorul TASM (Turbo Assembler), linkeditorul TLINK (Turbo Linker), bibliotecarul TLIB (Turbo Librarian) i depanatorulinteractivTD(TurboDebugger). Vom utiliza extensiile implicite ale fiierelor: .ASM pentru fiiere surs, .OBJ pentrufiiereobiect, .EXEsau .COMpentrufiiereexecutabile. O problem specific limbajului de asamblare este absena unor instruciuni de intrareieire de nivel nalt. Pentru asemenea operaii, va trebui s ne scriem propriile rutine. n aceast lucrare, vom utiliza o serie de proceduri i macroinstruciuni, implementate n fiierul IO.H (fiier header, listat n Anexa A) i n fiierul IO.ASM (fiier surs, listat n Anexa B). Aceste fiiere asigur (ntrealtele)suportpentruurmtoareleoperaiidebaz: introducereadecaracteredelaconsol afiareadecaracterelaconsol introducereadeiruridecaracteredelaconsol afiareadeiruridecaracterelaconsol afiareaunormesajeimediatelaconsol introducereadentregipe16biicusaufrsemndelaconsol afiareadentregipe16biicusaufrsemnlaconsol iniializarearegistrelorDSiESlaintrareanprogram terminareaprogramuluicuieirensistemulDOS.

Programarenlimbajdeasamblare96 Se vor utiliza directivele de definire simplificat a segmentelor. ablonul de dezvoltare al unui program ASM care conine un modul executabil va fi urmtorul:
.model include .stack .data .code ; Definitii de proceduri start: init_ds_es ; Program principal exit_dos start MMMMM io.h NNNN ; Definitii de date

end

unde: MMMMM este modelul de memorie, care poate fi tiny, small, medium, compact, large sau huge modelele uzuale sunt small i large, n care toate adresele, procedurile, apelurile, salturile i revenirile dinprocedursuntimplicitdetipNEAR,respectivdetipFAR NNNN este dimensiunea rezervat segmentului de stiv o valoare uzual este1024 include io.h este o directiv care include n textul surs fiierul io.h, care trebuiessegseascnacelaicatalog(director)cufiierulsurs init_ds_es este o macroinstruciune (definit n io.h) care iniializeaz registrele DS i ES cu adresa segmentului de date registrele SS i CS sunt iniializate automat la ncrcarea programului executabil de pe disc. exit_dos este o macroinstruciune (definit n io.h) care provoac terminareaprogramuluiirevenireansistemulDOS start este o etichet care marcheaz punctul de nceput al programului principal end start este o directiv care precizeaz c modulul curent este modul deprogramprincipal,avndpunctuldeintrarelaetichetastart. O alt variant este scrierea programului principal sub forma unei proceduri (avnd numele, de exemplu, _main) i precizarea punctului de start prin numele procedurii:
.model include .stack .data .code MMMMM io.h NNNN ; Definitii de date

97Capitolul2
; Definitii de proceduri _main proc init_ds_es ; Program principal exit_dos _main endp end _main

Un modul de program care nu este modul de program principal (deci conine definiii de date i/sau proceduri) nu are etichet n directiva end. ntro aplicaie dezvoltat modular (n mai multe fiiere surs), un singur modul poatefimoduldeprogramprincipal. Asamblorul nu face distincie ntre simboluri scrise cu litere mici sau mari. De acum ncolo, vom scrie de regul programele cu litere mici, iar cu litere mari unele directive i tipuri de date definite de utilizator, pentru a le scoate n eviden. AsamblareaunuifiiersursNUME.ASMsefacecuunadincomenzile:
C:\> tasm nume.asm C:\> tasm nume

nurmacreiarezultunfiierobiectNUME.OBJ. Dacsedoreteifiierlisting,sedcomanda:
C:\> tasm nume ,,nume

nurmacreiarezultiunfiierNUME.LST. Dac se dorete o depanare simbolic ulterioar, trebuie introdus opiunea /zi:
C:\> tasm nume /zi

Operaiadeasamblaresefacepentrufiecarefiiersursnparte. Legareamodulelorsefacecucomanda:
C:\> tlink nume_1 nume_2 ... [, nume_bin ] [/v]

n care parantezele drepte indic parametrii opionali nume_1, nume_2 sunt numele modulelor obiect, nume_bin este numele fiierului executabil rezultat (dac lipsete, se consider numele primului modul obiect), iar /v este o opiune de depanare simbolic (se introduce dac vrem s executm programul sub controlul depanatorului TD). n urma comenzii, rezult un fiier executabil. O situaie tipic este cea a unui singur modul surs, caz n care comanda de legarevafi:
C:\> tlink nume io

Programarenlimbajdeasamblare98 prin care se leag i modulul io.obj (care conine procedurile de intrareieire descrisemaisus). Peste tot n cuprinsul crii vom considera c irurile de caractere sunt terminate cu octetul 0 binar. Definiia unui ir constant sau rezervarea de spaiu pentru un ir variabil se pot face prin directiva Define Byte (constantele simbolice cr i lf sunt definite n fiierul io.h). Definiia unui ntreg sau rezervarea de spaiu pentru un ntreg se poate face cu directiva Define Word. DefinireadespaiulaniveldecaractersefacecudirectivaDefineByte.
.data sir_1 sir_2 i_1 i_2 u_1 u_2 c_1 c_2 db db dw dw dw dw db db 'Un sir de caractere', cr, lf, 0 80 dup (0) -200 ? 0FFFFH -1 'A' ?

Afiarea unui ir de caractere la consol se poate macroinstruciunea puts (Put String),nunadinformele:


puts lea puts sir_1 si, sir_1 [si] ; O prima forma de invocare ; O a doua ; forma de invocare

face

prin

Citirea unui ir de caractere de la consol se poate macroinstruciuneagets (Get String),nunadinformele:


gets lea gets sir_2 bx, sir_2 [bx] ; O prima forma de invocare ; O a doua ; forma de invocare

face

cu

Afiarea unui ir constant de caractere (mesaj la consol) se poate face cu macroinstruciunea putsi (Put String Immediate), care nu necesit definireairuluiiniciprezenaexplicitaterminatorului0:
putsi <'Introduceti un sir de caractere', cr, lf> gets sir_2 putsi <'Sirul introdus este:', cr, lf> puts sir_2 putsi <cr,lf>

Introducerea unui ntreg cu sau fr semn se poate face cu macroinstruciunile geti (Get Integer), fr parametri, care ntoarce ntregulcititnregistrulAX. Afiarea unui ntreg cu sau fr semn se poate face cu macroinstruciunile puti (Put Integer)sauputu (Put Unsigned),nunadinformele:

99Capitolul2
geti puti mov puti putu lea puti putu ax i_1, ax i_1 u_1 di, i_2 [di] [di] ; ; ; ; ; Citeste intreg in AX Afiseaza intregul din AX Depune Afiseaza intreg cu semn din memorie Afiseaza ca numar fara semn

; Afiseaza ca numar cu semn ; Afiseaza ca numar fara semn

Introducerea unui singur caracter de la consol se poate face cu macroinstruciunea getc (Get Character), care ntoarce caracterul n registrul AL, iar afiarea unui caracter se poate face cu macroinstruciunea putc (Put Character),nunadinformele:
putc putc lea putc 'A' car_1 bx, car_2 [bx]

Toate macroinstruciunile de mai sus conserv registrele procesorului, deci nu enevoiedesalvriirestaurriexplicite. Sconsidermunexempludeprogram,ncaresefacurmtoareleoperaii: secitescdelaconsolcelmult20dentregicusemn seafieazvalorileintroduse sesorteazcresctoracestevalori seafieazvalorilesortate. Considerm modelul de memorie large, adic toate adresele sunt implicit de 32 de bii. Pentru sortare, vom folosi un algoritm elementar (metoda bulelor), descrismaijos(seconsidercindiciidintabloulavariazdela0lan1):
for i = 1 to n-1 for j = n - 1 downto i if ( a[j-1] > a[j] ) schimba a[j] cu a[j-1]

Implementareantreguluiprogramesteurmtoarea:
.model large include io.h .stack 1024 .data vec dw 20 dup (?) n dw ? .code tipvec proc far ; Procedura de afisare vector. ; Date de intrare: ; ds:si = adresa vector de intregi

Programarenlimbajdeasamblare100
; tip: puti putsi add loop tipend: ret tipvec endp [si] <' '> si, 2 tip ; ; ; ; Afisare intreg cu semn Spatiu Actualizare adresa Bucla dupa CX cx = numar de elemente jcxz tipend ; Nu avem ce afisa

bubble proc far : Procedura de sortare ; Date de intrare ; ds:bx = adresa tablou de intregi ; cx = dimensiune tablou ; Variabila i : asignata la si ; Variabila j : asignata la di ; Adresa de inceput a tabloului: asignata la bx cmp jbe mov fori: mov dec forj: shl mov cmp jle xchg mov nextj: shr dec cmp jae nexti: inc si cmp si, cx jb fori algend: ret bubble endp ; Programul principal start: init_ds_es putsi <'Introduceti datele',cr,lf> mov cx, 20 ; Numar maxim ; de elemente lea bx, vec ; Adresa tablou ; Ciclu to ; Cat timp i < n di, 1 di di, si forj ; Refacere indice ; Ciclu downto ; Cat timp j >= i di, 1 ax, [bx][di-2] ax, [bx][di] nextj ax, [bx][di] [bx][di-2], ax ; ; ; ; ; ; intregii pe 2 octeti a[j-1] Compara cu a[j] Mai mic sau egal Schimba a[j] cu a[j-1] di, cx di ; j = n-1 cx, 1 algend si, 1 ; Nu avem ce sorta ; i = 1

101Capitolul2
iar: geti test jz mov add loop gata: mov sub mov ax, 20 ax, cx n, ax ; Calcul numar de ; elemente introduse ax, ax gata [bx], ax bx, 2 iar ; ; ; ; ; ; Citire intreg cu semn Este 0 ? Daca da, gata Depunere in tablou Actualizare adresa Bucla dupa CX

putsi <'Vector nesortat', cr, lf> lea si, vec ; Adresa tablou mov cx, n ; Numar de elemente call tipvec ; Afisare tablou ; nesortat lea mov call bx, vec cx, n bubble ; Adresa tablou ; Numar de elemente ; Sortare tablou

end

putsi <cr,lf,'Vector sortat', cr, lf> lea si, vec mov cx, n call tipvec ; Afisare tablou sortat exit_dos ; Iesire in DOS start

n segmentul de date, se rezerv spaiu pentru tabloul vec de cel mult 20 ntregiipentrudimensiuneanaacestuia. Procedura TIPVEC primete n SI adresa unui tablou i n CX numrul elemente, realiznd afiarea la consol a elementelor, considerate ntregi semn. Se observ forma standard a unei bucle de program implementat instruciuneaLOOP.

de de cu cu

Procedura BUBBLE implementeaz algoritmul de sortare. Indicii i i j din descrierea algoritmului sunt asignai la regitrii SI i DI. Indicii sunt incrementai sau decrementai cu 1, dar ntregii sunt pe doi octei. De aceea, n secvena de adresare a memoriei, se nmulete temporar DI cu 2, pentru a accesa corect elementele tabloului. Astfel, elementul de indice 0 se va afla la deplasament 0, elementul de indice 1 la deplasament 2 etc. nmulirea i refacerea se realizeaz prin deplasri logice. Se observ secvena standard de interschimbare a dou elemente din memorie (dou MOVuri i un XCHG). Trebuie remarcat modul n care se fac comparaiile diverselor elemente: indicii sunt considerai fr semn, deci testele se fac cu instruciuni de salt condiionat de tip Above sau Below. n schimb, tabloul este cu semn, deci comparaiile ntre elemente se fac cu instruciuni de salt condiionat de tip Greater sau Less. Programul principal ncepe printro bucl de citire a datelor. Introducerea se poate opri mai devreme de 20 de elemente dac se

Programarenlimbajdeasamblare102 introduce valoarea 0. La ieirea din bucl, se calculeaz numrul de elemente efectiv introduse, ca diferena dintre numrul maxim admis (20) i valoarea curent a lui CX. Acest numr se depune n variabila n, pentru utilizri viitoare. n continuare, vom avea secvene de apel ale procedurilor TIPVEC i BUBBLE. Se observ ncrcarea corespunztoare a parametrilor (adresa tabloului i numrul de elemente) n registrele desemnate n acest scop pentru fiecare procedur. Exemplul prezentat ilustreaz modul de utilizare a macroinstruciunilor prezentate, ca i schema general de dezvoltare a unui program.

Capitolul3
Procesoarede32debii Coprocesoarematematice
3.1Arhitecturaprocesoarelorde32debii
3.1.1Generaliti
Apariia i dezvoltarea procesoarelor Intel de 32 de bii a constituit o adevrat revoluie n domeniul calculatoarelor personale, att prin creterea performanelor hardware (n special creterea spaiului de memorie adresabildirect),ctiprinperspectiveledeschisesistemelordeprograme. Procesoarele de 32 de bii sunt compatibile ca arhitectur cu cele de 16 bii, prin aceea c registrele de 16 bii se regsesc ca subregistre ale registrelor de 32 de bii. Aceasta a permis ca setul de instruciuni al procesoarelor de 16 bii s fie un subset al celui specific procesoarelor de 32 bii, ceea ce face ca orice program dezvoltat pentru procesoarele de 16 bii s poat fi executate i pe maini de 32 de bii. n plus, toate instruciunile care utilizau operanzi de 16 bii se extind i asupra operanzilor de 32 de bii. Aceast compatibilitate a setului de instruciuni a fost unul din scopurile declarate ale noii generaii de procesoare, pentru a conserva imensa cantitate de software dezvoltatanterior. Figura 3.1 descrie registrele procesoarelor de 32 de bii, din punctul de vedere alprogramelordeaplicaie. Exist opt registre generale de 32 de bii, care au numele registrelor generale de 16 bii, cu prefixul E (de la extended). Astfel, registrul EAX se numete acumulator extins, ESP se numete stack pointer extins etc. Primii 16 bii mai puin semnificativi ai acestor registre sunt disponibili i ca registre de 16 bii (AX,SPetc.),fiindpracticidenticecuregistrelegenerale8086. Aceeai abordare se regsete i n cazul registrelor EIP (contor program extins) i EFLAGS (registru de flaguri extins). Subsetul de bistabili din registrul FLAGSseregsetenpartealowaregistruluiEFLAGS.

103 Capitolul3
Registrele de segment au fost pstrate de 16 bii, dar sau adugat dou noi registre:FSiGS. Pe lng registrele generale din Figura 3.1, procesoarele de 32 de bii dispun de registre de control, de gestiune a adresei, de depanare i de test. Acestea difer de la un tip de procesor la altul i sunt folosite n principal de programele desistem.

Figura 3.1 Registrele procesoarelor de 32 de bii Una din modificrile majore ale arhitecturii este semnificaia registrelor de segment, care acioneaz n general ca selectoare de segment. Acestea nu mai indic n mod nemijlocit adresa de baz a segmentului de memorie, ci un descriptor de segment (ncrcat ntrun registru special de control) care precizeaz adresa de baz a segmentului, dimensiunea acestuia i drepturile de acces asociate. Abordarea respectiv permite ca adresa de baz i limita segmentului s poat fi specificate pe 32 de bii, crescnd dimensiunea maximaunuisegmentpnla4GB.

3.1.2Modurideadresarepe32debii
Modurile de adresare (formarea adresei fizice) au fost mult dezvoltate fa de celepe16bii.Seintroducurmtoarelenoiuni: deplasament o valoare imediat pe 8 sau 32 de bii, coninut n instruciune

Programarenlimbajdeasamblare 104 registru de baz orice registru general de 32 de bii (spre deosebire de adresarea pe 16 bii unde ca registre de baz se utilizeaz doar BX iBP) registru index orice registru general de 32 de bii, cu excepia lui ESP (spre deosebire de adresarea pe 16 bii unde ca registre index se utilizeazdoarSIiDI) factor de scal indexul poate fi nmulit cu un factor de scal de valoare1,2,4sau8(inexistentnadresareape16bii). Seobinastfel9moduriposibiledeadresare: adresare direct adresa efectiv a operandului face parte din instruciune,putndfipe8,16sau32debiiexemplu:
INC dword ptr [1000H]

adresare indirect prin registre adresa efectiv a operandului este coninutntrunuldinregistreledebazexemplu:


MOV [EBX], EAX

adresare bazat adresa efectiv a operandului este format din coninutul unui registru de baz la care se poate aduga un deplasamentexemplu:
ADD ECX, [EAX+32]

adresare indexat adresa efectiv a operandului este format din coninutul unui registru index la care se poate aduga un deplasament exemplu:
MUL byte ptr TABLOU [ESI]

adresare indexat cu factor de scal adresa efectiv a operandului este format din coninutul unui registru index, nmulit cu unfactordescal,lacaresepoateadugaundeplasamentexemplu:
MOV EAX, dword ptr TABLOU [EDI*4][100H]

adresare bazat i indexat adresa efectiv a operandului este format din coninutul unui registru de baz la care se adun coninutulunuiregistruindexexemplu:
MOV EAX, [ESI][EBX]

adresare bazat i indexat cu factor de scal adresa efectiv a operandului este format din coninutul unui registru de baz la care se adaug coninutul unui registru index, nmulit cu un factor de scalexemplu:
MOV ECX, [EDX*8][EAX]

105 Capitolul3
adresare bazat i indexat cu deplasament adresa efectiv a operandului este format din coninutul unui registru de baz la care se adaug coninutul unui registru index, la care se poate aduga un deplasamentexemplu:
ADD EDX, [ESI] [EBP + 10000H]

adresare bazat i indexat, cu factor de scal i deplasament adresa efectiv a operandului este format din coninutul unui registru de baz la care se adaug coninutul unui registru index, nmulit cu un factor de scal, la care se poate aduga undeplasamentexemplu:
MOV EAX, TABLOU [EDI*4] [EBP+800H]

Figura 3.2 ilustreaz modul cel mai general de adresare (bazat i indexat, cu factor de scal i deplasament), n care adresa efectiv AE se calculeaz dup relaia:
AE = Registru_Baza + Registru_Index * Factor_Scala + Deplasament

Factorul de scal este foarte util la parcurgerea tablourilor de date simple (pe 2, 4 sau 8 octei), permind ca indicele logic al tabloului s coincid cu coninutulregistruluiindex.Deexemplu,oinstruciuneCdeforma:
long int tablou [1000]; for (i = 0; i < 1000; i++) tablou[i] += 10;

seimplementeazprinsecvena:
MOV XOR bucla: ADD INC LOOP _TABLOU [EBX*4], 10 EBX bucla CX, 1000 EBX, EBX

n care registrul EBX are exact aceeai semnificaie ca i indicele i din programulC.

3.1.3ModurileRealiProtected
Pentru a pstra compatibilitatea cu programele dezvoltate pentru maini de 16 bii, procesoarele de 32 de bii dispun de dou moduri de operare: modul Real Address (pe scurt, modul Real) i modul Protected Virtual Address(pescurt,modulProtected). n modul Real, procesorul se comport ca un procesor de 16 bii foarte rapid, permindnsaccesulladateiadresede32debii.

Programarenlimbajdeasamblare 106 Modul Protected ofer mecanisme sofisticate de gestiune a memoriei (paginare, drepturi de acces la segmente etc.). n acest mod de operare, unitile de program se numesc taskuri. Se poate executa o comutare de task, pentru a intra ntrun regim special de funcionare, denumit mod Virtual 8086. Fiecare asemenea task se comport (din punct de vedere software) ca o main de tip 8086, permind programelor de 16 bii (aplicaii sau chiar un ntregsistemdeoperare)spoatfiexecutatecataskuri.

Figura 3.2 Moduri de adresare pe 32 de bii Att n modul Real, ct i n modul Protected, procesorul poate executa instruciuni de 16 bii, prin examinarea unui bit din descriptorul de segment asociat registrului CS. Acest bit precizeaz lungimea implicit a operanzilor i a adreselor(16sau32debii). n afara dimensiunii implicite, se poate fora o anumit dimensiune prin prefixele numite Operand Size (Dimensiune operand) i Address Length (Lungime adres). Aceste prefixe (de valoare 66H i 67H) sunt generate

107 Capitolul3
automat de ctre macroasambloare. S presupunem modul Real i s considermurmtoareasecvendecodsurs:
.code MOV MOV MOV MOV AX, word ptr [DI][100H] EAX, dword ptr [DI][100H] AX, word ptr [EDI][100H] EAX, dword ptr [EDI][100H]

Fiierullistinggeneratvaconineurmtoareadescriere:
0000 0004 0009 0010 8B 66| 67| 66| 85 8B 8B 67| 0100 85 0100 87 00000100 8B 87 00000100 MOV MOV MOV MOV AX, word ptr [DI][100H] EAX, dword ptr [DI][100H] AX, word ptr [EDI][100H] EAX, dword ptr [EDI][100H]

Se observ acelai cod al instruciunii MOV (8BH), acelai deplasament 100H generat pe 16 sau 32 de bii i prefixele inserate automat. Prima instruciune este cu operand i adresare de 16 bii. A doua instruciune este cu operand pe 32 de bii i adresare pe 16 bii se observ prefixul 66H i offsetul 100H generat pe 16 bii. A treia instruciune este cu operand pe 16 bii i adresare pe 32 de bii se observ prefixul 67H i offsetul 100H generat pe 32 de bii. n fine, ultima instruciune este cu operand i adresare pe 32 de biiseobservambeleprefixeioffsetul100Hgeneratpe32debii. n modul de operare Real, formarea adresei fizice este exact ca la procesoarele de 16 bii (vezi Figura 3.3). Selectorul de segment este unul din cele 4 registre de segment, iar offseturile sunt pe 16 bii, conducnd astfel la o lungime maxim a unui segment de 64KB. Pointerii ctre date sau ctre instruciuni pot fi memorai pe 4 octei (doi octei pentru adresa de segmentidoiocteipentruoffset). Asambloarele dispun de directiva DD (Define DoubleWord), care genereaz pointeripe4octei,canexemplulurmtor:
.data TABLOU ADR_16 .code LES MOV BX, ADR_16 EAX, ES:[BX] DD DD 256 dup (?) TABLOU

Instruciunea LES BX, ADDR_16 ncarc perechea de registre (ES:BX) cu un pointerpe4octei. n modul de operare Protected, registrele selectoare de segment (de 16 bii) sunt ncrcate cu adresa unui descriptor de segment, iar offseturile pot fi de 16 sau 32 de bii (vezi Figura 3.4), conducnd la o lungime maxim a unui segment de 4 GB. Pointerii pot fi pe 4 octei (doi octei pentru descriptorul de

Programarenlimbajdeasamblare 108 segment i doi octei pentru offset) sau pe 6 octei (patru octei pentru offset). Asambloarele dispun de directiva DP (Define Pointer), care genereaz pointeri pe6octei,canexemplulurmtor:

Figura 3.3 Adresarea n modul Real


.data TABLOU ADR_32 .code LFS MOV EBX, ADR_32 EAX, FS:[EBX] DD DP 256 dup (?) TABLOU

Instruciunea LFS EBX, ADDR_32 ncarc n perechea de registre (FS:EBX) cuunpointerpe6octei. Sconsidermurmtoareasecvensurs:
.data TABLOU ADR_16 ADR_32 .code LEA MOV LEA BX, TABLOU EAX, [BX] EBX, TABLOU ; ; ; ; ; Acces prin pointer near de 16 biti in cadrul segmentului selectat prin DS Acces prin pointer near DD DD DP 256 dup (?) TABLOU TABLOU

109 Capitolul3
MOV LES MOV LFS MOV EAX, [EBX] AX, ADR_16 EAX, ES:[BX] EBX, ADR_32 EAX, FS:[EBX] ; ; ; ; ; ; ; de 32 de biti in cadrul segmentului selectat prin DS Acces prin pointer far de 32 de biti n cadrul segmentului selectat prin ES

; Acces prin pointer far ; de 48 de biti in ; cadrul segmentului selectat ; prin FS

Figura 3.4 Adresarea n modul Protected Listingulgeneratlaasamblarepentrusecvenademaisuseste:


0000 .data 0000 0100*(????????) 0400 00000000sr 0404 000000000000sr 040A 0000 BB 0000r 0003 66| 8B 07 .code LEA MOV LEA MOV LES BX, TABLOU EAX, [BX] EBX, TABLOU EAX, [EBX] BX, ADR_16 TABLOU ADR_16 ADR_32 DD 256 dup (?) DD TABLOU DP TABLOU

0006 66| 8D 1E 0000r 000B 66| 67| 8B 03 000F C4 1E 0400r

Programarenlimbajdeasamblare 110
0013 66| 26: 8B 07 0017 66| 0F B4 1E 0404r 001D 66| 64: 67| 8B 03 MOV LFS MOV EAX, ES:[BX] EBX, ADR_32 EAX, FS:[EBX]

Se observ prezena a trei categorii de prefixe. Prefixele de operand pe 32 de bii (marcate cu 66|), cele de adres pe 32 de bii (marcate cu 67|) i prefixele de segment (marcate cu 26: pentru ES: i cu 64: pentru FS:). Instruciunea LEA (Load Effective Address) permite ncrcarea att a offset urilorde16bii,ctiacelorde32debii. n mod implicit, accesul la date se face prin selectorul DS (la fel ca la 8086), cu excepia modurilor de adresare care implic registrele EBP i ESP, caz n care selectorul implicit este SS. Se poate folosi orice prefix de segment, cu aceleaiexcepiicunoscutedela8086: instruciunileexecutatesuntaccesatetotdeaunaprinCS operaiile de salvare i restaurare n stiv implicate n instruciunile CALL,RET,PUSHiPOPseexecuttotdeaunaprinselectorulSS destinaia instruciunilor pentru iruri este accesat totdeauna prin selectorulES. La punerea sub tensiune, procesorul este n modul Real. Trecerea n modul Protected se face prin poziionarea unui bit din cuvntul mai puin semnificativ(numitMachine Status Word)alregistruluidecontrolCR0. Aa cum la procesoarele de 16 bii trebuia s ncrcm registrele de segment cu valori cu sens, trecerea n modul Protected presupune definirea corespunztoare a descriptorilor de segment i ncrcarea registrelor selectoare. Aceste operaii nu vor fi descrise, n ideea c programele de aplicaie dezvoltate n limbaj de asamblare vor opera n general n modul Real.

3.2Setuldeinstruciunialprocesoarelorde32de bii
3.2.1Extensiainstruciunilorde16bii
Pentru ca asamblorul s recunoasc instruciunile specifice, se utilizeaz directivele.286,.386..486,careprecizeaztipulprocesorului. O serie de restricii de la setul de baz 8086 sunt eliminate, ncepnd de la procesorul80286.Deasemenea,seadaugoseriedeinstruciuninoi. ncrcarea registrelor de segment se poate face i cu valori imediate exemplu MOVDS,DGROUP. Instruciunile de deplasare i rotaie se pot executa pe un numr oarecare debii,specificatninstruciunedeexemplu:SHLAX,4.

111 Capitolul3
Instruciunea de nmulire cu semn (IMUL) are urmtoarele forme suplimentare: IMUL reg16, im16 prin care se nmulete registrul de 16 bii reg16 cu o valoare imediat pe 16 biiim16,iarrezultatulsedepunenreg16 IMUL dreg16, sursa16 prin care se nmulete dreg16 cu sursa16 (registru sau memorie) i rezultatul sedepunendreg16(numaila80386iurmtoarele) IMUL dreg16, sursa16, im16 prin care se nmulete sursa16 (registru sau memorie) cu valoarea imediat im16irezultatulsedepunenregistruldreg16(destinaie). Instruciuniledelucrucustivaseextindcu: PUSHA (PushAll) care salveaz n stiv registrele AX, CX, DX, BX, SP, BP, SI, DI (n aceast ordine),iarregistrulSPestesczutcu16 POPA (PopAll) care reface registrele DI, SI, BP, SP, BX, DX, CX, AX (salvate cu o instruciune PUSHA anterioar) registrul SP se reface prin adunarea valorii 16,nuprinextragereaefectivdinstiv PUSH im16 carepunenstivovaloareimediat. Instruciunilepentruiruriseextindcu: INSB, INSW (InputString) cusemnificaia: (ES:(DI))byte/wordcititdelaportulspecificatdeDX actualizeazDI OUTSB, OUTSW(OutputString) cusemnificaia: portspecificatprinDX(DS:SI)) actualizeazSI Instruciuniledecontrolseextindcu: BOUND reg16, lim(Testeazlimite) n care lim este adresa unei zone de memorie de doi ntregi, care precizeaz limita minim i maxim pentru registrul reg16. Dac reg16 < DS:(lim) sau reg16>DS:(lim+2),atuncisegenereazontreruperesoftwarepenivelul5.

Programarenlimbajdeasamblare 112 ENTER dim_loc, nivel (Creeaz ablon stiv la intrarea n procedur) ncaredim_locinivelsuntntregipe16biifrsemn. Semnificaiaesteurmtoarea:
PUSH BP temp SP daca (nivel > 0) { for (i = 1 to nivel-1) { BP BP - 2 PUSH SS:[BP] } PUSH temp } BP temp SP SP - dim_loc

Primul parametru dim_loc este dimensiunea necesar n stiv pentru parametrii localiaiprocedurii.Dacniveleste0,atuncisemnificaiaesteechivalentcu:
PUSH MOV SUB BP BP, SP SP, dim_loc

care este secvena standard de intrare ntro procedur cu parametri locali n stiv(vezi6.6). Dac nivel este > 0, se copiaz n stiv coninutul zonei de stiv (parametri locali) a procedurii apelante. Dac procedura curent este apelat dintro alt procedur, care are registrul BP poziionat printro instruciune ENTER, atunci ablonul stivei curente va conine primii nivel1 parametri locali ai proceduriiapelante. LEAVE(Pregtirepentruieiredinprocedur) Instruciunea LEAVE reface registrele SP i BP, anulnd efectul instruciunii LEAVE.Esteechivalentcusecvena:
MOV SP, BP POP BP

Instruciunea ENTER se scrie ca prim instruciune din procedur, iar LEAVEimediatnaintedeRET.

3.2.2Instruciunispecificeprocesoarelorde32debii
ntregul set de instruciuni de transfer, aritmetice i logice se extinde cu operanzidetipDoubleWord(registre,memoriesauvaloriimediate). Instruciunispecificedetransfer PUSHAD/POPAD (Push/PopAllDouble)

113 Capitolul3
Salveaz/restaureaz registrele EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI n stiv. PUSHFD/POPFD (PushFlagsDouble) Salveaz/restaureazregistrulEFLAGSnstiv. CMPXCHG reg/mem, reg (CompareandExchange) Compar i apoi interschimb cei doi operanzi, poziionnd flagurile aritmetice. BSWAP reg32 (Byte Swap) Inverseazordineaocteilorntrunregistrude32debii. XADD reg/mem, reg (Exchange and Add) Esteechivalentcusecvena:
XCHG ADD reg/mem, reg reg/mem, reg

Instruciunispecificedeconversie MOVZX/MOVSXdestinaie,surs (Move with Zero/Sign Extension) Copiaz operandul surs (de 8 sau 16 bii) n operandul destinaie (de lungime dubl), completnd cu 0 (MOVZX) sau cu bitul de semn al operandului surs (MOVSX). Destinaia poate fi registru sau memorie de 16/32 de bii, iarsursapoatefiregistru,memoriesauvaloareimediatde8/16bii. CWDE (ConverWordtoDoubleWordExtended) Convertete AX la un dublu cuvnt n EAX, cu extensie de semn. Este asemntoare cu CWD (Convert Word to Double), care are ca destinaie perechea(DX:AX). CDQ (ConvertDoubleWordtoQuadWord) Convertete registrul EAX la un cuvnt cvadruplu n perechea (EDX:EAX), cu extensiedesemn. Instruciunispecificeadreselor LFS/LGS/LSS registru,memorie ncarc o pereche de registre cu un pointer din memorie, pe 4 sau 6 octei. Registrulspecificatpoatefide16saude32debii. Instruciuniaritmetice Operaiile de nmulire i de mprire se pot executa pe 32 de bii. Se utilizeaz registrele EAX i EDX, cu semnificaie asemntoare ca la operaiilede16bii.Deexemplu,instruciunea:
DIV EBX

Programarenlimbajdeasamblare 114 mparte(EDX:EAX)laEBX,cuctulnEAXirestulnEDX. Instruciunidedeplasare SHLD/SHRDreg/mem,reg,CL/im8(ShiftLeft/RightDouble) Se deplaseaz reg/mem la stnga/dreapta cu numrul de bii specificat n CL sau n operandul imediat im8 (pe 8 bii). Al doilea operand este folosit pentru a completa biii deplasai ai primului operand. Primii doi operanzi trebuie s fie deaceeaidimensiune(WordsauDoubleWord). Instruciunipentruiruri Setul de instruciuni pentru iruri se extinde cu operaii specifice irurilor de ntregi pe 4 octei. Exist astfel instruciunile MOVSD (Move String Double), STOSD (Store String Double), LODSD (Load String Double), SCASD (Scan String Double). Se utilizeaz registrul acumulator extins EAX, iar adresele surs idestinaie(SIiDI)suntincrementate/decrementatecu4. Instruciunilaniveldebit BSF/BSR reg, reg/mem (BitScanForward/Reverse) Instruciunea parcurge operandul surs reg/mem (16 sau 32 de bii), pn la primul bit egal cu 1. BSF parcurge de la dreapta la stnga, iar BSR invers. Indicelebitului1identificatesteplasatnprimuloperand(registru). BT reg/mem, im8/reg (BitTest) Plaseazbitulcunumruldatdeim8sauderegaloperanduluireg/memnCF. BTC reg/mem, im8/reg (BitTestandComplement) Plaseaz bitul cu numrul dat de im8 sau de reg al operandului reg/mem n CF, apoicomplementeazbitulrespectiv. BTR reg/mem, im8/reg (BitTestandReset) Plaseaz bitul cu numrul dat de im8 sau de reg al operandului reg/mem n CF, apoiforeazbitulrespectivlavaloarea0. BTS reg/mem, im8/reg (BitTestandSet) Plaseaz bitul cu numrul dat de im8 sau de reg al operandului reg/mem n CF, apoiforeazbitulrespectivlavaloarea1. Instruciunidecontrol JECXZ etichet (JumpifECXisZero) EsteextensiainstruciuniiJCXZpentruregistrulECX. SETccc reg/mem (SetBytesConditionally) Seteaz un octet conform unei condiii logice. Octetul poate fi un registru de 8 bii sau o locaie de memorie. Condiiile logice i semnificaiile lor sunt aceleai ca la instruciunile de salt condiionat. n mnemonicele

115 Capitolul3
instruciunilor se substituie ccc cu condiia care este codificat sub forma Jccc la instruciunile de salt condiionat. Exist deci instruciuni SETG, SETGE,SETNB,SETPO,SETNLEetc.Deexemplu:
SETLE SETNBE SETNC AL byte ptr [SI] byte ptr [EBX]

3.3Coprocesoarematematice
3.3.1Arhitecturacoprocesoarelormatematice
Coprocesoarele matematice sunt circuite integrate dedicate (procesoare specializate), care extind setul de instruciuni al procesoarelor centrale cu instruciunispecificeoperaiilorcunumererealenvirgulmobil. Coprocesoarele sunt fie circuite de sine stttoare (8087, 80287, 80387), fie sunt integrate n procesorul de baz (80486). n cel deal doilea caz, nu se mai face distincie ntre setul de instruciuni al procesorului de baz i cel specific formatuluinvirgulmobil. Tipurilededaterecunoscutedecoprocesoaresunt: numrrealnsimplprecizie(dword) numrrealndublprecizie(qword) numrrealnprecizieextins(tbytes) ntregpe2octei(word) ntregpe4octei(dword) ntregpe8bii(qword) ntregBCDpe10cifre(tbytes). Aceste tipuri de date vor fi notate cu real32, real64, real80, int16, int32 i bcd80. ntregii pe 8 octei pot fi numai ncrcai n coprocesor. Intern, coprocesoarele lucreaz exclusiv cu formatul real n precizie extins (10 octei), descris n Capitolul 1. La ncrcarea operanzilor din memorie, toate tipurile de date de mai sus sunt convertite la tipul intern similar, la depunerea operanzilor n memorie, au loc conversii de la formatul intern la unul din formateledemaisus.

Programarenlimbajdeasamblare 116 Arhitectura coprocesoarelor cuprinde 8 registre de cte 80 de bii, numite ST(0), ST(1), ..., ST(7). Aceste registre sunt organizate ca o stiv, registrul ST(0) (care se mai noteaz simplu cu ST) fiind vrful stivei (vezi Figura 3.5). Coprocesoarele dispun de o serie de registre suplimentare, dintre care cele mai importante sunt registrul de stare (Status Word) i registrul de control (Control Word). Registrul de stare conine flaguri care se poziioneaz n urma instruciunilor de comparaie sau n caz de eroare. Registrul de control conine cmpuri care controleaz modul de execuie al anumitor aciuni (de exemplu,cumsefacerotunjirealavalorintregi). Comunicaia dintre procesorul de baz i coprocesor se face exclusiv prin intermediul memoriei. Coprocesorul dispune de instruciuni de transfer ntre memorie i cele 8 registre de lucru, precum i pentru cuvintele de control i de stare.

Figura 3.5 Arhitectura coprocesoarelor 80x87 Ne vom referi n continuare la coprocesorul 8087, deoarece setul de instruciuni este practic acelai la toate coprocesoarele. La procesoarele mai vechi dect 80486, se pune i problema comunicaiei dintre procesorul de bazicoprocesor. Instruciunile specifice 8087 se scriu n textul surs la fel ca instruciunile procesorului de baz. Asamblorul recunoate mnemonicele acestor instruciuni i genereaz cod main corespunztor. Acest cod va fi executat

117 Capitolul3
de ctre coprocesor, n urma generrii unui semnal de ctre procesorul de baz 8086. Coprocesorul 8087 monitorizeaz permanent fluxul de instruciuni i sesizeaz prezena unei instruciuni specifice 8087 n memorie. n acest caz, el semnaleaz intenia de a intra n execuie prin semnalul electric TEST. Execuia ncepe numai dup ce 8086 intr n ateptare, ca urmare a unei instruciuni WAIT. Coprocesorul recunoate starea de ateptare i ncepe execuia instruciunii matematice, anulnd n acelai timp cererea efectuat prin semnalul TEST. Ca urmare, 8086 iese din starea de ateptare i i continu execuia. Asambloarele insereaz automat o instruciune WAIT naintea fiecrei instruciuni 8087, deci nu este necesar codificarea lor explicit. La coprocesoarele de generaie mai nou (80387), sincronizarea cu procesorul de baz se face prin semnale specializate, ceea ce elimin necesitateainstruciunilorWAIT. n mod corespunztor, exist instruciunea 8087 FWAIT, destinat sincronizrii reciproce (8087 ateapt dup 8086). Instruciunea FWAIT este necesarnumaidupoperaiilededepunerenmemorieexecutatede8087. naintea nceperii operrii propriuzise, este necesar o instruciune FINIT, caretergeregistreleinterne,condiiiledeeroareetc.

3.3.2Setuldeinstruciuni8087
Mnemonicele instruciunilor 8087 ncep toate cu litera F. Majoritatea instruciunilor au ca operanzi vrful ST al stivei coprocesorului i un alt registru ST(i) sau un operand n memorie. Cele mai multe instruciuni matematice actualizeaz stiva, prin operaiile descrise mai jos (ST i ST(0) reprezintacelairegistru):
PUSH_ST: for (i = 7 downto 1) ST(i) ST(i-1) POP_ST: for (i = 1 to 7) ST(i-1) ST(i)

Instruciunipentruncrcareadatelor
FLD ST(i) tempST(i) PUSH_ST STtemp FLD mem(real32/64/80) PUSH_ST (ncarcnumrrealdinmemorienST) (ncarcST(i)nST,cudeplasareastivei)

Programarenlimbajdeasamblare 118
STmem FILD mem(int16/32/64) PUSH_ST STmem FBLD mem(bcd80) PUSH_ST STmem FLDZ PUSH_ST ST0.0 FLD1 PUSH_ST ST1.0 FLDPI PUSH_ST ST FLDL2E PUSH_ST STlog2(e) FLDL2T PUSH_ST STlog2(10) FLDLG2 PUSH_ST STlog10(2) (ncarcconstantalog10(2)nST) (ncarcconstantalog2(10)nST) (ncarcconstantalog2(e)nST) (ncarcconstantanST) (ncarcconstanta1.0nST) (ncarcconstanta0.0nST) (ncarcnumrBCDdinmemorienST) (ncarcnumrntregdinmemorienST)

Instruciunipentrudepunereadatelor
FST FSTP ST(i) ST(i)ST ST(i) ST(i)ST POP_ST FST FSTP mem(real32/64/80) memST mem(real32/64/80) (DepuneSTrealnmemoriecudescrcare) (DepuneSTrealnmemoriefrdescrcare) (DepuneSTnST(i)cudescrcareastivei) (DepuneSTnST(i)frdescrcareastivei)

119 Capitolul3
memST POP_ST FIST mem(int16/32) memST FISTP mem(int16/32) memST POP_ST FBSTP mem(bcd80) memST POP_ST FXCH FXCH ST(i) (SchimbSTcuST(1)) (SchimbSTcuST(i)) (AdunSTcuST(1),cudescrcare) ST(1)ST(1)+ST POP_ST FADD ST(i),ST ST(i)ST(i)+ST FADD ST,ST(i) STST+ST(i) FADD mem(real32/64/80) STST+mem FIADD mem(int16/32) STST+mem FADDP ST(i) ST(i)ST(i)+ST POP_ST (AdunSTlaST(i)cudescrcareastivei) (AdunntregdinmemorielaST) (AdunrealdinmemorielaST) (AdunST(i)laST) (AdunSTlaST(i)) (DepuneSTBCDnmemoriecudescrcare) (DepuneSTntregnmemoriecudescrcare) (DepuneSTntregnmemoriefrdescrcare)

Instruciunideadunare
FADD

Instruciunidescdere
FSUB ST(1)ST(1)ST POP_ST FSUB ST(i),ST ST(i)ST(i)ST FSUB ST,ST(i) STSTST(i) (ScadeST(i)dinST) (ScadeSTdinST(i)) (CalculeazST(1)STcudescrcare)

Programarenlimbajdeasamblare 120
FSUB mem(real32/64/80) STSTmem FISUB mem(int16/32) STSTmem FSUBP ST(i) ST(i)ST(i)ST POP_ST FSUBR tempSTST(1) POP_ST STtemp FSUBRST(i),ST ST(i)STST(i) FSUBRST,ST(i) STST(i)ST FSUBRmem(real32/64/80) (ScadeSTdinrealnmemorie,rezultatnST) STmemST FISUBRmem(int16/32) ST) STmemST FSUBPRST(i) ST(i)STST(i) POP_ST (ScadeST(i)dinSTcudescrcare) (Scade ST din ntreg n memorie, rezultat n (ScadeSTdinST(i),rezultatnST) (ScadeST(i)dinST,rezultatnST(i)) (CalculeazSTST(1)cudescrcare) (ScadeSTdinST(i)cudescrcare) (ScadentregnmemoriedinST) (ScaderealnmemoriedinST)

Instruciunidenmulire
FMUL ST(1)ST(1)*ST POP_ST FMUL ST(i),ST ST(i)ST(i)*ST FMUL ST,ST(i) STST*ST(i) FMUL mem(real32/64/80) STST*mem FIMUL mem(int16/32) STST*mem (nmuletentregdinmemoriecuST) (nmuleterealdinmemoriecuST) (nmuleteST(i)cuST,rezultatnST(i)) (nmuleteSTcuST(i),rezultatnST(i)) (nmuleteSTcuST(1),cudescrcare)

121 Capitolul3
FMULP ST(i) ST(i)ST(i)*ST POP_ST (nmuleteSTcuST(i),cudescrcare)

Instruciunidemprire
FDIV ST(1)ST(1)/ST POP_ST FDIV FDIV FDIV FIDIV ST(i),ST ST(i)ST(i)/ST ST,ST(i) STST/ST(i) mem(real32/64/80) STST/mem mem(int16/32) STST/mem FDIVP ST(i) ST(i)ST(i)/ST POP_ST FDIVR tempST/ST(1) POP_ST STtemp FDIVRST(i),ST ST(i)ST/ST(i) FDIVRST,ST(i) STST(i)/ST FDIVR mem(real32/64/80) STmem/ST FIDIVRmem(int16/32) ST) STmem/ST FDIVPRST(i) ST(i)ST/ST(i) POP_ST (mparteSTlaST(i),cudescrcare) (mparte ntreg n memorie la ST, rezultat n (mparterealnmemorielaST,rezultatnST) (mparteST(i)laST,rezultatnST) (mparteSTlaST(i),rezultatnST(i)) (CalculeazST/ST(1),cudescrcare) (mparteST(i)laST,cudescrcare) (mparteSTlantregdinmemorie) (mparteSTlarealdinmemorie) (mparteSTlaST(i),rezultatnST(i)) (mparteST(i)laST,rezultatnST) (CalculeazST(1)/STcudescrcare)

Instruciunidecomparaie

Programarenlimbajdeasamblare 122 Instruciunile de comparaie poziioneaz indicatorii din cuvntul de stare prin efectuarea unei operaii temporare de scdere ntre operanzii care se compar.
FCOM FCOM ST(i) FICOM mem(int16/32) FTST FCOMP tempSTST(1) POP_ST FCOMPST(i) FICOMPmem(int16/32) FCOMPP tempSTST(1) POP_ST POP_ST (ComparSTcuST(i),cudescrcare) (ComparSTcuntreg,cudescrcare) (ComparSTcuST(1),cudescrcaredubl) FCOMPmem(real32/64/80) (ComparSTcureal,cudescrcare) (ComparSTcuST(1)) (ComparSTcuST(i) (ComparSTcuntregdinmemorie) (ComparSTcu0.0) (ComparSTcuST(1),cudescrcare)

FCOM mem(real32/64/80) (ComparSTcurealdinmemorie)

Instruciunidiverse
FABS ST|ST| FCHS STST FSQRT STsqrt(ST) (Radical) (Schimbsemnul) (Iavaloareaabsolut)

Instruciunidecontrol
FINIT FWAIT FSTSW mem(int16) FSTCWmem(int16) FLDCWmem(int16) FNOP (Iniializeazcoprocesor) (Sincronizeazcuprocesoruldebaz) (Depunecuvntdestarenmemorie) (Depunecuvntdecontrolnmemorie) (ncarccuvntdecontroldinmemorie) (Niciooperaie)

Pe lng instruciunile de mai sus, coprocesoarele dispun de instruciuni transcendente, pentru calculul funciilor trigonometrice directe i inverse, exponenial, logaritm etc. Aceste instruciuni nu vor fi prezentate, deoarece

123 Capitolul3
este puin probabil c se vor dezvolta programe cu funcii transcendente n limbajdeasamblare. n Capitolul 6, vor fi prezentate tehnici de programare specifice coprocesoarelor matematice.

Capitolul4
Structurareaprogramelor Definireaiiniializareadatelor Operatori
Capitolul curent i cel urmtor sunt dedicate limbajului de asamblare. Pe lng instruciunile propriuzise, un program ASM poate cuprinde directive, prin intermediul crora se definesc date, etichete i proceduri, se structureaz segmente, se definesc i se utilizeaz macroinstruciuni, se controleaz n general procesul de asamblare etc. Directivele nu reprezint instruciuni, ci comenzi ctre asamblor, efectul lor manifestnduse exclusiv n faza de asamblare.

4.1Segmentare.Directivepentrudefinireasegmentelor
Unmoduldeprogramnlimbajuldeasamblarepoateconducela: oporiunedintrunsegment unsegment poriunidesegmentediferite maimultesegmente. Maimultemoduleobiectseleagprinoperaiadelinkeditare.

4.1.1DirectiveleSEGMENTiENDS
Indiferent de modul de dezvoltare al unui program ASM, att instruciunile, ct i datele trebuie s se gseasc n interiorul unui segment. Directiva SEGMENTcontroleaz: numelesegmentului alinierea combinareacualtesegmente continuitatea(adiacena)segmentelor. FormageneraladirectiveiSEGMENTeste:
nume SEGMENT [tip_aliniere] [tip_combinare] ['nume_clasa']

124 Capitolul4
. . nume ENDS

Parametrii inclui n paranteze drepte sunt opionali. Dac sunt prezeni, acetiatrebuiesfienordineaspecificat.Semnificaiaparametriloreste: tip_aliniere specific la ce limit va fi relocat segmentul n memorie poateaveaunadinformele: PARA (implicit) aliniere la paragraf (segmentul fizic, adic adresa pe 20 de bii, va fi relocat la prima adres absolut divizibil prin 16) BYTEfraliniere(segmentulsevarelocalaurmtoruloctetliber) WORD aliniere la cuvnt (segmentul se va reloca la urmtorul octet liberaflatlaadrespar) DWORD aliniere la dublucuvnt (segmentul se va reloca la prima adresdivizibilcu4) PAGE aliniere la pagin (segmentul se va reloca la prima adres absolutdivizibilprin256). Sconsidermurmtoareledefiniiidesegmente:
DAT1 SEGMENT BYTE x1 db 7 dup (?) DAT1 ENDS DAT2 SEGMENT WORD x21 dw 300 dup (?) x22 dw ? DAT2 ENDS DAT3 SEGMENT PARA x3 db 5 dup (?) DAT3 ENDS

Dac prima adres disponibil este 1000H, cele trei segmente vor fi relocate la urmtoareleadresefizice: DAT1 1000:01000:6 DAT2 1000:81000:261 DAT3 1027:01027:4 Adresele de segment se obin prin trunchierea la primele patru cifre ale adresei fizice de nceput, iar offseturile se calculeaz corespunztor. Offset urile la execuie difer n general de offseturile la asamblare. Offsetul la asamblarepentrux21este0,darlaexecuieeste8. Operatorul OFFSET, care furnizeaz deplasamentul unei variabile sau unei etichete n cadrul unui segment, va produce offsetul de la execuie. Instruciunea:
mov bx, OFFSET x21

Programarenlimbajdeasamblare 125 vancrcanBXvaloarea8. Dac dorim ca offsetul la asamblare s coincid cu offsetul la execuie, putem folosi tipul de aliniere PARA (ultima cifr a adresei fizice de nceput a segmentuluieste0). tip_combinare specific dac i cum se va combina segmentul respectivcualtesegmente,laoperaiadelinkeditarepoatefi: necombinabil(implicit)nusescrienimic PUBLIC segmentul curent va fi concatenat cu alte segmente cu acelai nume i cu atributul PUBLIC. Aceste segmente pot fi n alte module de program. Se va forma, deci, un singur segment final cu numele respectiv, cu o unic adres de nceput lungimea unui segment cu atributul PUBLIC este suma lungimilor segmentelorcuacelainume. COMMON specific faptul c segmentul curent i toate segmentele cu acelai nume i tipul COMMON se vor suprapune n memorie (ncep la aceeai adres fizic) lungimea unui segment COMMON esteceamaimarelungimeasegmentelorcomponente STACK marcheaz segmentul curent ca reprezentnd stiva programului dac sunt mai multe segmente cu tipul STACK, ele vor fi tratate ca la PUBLIC urmtorul exemplu este o definire i o iniializareexplicitaunuisegmentdestiv:
stiva SEGMENT STACK db 256 dup(?) stiva_sp label WORD stiva ENDS cod SEGMENT mov ax, stiva mov ss, ax mov sp, OFFSET stiva_sp cod ENDS

AT EXPRESIE specific faptul c segmentul va fi plasat la o adres fizic absolut de memorie urmtorul exemplu ilustreaz definirea explicitatabeleidevectoridentreruperi:
INT_TABLE SEGMENT AT 0 dd PROC_NIV_0 dd PROC_NIV_1 . . INT_TABLE ENDS

Aceste forme se folosesc cnd programul este dezvoltat pentru echipamente dedicate. n cazul unui calculator de tip IBMPC, exist funciiDOSpentruaccesullatabeladentreruperi.

126 Capitolul4
'nume_clas' specific un nume de clas pentru segment, extinznd astfel numele segmentului de exemplu, dac segmentul are i atributul 'nume_clas', atunci atributele COMMON sau PUBLIC vor aciona numai asupra segmentelor cu acelai nume i acelai nume de clas ca numedeclase,sefolosescdeobicei'code','data'i'stack'. S considerm dou module ASM, asamblate distinct. n primul modul, avem urmtoareledefiniiidesegmente:
dseg1 SEGMENT PARA PUBLIC 'data' db 100 dup (?) dseg1 ENDS dseg2 SEGMENT PARA COMMON db 50 dup (?) dseg2 ENDS cseg SEGMENT PARA PUBLIC 'code' db 20 dup (?) cseg ENDS

naldoileamodul,existurmtoareledefiniii:
dseg1 SEGMENT PARA PUBLIC 'data' db 30 dup (?) dseg1 ENDS dseg2 SEGMENT PARA COMMON db 200 dup (?) dseg2 ENDS cseg SEGMENT PARA PUBLIC 'code' db 70 dup (?) cseg ENDS

Imaginea segmentelor rezultate n urma linkeditrii i a relocrii este cea din Figura4.1.

4.1.2DirectivaASSUME
Directiva ASSUME realizeaz o conexiune simbolic (logic) ntre definirea instruciunilor i a datelor n segmente logice (cuprinse ntre SEGMENT i ENDS) la momentul asamblrii i accesul, la execuie, la instruciuni i date prinregistreledesegment.Areformageneral:
ASSUME reg_seg:expresie, ...

ncarereg_segesteunregistrudesegment,iarexpresiepoatefi unnumedesegment unnumedegrupdesegmente SEGnumesegment NOTHING.

Programarenlimbajdeasamblare 127

Figura 4.1 Combinarea segmentelor este controlat de directiva SEGMENT n aceeai directiv ASSUME se pot asocia mai multe registre de segment, de exemplu:
ASSUME CS:CSEG, DS:DSEG1, ES:DSEG2, SS:SSEG

Directiva ASSUME nu ne scutete de ncrcarea registrelor de segment cu adresele de segment. Dac un nume de segment nu apare ntro directiv ASSUME, datele definite n acel segment pot fi accesate numai prin prefixe de segment.Sconsidermurmtorulexemplu:
dseg dseg cseg SEGMENT BETA dw 5 ENDS SEGMENT ASSUME cs:cseg, es:dseg mov ax, dseg mov es, ax mov bx, BETA ; se va genera o instructiune MOV, ; cu adresare prin registrul ES ; conform asocierii ES:dseg ENDS

cseg

Dac nu sar fi asociat registrul ES cu segmentul dseg prin directiva ASSUME, accesullavariabilaBETAtrebuiascrisnforma:

128 Capitolul4
mov bx, es:BETA

n formatul intern al instruciunii (n codificare), trebuie s apar prin ce registru de segment se calculeaz adresa fizic. Dac simbolul care apare ntr o instruciune (de exemplu, BETA), face parte dintrun segment care este asociat, printro directiv ASSUME, cu un registru de segment, atunci se va codifica intern accesul prin acel registru de segment (n cazul de fa, prin ES).Codificarearegistruluidesegmentseface: implicit datele sunt accesate n toate modurile de adresare prin registrul DS, cu excepia celor care implic registrul BP, caz n care se folosete SS, iar instruciunile sunt adresate totdeauna prinCS explicit prinutilizareaprefixelordesegment.

4.1.3DirectivaGROUP
Directiva GROUP servete la gruparea mai multor segmente (inclusiv cu nume i atribute diferite), a cror lungime total nu depete 64 KO, sub acelai nume.Areformageneral:
nume_grup GROUP nume_seg1, nume_seg2, ...

Aceast directiv reprezint o alt modalitate de combinare a mai multor segmente,pelngceaoferitdeatributulPUBLIC. Numele de grup se poate folosi n directive ASSUME, la iniializarea unor registre de segment sau la calculul unui offset. S considerm urmtorul exemplu:
d1 d1 d2 d2 data SEGMENT y ENDS SEGMENT x ENDS GROUP dw db d1, d2 20 2

Putemscrieinstruciunideforma:
mov mov mov mov ax, ds, ax, ax, data ax OFFSET x OFFSET data:x

saudirectivedeforma:
ASSUME ds:data

Programarenlimbajdeasamblare 129 Expresia OFFSET x furnizeaz offsetul variabilei x n cadrul segmentului d1, iar expresia OFFSET data:x produce offsetul variabilei x n cadrul grupului de segmentedata.

4.2Definireasimplificatasegmentelor
Aceast modalitate de definire este introdus n variantele recente ale asambloarelor. Avantajul major este faptul c se respect acelai format (structur a programului obiect) ca i la programele dezvoltate n limbaj de nivel nalt. Concret, dac utilizm definirea simplificat, se vor genera segmente cu nume i atribute identice cu cele generate de compilatoarele de limbaje de nivel nalt.Toatedirectivelesimplificatencepcuunpunct.

4.2.1Modeledememorie
Directivapentruspecificareamodeluluidememorieareformageneral: .model tip n care tip poate fi tiny, small, medium, large sau huge. Semnificaia acestortipurieste: tiny toate segmentele (date, cod, stiv) se pot genera ntrun spaiu de 64KO i formeaz un singur grup de segmente. Se folosete la programele de tip COM. Toate salturile, apelurile i definiiile de procedurisuntimplicitdetipNEAR small datele i stiva sunt grupate ntrun singur segment, iar codul n alt segment. Fiecare din acestea nu trebuie s depeasc 64KO. Toate salturile,apelurileidefiniiiledeprocedurisuntimplicitdetipNEAR medium datele i stiva sunt grupate ntrun singur segment (cel mult egal cu 64KO), dar codul poate fi n mai multe segmente separate (nu se grupeaz), deci poate depi 64KO. Salturile i apelurile sunt implicit tip FAR,iardefiniiiledeprocedurisuntimplicitdetipfar. compact codul generat ocup cel mult 64KO (se grupeaz), dar datele i stiva sunt n segmente separate (pot depi 64KO). Apelurile i salturile sunt implicit de tip NEAR. Se utilizeaz adrese complete (segment i offset) atunci cnd se acceseaz date definite n alte segmente. large attdatele,cticodulgeneratpotdepi64KO. huge este asemntor modelului large, dar structurile de date pot depi 64KO se utilizeaz adrese complete normalizate n care offsetul este redus la minim (n domeniul 015), ceea ce face ca o adres fizic s fie descrisdeounicpereche(segment,offset).

130 Capitolul4
La modelele compact i large, o structur compact de date (de tip tablou) nu poate depi limitele unui segment fizic (64KO) la modelul huge, aceast restriciedispare. Folosirea directivelor simplificate prezint i avantajul c nu mai sunt necesare directive ASSUME: asocierile ntre segmentele generate i registrele de segmentsuntimplicite. Seutilizeazurmtoareaterminologie: modelededatemici:small,compact modeledecodmic:small,medium modelededatemari:medium,large,huge modeledecodmare:compact,large,huge.

4.2.2Directivesimplificatededefinireasegmentelor
Formelegeneralealeacestordirectivesunt: .stackdimensiune .code[nume] .data .data? dateneiniializatenl.n.i .fardata[nume] segmentededateutilizateprin .fardata?[nume] adresecompletenl.n.i .const definiredeconstantenl.n.i) Dac parametrul nume lipsete, se atribuie nume implicite segmentelor generate,dupcumurmeaz: pentru.code TEXT (la modele de cod mic) sau nume_fiier_surs_TEXT(lamodeledecodmare) pentru.data? _BSS pentru.data DATA pentru.const CONST pentru.stack STACK pentru.fardata _FAR_DATA pentru.fardata? _FAR_BSS SegenereazgrupuldesegmenteDGROUP.Acestacuprinde: toatesegmentele,lamodeluldedatetiny DATA,_BSS,CONST,STACK,nrest. Se consider c exist o directiv ASSUME implicit (care nu mai trebuie, deci, scrisntextulsurs),deforma: lamodelelesmallicompact:
ASSUME cs:TEXT, ds:DGROUP, ss:DGROUP

lamodelelelargeihuge:

Programarenlimbajdeasamblare 131
ASSUME cs:nume_TEXT, ds:DGROUP, ss:DGROUP ; nume este numele din directiva .code ; sau numele fisierului sursa

lamodeluldememorietiny:
ASSUME cs:DGROUP, ds:DGROUP, cs:DGROUP

Dac se folosesc directivele .fardata i/sau .fardata?, atunci segmentele respectivetrebuiegestionateexplicitprindirectiveASSUME. Adresele de nceput ale segmentelor i ale grupurilor de segmente definite cu directivelesimplificatesuntdisponibileprinsimbolurileglobale: @data,@data?,@fardata,@fardata?,dgroup. Dac n acelai text surs (model de cod mare) se folosesc mai multe directive .code cu nume diferite, atunci, pn la ntlnirea unei alte directive de segment, este ca i cum sar fi scris o directiv ASSUME CS: cu numele respectiv. Segmentele generate au numele de clas 'STACK', 'CODE', 'DATA', 'BSS', 'FAR_BSS','FAR_DATA'.SegmentulCONSTarenumeledeclasDATA. Tipuriledecombinaresunt: PUBLIC(la.code,.data,.data?i.const) STACK(la.stack) frcombinare(la.fardatai.fardata?). Tipul de aliniere este PARA (pentru .stack, .fardata i .fardata?) i WORD (pentrucelelalte). Sconsidermfiierulsursexemplu.asm,cuconinutuldemaijos:
.model .data .const .stack .data? .fardata .fardata? .code end large 256

Fiierullistinggeneratcuprinde(ntrealtele),urmtoareleinformaii:
SymbolName ??DATE ??FILENAME ??TIME ??VERSION @CODE @CODESIZE @CPU Type Text Text Text Number Text Text Text Value "06/02/96" "exemplu" "15:21:50" 0200 EXEMPLU_TEXT 1 0101H

132 Capitolul4
@CURSEG @DATA @DATASIZE @FARDATA @FARDATA? @FILENAME @MODEL @WORDSIZE Text Text Text Text Text Text Text Text EXEMPLU_TEXT DGROUP 1 FAR_DATA FAR_BSS EXEMPLU 5 2 Bit 16 16 16 16 16 16 16 Size 0000 0100 0000 0000 0000 0000 0000 Align Combine Class Word Para Word Word Word Para Para Public Stack Public Public Public none none DATA STACK BSS DATA CODE FAR_BSS FAR_DATA

Groups & Segments DGROUP Group CONST STACK _BSS _DATA EXEMPLU_TEXT FAR_BSS FAR_DATA

Listingul relev o serie de simboluri predefinite i valorile asociate. Se remarc adresele de nceput ale segmentelor, cel mai important fiind simbolul @DATA, care are aceeai valoare cu adresa grupului DGROUP. Partea a doua a listinguluidescriesegmenteleigrupuriledesegmente. Iniializarea registrelor DS i ES la nceputul unui program principal se poate face cu simbolul @DATA sau cu simbolul DGROUP. Macroinstruciunea init_ds_esrealizeazoperaia:
mov mov mov ax, dgroup ds, ax es, ax

4.3Directivepentrulegareamodulelor
Cnd programul dezvoltat se compune din mai multe module asamblate separat, este necesar specificarea simbolurilor care sunt definite ntrun modul i utilizate n alte module. Aceste simboluri sunt nume de variabile, etichete sau nume de proceduri. n mod normal, un simbol este vizibil doar n modulul n care este definit (simbol local). Simbolurile care sunt vizibile n mai multe moduledeprogramsenumescsimboluriglobale. Sefolosescurmtoarelenoiuni: simboluri publice sunt simboluri care sunt definite ntrun modul curent de program i folosite (eventual) i n alte module aceste simboluri se declarcasimboluripublicenmodululncaresuntdefinite simboluri externe sunt simboluri care sunt folosite ntrunul din modulele n care nu sunt definite aceste simboluri se declar ca simboluri externe nmodulelencaresuntfolosite.

Programarenlimbajdeasamblare 133 Se observ c un simbol global trebuie declarat ca simbol public n modulul n care este definit i ca simbol extern n modulele n care este folosit, altele dect celncareestedefinit. Declaraia unui simbol ca simbol public, respectiv extern se face cu directivele PUBLIC,respectivEXTRN. Directiva PUBLICareformageneral:
PUBLIC nume, nume, ...

Simbolurile declarate ca publice pot fi variabile, etichete, nume de proceduri sau constantenumericesimbolice. Directiva EXTRNareformageneral:
EXTRN nume:tip, nume:tip, ...

ncaretipprecizeaztipulsimbolului.Acestapoatefi: BYTE, WORD, DWORD sau QWORD, n cazul n care simbolul este o variabil NEAR sau FAR, n cazul n care simbolul este o etichet sau un nume de procedur ABS,ncazulncaresimbolulesteoconstantnumericsimbolic. Sconsidermdoumoduledeprogram,M1.ASMiM2.ASM:
; Modul M1.ASM ; .model large extrn public .data var2 .code start: mov mov add call end start ; Modul M2.ASM ; .model large public extrn .data var 1 .code output proc

var1:word, output:far var2 dw 7 ax, dgroup ds, ax var1, 3 output

var1, output var2:word dw5 far add var2, 1 retf

134 Capitolul4
output endp end

n acest exemplu, accesul la simbolurile globale este facilitat de faptul c att var1, ct i var2 sunt n acelai segment de date, fiind accesibile prin registrul DS,iniializatcugrupuldesegmenteDGROUP. Dac nu am fi folosit directive simplificate, accesul la var1 i var2 ar fi fost mai complicat, deoarece nu sar fi cunoscut segmentul n care acestea sunt definite. n asemenea situaii, se folosete operatorul SEG, care produce adresa de segmentasimbolului:
mov ax, SEG var1 mov es, ax add es:var1, 3

Directiva END Aceast directiv marcheaz sfritul logic al unui modul de program i e obligatorie n toate modulele. Tot ce se gsete n fiierul surs dup aceast directivesteignoratlaasamblare.Formageneraleste:
END [punct_de_start]

n care punct_de_start este o etichet sau un nume de procedur care marcheaz punctul n care se va da controlul dup ncrcarea programului n memorie. ntro aplicaie compus din mai multe module i care se constituie ntrun program executabil, un singur modul trebuie s aib parametru n directivaEND.

4.4ContoaredelocaiiidirectivaORG
Contoarele de locaii controleaz procesul de asamblare, artnd la ce offset n cadrul segmentului curent se vor asambla instruciunea sau datele urmtoare.Uncontordelocaiipoatefiaccesatexplicitprinsimbolul$. La prima utilizare a unui nume de segment, contorul de locaii este iniializat cu zero. Dac se revine ntrun segment care a mai fost utilizat, contorul de locaii revine la ultima valoare utilizat n cadrul acelui segment, ca n exemplulurmtor:
.data db 5 dup(?) .code ; $ = 0 .data db 7 ; $ = 5 ; $ = 0 ; $ = 5

Programarenlimbajdeasamblare 135 Contoarele de locaii sunt utile la calculul automat al unor deplasamente sau dimensiuni. n exemplul urmtor, se definete un tablou de cuvinte TAB i o variabilLNGcareconinenumruldecuvintedintablou:
TAB dw 1, 2 , 3, 4, 5, 6, 7, 8, 9 LNG dw ($ - TAB)/2

Expresia $ TAB reprezint numrul de octei de la adresa TAB pn la adresa curent. mprind acest numr la 2, se deduce numrul de elemente din tablou. Putem acum aduga sau elimina date din tabloul TAB fr a actualiza lungimea LNG: asamblorul va calcula corect numrul de elemente din tablou. Alteexempledeutilizarepotfi:
JMP $ JMP $ + 5 ; Ciclu infinit: $ este chiar adresa ; instructiunii JMP ; salt relativ

Directiva ORG(OriginIniializeazcontoruldelocaii) Aceast directiv modific explicit contorul de locaii curent, avnd forma general:
ORG expresie

Deexemplu:
ORG $ + 5 ; Sare 5 octeti la asamblare ORG 100H ; Asambleaza la offset-ul absolut 100H

4.5Definireaiiniializareadatelor
Asamblorulrecunoatetreicategoriisintacticedebaz: constante variabile etichete(inclusivnumedeproceduri). Constantele pot fi absolute (numerice) sau simbolice. Constantele simbolice reprezint nume generice asociate unor valori numerice. Variabilele identific datele (un spaiu de memorie rezervat), iar etichetele identific codul (program sauprocedur). Instruciuni de tipul MOV, ADD, AND etc. folosesc variabile i constante, iar instruciunileJMPiCALLfolosescetichete. Variabilele i etichetele au asociate atribute, cum ar fi segmentul n care sunt definite,offsetullacaresuntdefiniteninteriorulsegmentuluietc.

4.5.1Constante

136 Capitolul4
Constantelenumericeabsolutepotfi: constantebinareseutilizeazsufixulBsaub constanteoctaleseutilizeazsufixeleO,Q,osauq constantezecimalefrsufixsaucusufixeleDsaud constante hexazecimale se utilizeaz sufixele H sau h i prefixul 0 dac prima cifr este mai mare ca 9 pentru cifrele peste 9 se utilizeaz simbolurileA...Fsaua...f. constante ASCII se scriu unul sau mai multe caractere ASCII ntre semnul apostrofsaughilimele Iat exemple de constante absolute: 123, 123D, 10001100B, 177q, 0AAH, 3fh, 'a',"AB". ConstantelesimbolicesedefinesccudirectivaEQU,nformageneral:
nume EQU expresie

Deexemplu,liniiledeprogram:
CR EQU 0DH LF EQU 0AH

definesc constantele simbolice CR i LF, cu valorile 0DH i 0AH. Putem folosi aceste constante simbolice n orice context n care este permis folosirea unei constantenumerice.

4.5.2Definireaiutilizareavariabilelor
Pentru definirea variabilelor, se utilizeaz directivele DB, DW, DD, DQ sau DT, care au fost introduse n Capitolul 1. Forma general a unei definiii de date este:
nume directiva lista_de_valori

n care nume este identificatorul asociat definiiei respective, iar list_de_valori estelistavaloriloriniiale,carepoatecuprinde: constantenumerice(absolutesausimbolice) simbolul? o adres, adic un nume de variabil sau de etichet se folosete la DW iDD unirASCII operatorulDUP(expresie),ncareexpresiepoatefi: constantnumeric listdevalori simbolul? operatorulDUP. Semnificaia simbolului ? este locaie neiniializat, iar cea a operatorului DUP,repetareadeunnumrdeoriaexpresieidinparantez.

Programarenlimbajdeasamblare 137 Sconsidermdefiniiileurmtoare:


var var_ adr_ adr_ a b n f db db dw dd 2 dup (0, 3 dup (1)) 1, 2, 3, ?, ?, ? var_a var_b

Primadefiniieesteechivalentcu:
var_a db 0, 1, 1, 1, 0, 1, 1, 1

Atributeledatelordefinitesunt: segmentcelcurent offsetcelcurent tip 1, 2, 4, 8, 10, dup cum sa utilizat ca directiv de baz DB, DW, DD, DQsauDT. Variabilelepotfiutilizateca: variabilesimplevar_a,var_b variabileindexatevar_a[bx],var_b[2],ALFA[si][bx]. n cazul variabilelor indexate, trebuie inut seama de tipul variabilei de baz. Deexemplu,nurmadefiniieitabloului:
B dw 10 dup(?)

expresiile indexate corecte din punct de vedere logic, care acceseaz elementele lui B, sunt B[0], B[2] etc. Din punct de vedere sintactic, putem scrie i:
mov ax, B [1]

dar aceast form va ncrca n AL partea high a primului cuvnt din tablou i n AH partea low a celui deal doilea cuvnt din tabloul B. Dac acest lucru sa urmrit,perfect! n cazul accesrii variabilelor prin expresii anonime, poate aprea necesitatea operatoruluiPTR.Instruciunile:
lea bx, B inc byte ptr [bx][4] inc word ptr [bx][4]

incrementeazoctetul,respectivcuvntuldelaadresaBX+4.

4.6Definireaetichetelor.DirectivaLABEL
Etichetele sunt folosite pentru specificarea punctelor int la instruciuni de salt sau apel sau pentru o specificare alternativ a datelor. n ambele cazuri, numele etichetei devine un nume simbolic asociat adresei curente de memorie.

138 Capitolul4
Atributele etichetelor sunt: segment, offset i tip. Pn acum am ntlnit dou modalitidedefinireaetichetelor: prinnumeurmatdecaracterul:sedefineteoetichetdetipnear prin directiva PROC numele procedurii este interpretat ca o etichet cu tipulderivatdintipulprocedurii Oaltposibilitateestedirectiva LABEL,careareformageneral:
nume LABEL tip

Dac ceea ce urmeaz reprezint instruciuni (cod), tipul etichetei va fi, de regul, NEAR sau FAR i eticheta va fi folosit ca punct int n instruciuni de timp JMP/CALL. Dac ceea ce urmeaz reprezint definiii de date, tipul eticheteivafi,deregul,BYTE,WORD,DWORDetc. Atributele NEAR sau FAR pot aprea numai dac eticheta este definit ntrun segment asociat cu registrul CS printro directiv ASSUME (explicit sau implicit). Directiva LABEL este util atunci cnd dorim s accesm variabile n moduri diferite.Deexemplu,nurmadefiniiei:
ALFAB label BYTE ALFAW dw 1234H

o instruciune de forma inc ALFAB va incrementa octetul mai puin semnificativ al cuvntului, iar una de tip inc ALFAW va incrementa ntreg cuvntulunefectsimilarsepoateobineprinoperatorulPTR. Similar,definiia:
adr_proc label dword proc_off dw ? proc_seg dw ?

permite definirea explicit a segmentului i a offsetului, dar i accesul la nivel dedublucuvnt,deexempluntroinstruciunedeapelindirectintersegment.

4.7Definireastructurilor.Operaiispecifice
Structurile reprezint colecii de date (cmpuri sau membri) plasate succesiv n memorie, grupate sub un unic nume sintactic. Dimensiunea unei structuri este suma dimensiunilor cmpurilor componente. Forma general a definiiei uneistructurieste:
nume_structura STRUC . . nume_membru definitie_date . . nume_structura ENDS

Programarenlimbajdeasamblare 139 Prin aceasta se definete tipul structurii (ablonul) fr a se rezerva spaiu de memorie. Definiiile de date pot cuprinde directive DB, DW etc. cu valori iniiale asociate, ?, DUP etc., exact ca orice definiie de date. Numele membrilor structurii trebuie s fie distincte, chiar dac aparin unor structuri distincte.Iatunexempludedefiniiedetipdestructur:
ALFA STRUC a db b dw c dd d db ALFA ENDS ? 1111H 1234 ?

O structur definit este interpretat ca un tip nou de date, care poate apoi participa la definiii concrete de date, cu rezervare de spaiu de memorie. De exemplu,putemdefiniostructurdetipulALFA,cunumelex:
x ALFA <, , 777, 5>

n care ALFA este tipul de date, x este numele variabilei, iar ntre paranteze unghiulare se trec valorile iniiale ale cmpurilor structurii x. Prezena virgulelor din lista de valori iniiale precizeaz c primii doi membri sunt iniializai cu valorile implicite de la definiia tipului ALFA, al treilea membru este iniializat cu valoarea 777, iar al patrulea cu valoarea 5. Astfel, definiia variabileixesteechivalentcusecvenadedefiniii:
a b c d db dw dd db ? 1111H 777 5

Principalul avantaj al structurilor este accesul la membri ntro form asemntoare limbajelor de nivel nalt. De exemplu, pentru a ncrca n SI cmpulbalstructuriix,putemscrie:
mov si, x.b

Accesullamembriistructuriixpoatefidecidetaliatn: x.avariabildetipbyte x.bvariabildetipword x.cvariabildetipdword x.dvariabildetipbyte Putemacumdefiniuntabloude5structuridetipALFA:


y ALFA 5 dup <, , , 10>

n care primii trei membri sunt iniializai cu valorile de la definiia tipului structurii, iar al patrulea cu valoarea 10. Au acum sens expresii de forma: y[0].a, y[SI], y[8].c, y[BX].d etc. De fapt, toate aceste expresii se evalueaz din adresa

140 Capitolul4
de nceput a variabilei y la care se adaug un deplasament corespunztor. Expresia y[11].d este echivalent cu y + 11 + deplasamentul cmpului d fa ncadrultipuluiALFA. Se observ c gestiunea deplasamentelor cade n sarcina utilizatorului. Dac dorim s accesm cmpul c al celei dea doua structuri din tabloul y, nu putem scrie y[1].c, aa cum am scrie ntrun limbaj de nivel nalt, ci y[8].c. Limbajul de asamblare ne pune la dispoziie operatorul TYPE, care ntoarce numrul de octei ocupat de o structur. Pentru a generaliza accesul la al ilea element al tablouluiy(icuprinsntre0i4),putemscriey[i*TYPEALFA].c. Problema se complic dac indicele i este cunoscut deabia la momentul execuiei(fiindmemoratntrunregistru,deexemplu).Oexpresiedeforma:
mov al, y [SI*TYPE ALFA].d

are sens numai la procesoarele care accept adresare cu factor de scal (80386 i peste) i numai dac factorul de scal este 1, 2, 4, sau 8. n caz contrar,deplasamentultrebuiecalculatexplicitprinoperaiiaritmetice. Cu toate aceste limitri, structurile sunt intens utilizate atunci cnd se lucreaz cu anumite abloane fixe, cum ar fi, de exemplu, imaginea stivei la intrarea ntr o procedur sau transmiterea prin referin a unei zone de date. S considermonregistrarelogicdescrisprincmpuri: cmpulNUMEirASCIIde30decaractere cmpulPRENUMEirASCIIde20decaractere cmpulCODntregpe4octei Dorim s transmitem unei proceduri far cu numele PRELUCRARE o asemenea nregistrare. Cel mai simplu mod este de a transmite adresa (near sau far) a zonei de memorie n care este stocat nregistrarea, de exemplu printrun registru sau o pereche de registre pentru accesul comod la cmpuri definim structura:
PERSOANA STRUC NUME PRENUME COD PERSOANA ENDS db 30 dup (?) db 20 dup (?) dd ?

Definiiaconcretadatelorisecvenadeapelaproceduriieste:
.data om adr_om .code les di, adr_om call PRELUCRARE PERSOANA <'Ionescu', 'Ion', 77206> dd om ; Pointer la om

Programarenlimbajdeasamblare 141 Se pune acum problema accesului la cmpurile nregistrrii, din interiorul procedurii. Beneficiem acum de structura PERSOANA. Ca s ncrcm adresa cmpuluiPRENUMEvomscrie:
lea bx, es:[di].PRENUME

Perechea ES:DI conine adresa structurii om, iar expresia es:[di].PRENUME reprezint deplasamentul cmpului PRENUME. n acest moment, n ES:BX avem adresa irului de caractere de tip PRENUME. Similar se procedeaz i pentrucelelaltecmpuri:casprelumnDX:AXcmpulCOD,putemscrie:
mov ax, word ptr es:[di].COD mov dx, word ptr es:[di].COD + 2

Este evident c toate secvenele de mai sus se puteau nlocui cu deplasamente calculate explicit de ctre programator. ncrcarea cmpului CODarfipututfiscris:
mov ax, word ptr es:[di + 50] mov dx, word ptr es:[di + 52]

dar forma cu nume de cmpuri este mult mai clar i mai comod. n plus, noi putemgreilacalcululunuideplasament,darasamblorulnu. Aceast tehnic este benefic i din punctul de vedere al ntreinerii unui program. Dac se modific ulterior nregistrarea PERSOANA i se adaug nc un cmp ntre PRENUME i COD, toate deplasamentele calculate explicit trebuie modificate. n varianta cu structur, trebuie doar s schimbm definiia structurii,restulfiindfcutautomatlaasamblare.

4.8Definireanregistrrilor.Operaiispecifice
nregistrrile (RECORD) corespund de fapt unor structuri mpachetate din limbajele de nivel nalt. Concret, o nregistrare este o definiie de cmpuri de bii de lungime maxim 8 sau 16. Din punct de vedere sintactic, definiia unei nregistrriestesimilarcuceaauneistructuri,formageneralfiind:
nume_inregistrare RECORD nume_camp:valoare, ...

sau,cuiniializareimplicit:
nume RECORD nume_camp:valoare = expresie, ...

Valorile care apar asociate cu numele de cmpuri dau de fapt numrul de bii pe care se memoreaz cmpul respectiv. n varianta cu iniializare, expresia care apare dup semnul egal se evalueaz la o cantitate care se reprezint pe numrul de bii asociat cmpului respectiv. La fel ca la structuri, numele cmpurilortrebuiesfiedistincte,chiardacaparinunornregistrridiferite. Sconsidermunexemplu:

142 Capitolul4
BETArecordX:7,Y:4,Z:5 prin care se definete un ablon de 16 bii, grupai n cmpurile X, Y i Z (veziFigura4.2)

Figura 4.2 Definiia unei nregistrri Lafelcalastructuri,putemacumdefinivariabiledetipulnregistrriiBETA:


VAL BETA <5, 2, 7>

n care valorile dintre parantezele unghiulare iniializeaz cele trei cmpuri de bii.Seobservcaceastdefiniieesteechivalentcudefiniiaexplicit:
VAL dw 0000101001000111B

Exist doi operatori specifici nregistrrilor: MASK i WIDTH. Operatorul MASK primete un nume de cmp i furnizeaz o masc cu biii 1 pe poziia cmpului respectiv i 0 n rest. Astfel, expresiile MASK X i MASK Y sunt echivalente cu constantele binare 1111111000000000B i 0000000111100000B. Asemenea expresii pot fi utilizate pentru selectarea cmpurilor respective, ca n exempleledemaijos:
AND AX, MASK Y AND BX, NOT MASK Z ; Filtreaza campul Y ; Forteaza campul Z la 0

Operatorul WIDTH primete un nume de nregistrare sau un nume de cmp dintro nregistrare, ntorcnd numrul de bii ai nregistrrii sau ai cmpului respectiv.Deexemplu,secvena:
MOV AL, WIDTH BETA MOV BL, WIDTH Y ; Al <--- 16 ; BL <--- 4

vancrcanALvaloarea16inBLvaloarea4. Dac se utilizeaz un nume de cmp ntro instruciune de tip MOV, se va ncrca un contor de deplasare, util pentru a deplasa cmpul respectiv pe poziiilecelemaipuinsemnificative.

Programarenlimbajdeasamblare 143 S presupunem c dorim s testm valoarea numeric a cmpului Y din nregistrarea VAL. Nu este suficient sl izolm i s folosim o instruciune de comparaie. nainte de comparaie, cmpul Y trebuie adus pe poziiile cele maidindreapta.Realizmacesteoperaiiprinsecvena:
MOV AND MOV SHR AX, AX, CL, AX, VAL MASK Y WIDTH Y CL ; ; ; ; Preluare inregistrare Selectare camp Y Incarcare in CL a valorii 4 Deplasare camp Y la dreapta

4.9Operatorinlimbajuldeasamblare
Limbajul de asamblare dispune de un set de operatori cu care se pot forma expresii aritmetice i logice. Aceste expresii sunt evaluate la momentul asamblrii, producnd, de fapt, constante numerice. Este esenial s deosebim instruciunile executabile (codul main) de operaiile care se fac lamomentulasamblrii.

4.9.1Operatoriaritmeticiilogici
Operatorii aritmetici sunt: +, , *, /, MOD, SHL i SHR. Primii patru au semnificaii evidente i opereaz numai cu cantiti ntregi. Operatorul MOD produce restul la mprire, iar SHL i SHR provoac deplasare la stnga sau ladreapta. Deexemplu,instruciunea:
mov ax, 1 SHL 3 ; 1 deplasat la stanga cu 3 biti

esteechivalentcu:
mov ax, 100B

Similar,ndirectiva:
COUNT dw ($ - TAB)/2

se va evalua la momentul asamblrii expresia ($ TAB)/2, adic diferena dintrecontorulcurentdelocaiiiadresaTAB,mpritla2. Operatorii logici sunt NOT, AND, OR i XOR, cu semnificaii evidente. Toi aceti operatori accept drept operanzi constante ntregi operaiile respective se fac la nivel de bit. Ei nu trebuie confundai cu instruciunile executabile cu acelainume.ninstruciunea:
and al, (1 SHL 3 ) OR (1 SHL 5)

registrulALvafincrcatcuconstanta101000B.

4.9.2Operatorirelaionali

144 Capitolul4
Operatorii relaionali sunt EQ, NE, LT, LE, GT, GE, cu semnificaii evidente. Acetia ntorc valori logice, codificate ca 0 sau ca secvene de 1 pe un numr corespunztordebii.nurmadefiniiilor:
x db 1 EQ 2 y dw 1 NE 2 z dd 1 LT 2

variabilele x, y i z vor fi iniializate cu constantele 0, 0FFFFH, respectiv 0FFFFFFFFH. Operatorii relaionali sunt utilizai n special n directivele de asamblare condiionat.

4.9.3Operatoruldeatribuire=
Operatorul de atribuire = definete constante simbolice, fiind similar cu directiva EQU,darpermiteredefinireasimbolurilorutilizate.Odefiniredeforma:
N EQU 1 N EQU 2

estesemnalatcaeroare,darsecvena:
N = 1 N = 2

estecorect. Acestoperatoresteutilizatnspecialndefiniiiledemacroinstruciuni.

4.9.4Operatoricarentorcvalori
Aceti operatori se aplic unor entiti ale programului n limbaj de asamblare (variabile,etichete),ntorcndvaloriasociateacestora. Operatorul SEG Se aplic att variabilelor, ct i etichetelor i furnizeaz adresa de segment asociat variabilei respective. Dac var este o variabil, atunci putem scrie secvena:
mov ax, SEG var mov ds, ax

Operatorul OFFSET EstesimilarcuSEG,furnizndoffsetulasociatvariabileisauetichetei:


mov bx, OFFSET var

Operatorul THIS

Programarenlimbajdeasamblare 145 Acest operator creeaz un operand care are asociate o adres de segment i un offset identice cu contorul curent de locaii. Forma general a operandului este:
THIS tip

n care tip poate fi BYTE, WORD, DWORD, QWORD sau TBYTE pentru definiii de date, respectiv NEAR sau FAR pentru etichete. Operatorul THIS se utilizeaz de obicei cu directiva EQU. De exemplu, definiia constantei simbolice:
ALFA EQU THIS WORD

esteechivalentcudefiniiauneietichete:
ALFA LABEL WORD

Operatorul TYPE Se aplic variabilelor i etichetelor, ntorcnd tipul acestora. Pentru variabile ntoarce valorile 1, 2, 4, 8 sau 10 pentru variabile simple (definite cu directivele DB, DW, DD, DQ respectiv DT), iar pentru structuri ntoarce numrul de octei pe care este memorat structura respectiv. Pentru etichete, ntoarce tipul etichetei(NEARsauFAR). Operatorul LENGTH Se aplic numai variabilelor i ntoarce numrul de elemente definite n variabila respectiv.Deexemplu,ndefiniia:
A DW 100 dup (?)

expresiaLENGTHAarevaloarea100. Operatorul SIZE Se aplic numai variabilelor i ntoarce dimensiunea n octei a variabilei respective.ndefiniiademaisus,expresiaSIZEAarevaloarea200. Pentruovariabiloarecarevar,areloctotdeaunaidentitatea:
SIZE var = (LENGTH var) * (TYPE var)

Aceti operatori sunt utili la prelucrarea tablourilor. Secvena urmtoare nu depindedetipuldebazaltablouluiTABinicidedimensiuneasa:


.data TAB .code mov lea bucla: .... add loop si, TYPE TAB bucla cx, LENGTH TAB si, TAB dd 100 dup (?)

146 Capitolul4
Dac nlocuim acum tipul de baz al tabloului TAB cu o structur de tip PERSOANA(definitn4.7),modificndidimensiunea:
PERSOANA STRUC ....... PERSOANA ENDS .data TAB PERSOANA 50 dup <,,,>

partea de program nu trebuie modificat, deoarece asamblorul va evalua corect expresiileLENGTHTABiTYPETAB.

4.9.5OperatorulPTR
Acest operator se aplic att variabilelor, ct i etichetelor, avnd ca efect schimbarea tipului variabilei sau al etichetei respective. Este obligatoriu n cazul n care se folosesc referine anonime la memorie, din care nu se poate deducetipuloperandului:
add call call word ptr [bx], 2 dword ptr [bx] near ptr proc

4.10Directivedeasamblarecondiionat
Permit ignorarea unor poriuni din textul surs, funcie de o condiie care se poateevalualaasamblare.DirectivadebazesteIF,cuformageneral:
IF expresie . . . [ELSE] . . . ENDIF

Dac expresia din directiva IF este adevrat (adic este diferit de 0), se asambleaz poriunea de program dintre IF i ELSE i se ignor poriunea dintre ELSE i ENDIF. Dac expresia din IF este fals, se asambleaz poriunea de program dintre ELSE i ENDIF i se ignor poriunea dintre IF iELSE.RamuraELSEesteopional. Aceste operaii se petrec la momentul asamblrii, permind ntreinerea comod a unui program de dimensiuni mari sau chiar meninerea n acelai text surs a mai multor variante de program executabil. S presupunem c dorim un program care s poat fi configurat rapid pentru modele de date mici, respectiv mari. Aceasta presupune ca orice secven de instruciuni care definete, citete sau scrie o adres s fie inclus n directive de asamblarecondiionat:

Programarenlimbajdeasamblare 147
FALSE equ 0 TRUE equ NOT FALSE DATE_MARI equ TRUE DATE_MICI equ NOT DATE_MARI .data X dw 100 dup (?) IF DATE_MARI ADR_X dd X ELSE ADR_X dw X ENDIF .code IF DATE_MARI lds si, ADR_X ELSE mov si, ADR_X ENDIF ; ; Prelucrare TABLOU ;

Exist i directivele IFDEF/ENDIF i IFNDEF/ENDIF, care testeaz dac un simbol este definit sau nu, i directivele IFB/ENDIF (If Blank), respectiv IFNB/ENDIF (If Not Blank), care testeaz dac un simbol este vid sau nevid. Acesteadinurmvorfiutilizateladefinireamacroinstruciunilor. n expresiile care apar n directivele de tip IF se utilizeaz de obicei operatori logiciirelaionali. S considerm un exemplu de program surs multifuncional. Se dorete scrierea unei secvene care s calculeze n acumulator suma elementelor unui tablou A (de octei sau de cuvinte), definit n segmentul curent de date, ca sum pe octei i pe cuvinte, indiferent de tipul i de dimensiunea tabloului. TipulsumeiestedictatdeconstantelesimboliceSUM_BiSUM_W.
FALSE TRUE SUM_B SUM_W .code if SUM_B mov else mov endif xor mov bucla: if SUM_B add inc else add equ equ equ equ cx, SIZE A cx, (SIZE A)/2 bx, bx ax, bx al, byte ptr A [bx] bx ax, word ptr A [bx] ; Indice initial ; Suma initiala ; Suma pe octet ; Actualizare adresa ; Suma pe cuvant 0 NOT FALSE TRUE NOT SUM_B ; Numar de iteratii

148 Capitolul4
inc bx inc bx endif loop bucla ; Bucla A) MOD 2) EQ 1 Un eventual ultim octet if SUM_W AND (TYPE A EQ 1) AND ((SIZE push ax mov al, byte ptr A [bx] ; cbw ; mov dx, ax ; pop ax add ax, dx endif ; Actualizare adresa

Se observ c nu putem iniializa contorul CX cu expresia LENGTH A, deoarece numrul de iteraii este dictat de modul de calcul al sumei, i nu de tipul tabloului. Ca atare, lum dimensiunea n octei a tabloului, pe care o mprim la 2 n cazul sumei pe cuvnt. Calculul sumei i actualizarea adresei suntevidente. Apare o problem special n urmtoarea situaie: se cere suma pe cuvnt, iar tabloul, definit ca tablou de octei, are un numr impar de elemente. n aceast situaie, este evident c ultimul octet nu este considerat n bucla de sumare.Caatare,elesteadugatexplicitlasfrit. De remarcat formularea situaiei de mai sus n termenii condiiei logice de la ultimadirectivIF: SUM_Wcodificcerereadecalculasumeilaniveldecuvnt (TYPE A EQ 1) codific situaia n care tabloul A este definit la nivel de octet ((SIZE A) MOD 2) codific situaia n care tabloul are un numr impar de octei.

Capitolul5
Macroinstruciuni
5.1Scopulmacroinstruciunilor.Definireiexpandare
Macroinstruciunile permit programatorului s defineasc simbolic secvene de program (instruciuni, definiii de date, directive etc.), asociate cu un nume. Folosind numele macroinstruciunii n program, se va genera ntreaga secven de program. n esen, este vorba de un proces de substituie (expandare) n textul programului surs, care se petrece nainte de asamblarea programului. Un asamblor care dispune de macroinstruciuni se numete macroasamblor. Sunt dou etape de lucru cu macroinstruciuni: definirea macroinstruciunilor i utilizarea lor. Utilizarea se mai numete invocare sau chiar apel de macroinstruciune, dar ultima denumire poate produce confuzie, termenul utilizndusencazulprocedurilor. Spre deosebire de proceduri, macroinstruciunile sunt expandate la fiecare utilizare, deci programul nu se micoreaz. Avantajul este c textul surs scris deprogramatordevinemaiclarimaiscurt. Macroinstruciunile pot fi cu parametri sau fr parametri. Din punct de vedere sintactic, ele sunt asemntoare cu directivele de tip DEFINE din limbajele de nivelnalt,dispunnd,ngeneral,demecanismemaievoluatedectacestea. Definiiauneimacroinstruciunifrparametrisefacenformageneral:
nume_macro MACRO ; ; Corp macroinstructiune ; ENDM

Invocarea const n scrierea n textul surs a numelui macroinstruciunii. Macroinstruciuneainit_ds_esestedefinitnfiierulheaderio.hprin:


init_ds_es macro mov ax, DGROUP mov ds, ax

150 Capitolul5
mov endm es, ax

Macroinstruciuneaexit_dosestedefinitprin:
exit_dos macro mov ax, 4C00H int 21H endm

O pereche de macroinstruciuni care salveaz i refac registrele generale poateficonceputastfel:


save macro push push push push push push rest ax bx cx dx si di endm macro pop pop pop pop pop pop di si dx cx bx ax

endm

Putem utiliza aceste macroinstruciuni la intrarea i la ieirea dintro procedur:


PROCEDURA save . . rest ret PROCEDURA proc near

endp

Din punct de vedere simbolic, este ca i cum setul de instruciuni al mainii ar fifostextinscudounoiinstruciuni:SAVEiREST.

5.2Macroinstruciunicuparametri
Macroinstruciunile importante sunt cele cu parametri. Definiia unei macroinstruciunicuparametriareformageneral:
nume_macro MACRO P1, P2, ..., Pn ; ; Corp macroinstructiune ; ENDM

n care P1, P2, ..., Pn sunt identificatori care specific parametrii formali. Apelul (invocarea) unei macroinstruciuni cu parametri se face prin specificarea numelui,urmatdeolistdeparametriactuali:
nume_macro X1, X2, ..., Xn

Programarenlimbajdeasamblare 151 La expandarea macroinstruciunii, pe lng expandarea propriuzis, se va nlocuifiecareparametruformalcuparametrulactualrespectiv. S considerm cteva exemple. Apelurile de funcii DOS presupun numrul funcieinregistrulAH.Putem,deci,definiomacroinstruciunedeforma:
dosint endm macro N mov ah, N int 21H

iputeminvocamacroinstruciuneaprinliniideforma:
dosint 2

Similar, pentru deschiderea unui fiier disc pentru citire (operaie realizat prin funciaDOS3CH),putemscrieomacroinstruciunedeforma:
o_read macro mov lea dosint mov endm fname, hand al, 0C0H dx, fname 3DH hand, ax

n care file_name conine numele fiierului, iar handle este o variabil de tip word n care se depune un indicator ctre fiierul deschis. Parametrul 0C0H codific modul de acces. Se observ utilizarea macroinstruciunii dos_int n definiialuio_read. Citireadinfiierpoateficodificatntromacroinstruciunedeforma:
f_read macro hand, buf, nr mov bx, hand mov cx, nr lea dx, buf dosint 3FH endm

n care hand este indicatorul ctre fiierul anterior deschis, nr este numrul de octei care se citete, iar buf este adresa unei zone de memorie n care se vor depunedatelecitite. nchidereaunuifiierdeschissepoatefacecuomacroinstruciunedeforma:
f_close macro hand mov bx, hand dosint 3EH endm

Macroinstruciunile de mai sus sunt definite n fiierul io.h. Ne propunem acum s scriem un program executabil care s afieze la consol un fiier text. Beneficiemdemacroinstruciuniledefinitenfiierulio.h:

152 Capitolul5
.model large include io.h .stack 1024 .data file_name db hand dw buf db .code start: init_ds_es putsi <'Nume fisier: '> gets file_name o_read file_name, hand jc eroare bucla: f_read jc mov mov puts cmp jb jmp gata: f_close hand jmp iesire eroare: putsi iesire: exit_dos end start <'Eroare fisier'> ; Inchidere ; Salt la iesire ; Mesaj de ; eroare ; Iesire n DOS hand, buf, 1024 eroare si, ax byte ptr buf [si], 0 buf ax, 1024 gata bucla ; ; ; ; ; ; ; ; Citire 1024 octeti Eroare citire AX = cati octeti s-au citit de fapt Afisare la consola S-au citit mai putin de 1024 ? Nu, reluare ; ; ; ; Mesaj Citire nume Deschidere Eroare deschidere ?

30 dup (0) ; Spatiu nume fisier ? ; Spatiu handler 1024 dup (?); Buffer citire

n zona de date, se rezerv spaiu pentru numele fiierului, pentru indicator (handler) i pentru un buffer de citire de 1024 de octei. Reamintim c operaiile cu perifericele sunt n esen transferuri ntre periferice i memorie. Programul afieaz un mesaj la consol, dup care citete un nume de fiier. Se face apoi operaia de deschidere a fiierului specificat. Toate funciile DOS de lucru cu fiiere ntorc CF = 1 n caz de eroare. O eroare tipic la operaia de deschidere pentru citire este un nume eronat de fiier. Se testeaz deci CF i, n caz de eroare, se afieaz un mesaj adecvat i se iese nDOS. Se trece acum la o bucl de citireafiare. Funcia de citire ntoarce n AX numrul de octei efectiv citii (care este mai mic sau egal cu cel cerut). Dorim s afim numai ce sa citit efectiv, aa c punem terminatorul 0 n buffer, dup ultimul octet efectiv citit. E posibil ca, la ultima iteraie, s se citeasc 0 octei. Se afieaz la consol bufferul respectiv (cu macroinstruciuneaputs).

Programarenlimbajdeasamblare 153 Dac numrul de octei efectiv citii este mai mic strict dect cel cerut (1024) nseamn c sa ajuns la sfritul fiierului i bucla se termin. n caz contrar, sereiacuonoucitiredinfiier.nfinal,senchidefiieruliseiesenDOS. Acest exemplu ilustreaz foarte bine avantajele macroinstruciunilor. O aciune destul de laborioas n limbaj de asamblare (afiare fiiere text) a putut fi codificat prin cteva linii de program surs (e drept c aproape toate suntinvocridemacroinstruciuni). Morala fabulei este c, dac reuim s concepem un set de macroinstruciuni adecvat unei probleme (n cazul de fa, interfaa cu sistemul DOS), scrierea programelordevinefoartecomod. Cititorul este sftuit s scrie un program similar, care s realizeze copierea unui fiier disc n alt fiier. Pentru operaii de scriere, se pot utiliza macroinstruciunile:
o_write macro mov lea dosint move endm f_write macro mov mov lea dosint endm fname, hand al, 0C1H dx, fname 3DH hand, ax hand, buf, nr bx, hand cx, nr dx, buf 40H

care deschid un fiier pentru scriere, respectiv scriu n fiier. Parametrii sunt asemntori cu cei din macroinstruciunile o_read i f_read. Bucla de citire_din_fiierafiare din exemplul anterior se nlocuiete cu o bucl de citire_din_fiier_sursscriere_n_fiier_destinaie. n unele situaii, substituia parametrilor formali cu cei actuali poate ridica unele probleme. S presupunem c un tnr programator care nva limbajul ASM nu a ajuns nc la instruciunea XCHG, ci are cunotin doar de instruciunile PUSH, POP i MOV. El i propune s scrie o macroinstruciunecaresinterschimbedoucantitide16bii:
trans macro push push mov mov mov mov pop pop endm X, Y ax bx bx, X ax, Y X, ax Y, bx bx ax

154 Capitolul5
Aparent,totulenordine.Totui,potapreasituaiinedorite,cansecvena:
trans AX, SI ; Interschimba AX cu SI (oare ?)

Aceastinvocaredemacroinstruciuneseexpandeazn:
push push mov mov mov mov pop pop ax bx bx, ax, AX, SI, bx ax

AX SI ax bx

i este evident c registrul AX nu se modific. Se poate ns i mai ru, ca n secvena:


trans SP, DI ; Interschimba SP cu DI (oare ?)

careseexpandeazn:
push push mov mov mov mov pop pop ax bx bx, ax, SP, DI, bx ax

SP DI ax bx

; ; ; ;

Aici se modifica SP si POP-urile sunt compromise

Pericolul apare, deci, n situaiile n care parametrii actuali intr n conflict cu anumite variabile sau registre care sunt folosite n interiorul macroinstruciunii. Acestesituaiitrebuieevidentevitate. Utilitatea foarte mare a macroinstruciunilor devine evident la secvenele de apel ale procedurilor cu parametri (n acest caz, se vorbete despre macroinstruciuni de apel). Apelurile de funcii sistem codificate anterior sunt cazuriparticularedemacroinstruciunideapel. Procedurile cu parametri utilizeaz diverse tehnici de transmitere a parametrilor. Parametrii trebuie plasai n anumite registre sau n stiv, ntro ordine specificat. Aceste detalii de apel sunt greu de inut minte i nici nu intereseaz pe cel care apeleaz procedura. Putem ns dezvolta macroinstruciunicaresascundacestedetalii. S considerm o procedur NEAR cu numele puts_proc, care afieaz un ir de caractere (terminat cu 0). Adresa irului (offsetul n cadrul segmentului curent adresat prin DS) se specific n registrul SI. O macroinstruciune de apelsepoatescrienforma:
puts macro X push si

Programarenlimbajdeasamblare 155
lea call pop endm si, X puts_proc si

Ca parametru actual se poate utiliza orice operand compatibil cu instruciunea LEA.Astfel,dacexistdefiniiadedate:


.data STRING db "abcdefghijklmnopqrstuvwxyz", 0

sepotutilizaformeledeinvocare:
.code puts STRING lea bx, STRING puts [bx] ; Adresare directa ; Adresare indirecta

n al doilea caz, nu putem scrie puts bx, pentru c acest apel ar conduce la o expandare de forma lea si, bx, ceea ce este o eroare de sintax. Forma puts [bx]seexpandeaznleasi,[bx],careestecorect.

5.3Controlulnumruluideparametriactuali
O problem important este controlul coincidenei dintre numrul parametrilor formali i cel al parametrilor actuali. Se vor utiliza urmtoarele directive specifice: Directiva %OUT (Mesaj la consol la momentul asamblrii). Are forma general %OUT TEXT, efectul fiind afiarea TEXTului la consol, la momentul asamblrii este utilizat pentru mesaje de eroare la asamblare. Directiva .ERR (Foreaz eroare de asamblare). Aceast directiv foreaz o eroare la asamblare, astfel nct s nu se mai genereze fiier obiect este utilizat n cazul neconcordanei dintre numrul parametrilor actualiicelalparametrilorformali. DirectivaEXITM(Ieireforatdinexpandare) n caz de eroare, stopm expandarea macroinstruciunii curente i afim un mesajdeeroarelaconsol. Pentru controlul efectiv al parametrilor actuali, se mai utilizeaz directivele de asamblare condiionat IFNB (If Not Blank) i IFB (If Blank) care testeaz existenasaunonexistenaunuiparametruactual. Pentruforareauneierori,definimpentrunceputmacroinstruciunea:
eroare macro text %OUT text .err ;; Mesaj la consola ;; Fortare eroare la ;; asamblare

endm

156 Capitolul5
S considerm macroinstruciunea puts, definit mai sus, care are un singur parametru formal. La invocare, sar putea s existe un parametru actual, nici unul sau mai muli. Pentru a controla toate aceste situaii, rescriem macroinstruciunea puts i o declarm cu doi parametri: X i IN_PLUS. Dac IN_PLUS este nevid, nseamn c sunt cel puin doi parametri actuali, iar dacXestevid,nuexistniciunparametruactual.Codificareavafideci:
puts macro X, IN_PLUS ifb <X> eroare exitm endif ifnb <IN_PLUS> eroare exitm endif lea si, X call puts_proc

<PUTS - lipsa parametru>

<PUTS - parametri in plus>

endm

Testm explicit dac X este vid i dac IN_PLUS este nevid, fornd mesaje adecvate de eroare. Scrierea cu paranteze unghiulare <> nseamn literalizarea textului respectiv, adic transmiterea lui ca un unic parametru. Dac se considerunfiiert_macro.asmcusecveneledeinvocare:
.data sir .code puts puts puts puts puts puts end [si] [bx] [si] [bx], [si] [bx], sir sir db 10 dup (0)

atuncisevorobinemesajeledeeroare:
PUTS - parametri in plus PUTS - parametri in plus PUTS - lipsa parametru PUTS - parametri in plus **Error** t_macro.asm(26) **Error** t_macro.asm(27) **Error** t_macro.asm(28) **Error** t_macro.asm(29)

EROARE(2) EROARE(2) EROARE(2) EROARE(2)

User User User User

generated generated generated generated

error error error error

Numereledinparantezeindicliniiledinfiierulsursncareafostforat expliciteroareadeasamblare. Putem acum da o regul general de scriere a unei macroinstruciuni cu controlul parametrilor. Dac macroinstruciunea are N parametri utili, declarm

Programarenlimbajdeasamblare 157 un al N+1lea parametru suplimentar i testm dac al Nlea parametru este vid (cu directiva IFB), respectiv dac al N+1lea parametru este nevid (cu directiva IFNB).

5.4 Directive de control macroinstruciuni

al

listrii.

Etichete

Exist diverse posibiliti de control al fiierului listing al unui program care coninemacroinstruciuni.Controlulsefaceprinurmtoareledirective: Directiva .SALL (Supress All Suprim tot). n textul surs care urmeaz acestei directive, se va suprima listarea coninutului macroinstruciunilor invocate. n listing apare numai invocarea (numele) macroinstruciunii,exactcanfiierulsurs. Directiva .LALL (List All Listeaz tot). Dup aceast directiv, se listeaz attinvocareamacroinstruciunii,ctitextulgenerat. Directiva .XALL Dup aceast directiv, se listeaz textul generat efectiv de invocarea unei macroinstruciuni. Dac macroinstruciunile conin invocri ale altor macroinstruciuni, la al doilea nivel se listeaz numai invocarea. Uneori e necesar ca macroinstruciunile s conin etichete, de exemplu pentru instruciuni de salt. Apare ns urmtoarea problem: dac eticheta se definete n mod obinuit, ea va fi generat la fiecare expandare a macroinstruciunii, ceea ce va duce la mai multe etichete cu acelai nume. Acestfaptvaprovocaoeroarelaasamblare,detipsimbolmultipludefinit. ProblemaserezolvprindirectivaLOCAL,careareformageneral:
LOCAL simb_1, simb_2, ...

efectul fiind c simbolurile care apar n directiv vor fi expandate n aa fel nct s nu apar dou nume identice. Practic, asamblorul genereaz nite nume complicate, de forma ??0000, ??0001, ??0002 etc. (care nu se repet), pentru careexistanseminimescoincidcunumedefinitedeutilizator. Sconsidermmacroinstruciunea:
test_local macro local aici jmp aici aici: endm

isecvenadeinvocare:
.code .xall test_local

158 Capitolul5
test_local test_local end

Sevageneraurmtorullisting:
test_local jmp ??0000: test_local jmp ??0001: test_local jmp ??0002: ??0000 ??0001 ??0002

Eticheta aici a fost nlocuit la expandare cu etichetele ??0000, ??0001 i ?? 0002. Simbolurile variabile (definite cu operatorul de atribuire =) se dovedesc utile n macroinstruciuni, deoarece pot fi redefinite chiar n macroinstruciune. S considermdefiniia:
m_mesaj macro db 'Mesaj ', '0'+n, 0 n = n + 1 endm

isecvenadeprogram:
n = 1 .data m_mesaj m_mesaj m_mesaj

Sevageneratextulsurs:
db db db 'Mesaj ', '0' + 1, 0 'Mesaj ', '0' + 2, 0 'Mesaj ', '0' + 3, 0

decicaicumsarfiscris:
db db db 'Mesaj 1', 0 'Mesaj 2', 0 'Mesaj 3', 0

Dac dorim s includem comentarii n macroinstruciuni, dar acestea s nu apar la fiecare expandare, ci numai la definiia macroinstruciunii, putem utilizasecvenadedoucaractere(nceputdecomentariu).

5.5Macroinstruciunirepetitive

Programarenlimbajdeasamblare 159 Aceste macroinstruciuni sunt predefinite, deci nu trebuie definite de utilizator. Scopullorestedeagenerasecvenerepetatedeprogram. Macroinstruciunea REPT (Repete - Repet) Formageneraldeinvocareeste:
rept n ; ; Corp macroinstructiune ;

endm

n care n este o constant ntreag. Efectul este repetarea corpului macroinstruciunii de n ori. Secvena anterioar de generare a trei mesaje s arputeascrieacum:
rept 3 m_mesaj endm

Iatosecvencaregenereazunirdecaractereculiteredela'A'la'Z':
n = 0 alfabet label byte rept 26 db 'A'+n n = n + 1 endm

Macroinstruciunea IRP nedefinit) Formageneraldeinvocareeste:

(Indefinite

Repeate

Repet

irp p_formal, <lista_par_act> ; ; Corp macroinstructiune ; endm

n care p_formal este un parametru formal, iar list_par_act este o list de parametri actuali, separai prin virgul. Efectul este repetarea corpului macroinstruciunii de attea ori cte elemente conine lista de parametri actuali. La fiecare repetare, se substituie parametrul formal cu cte un parametruactual.Invocarea:
irp x, <'a', 'b', 'c'> db x endm

sevaexpandan:
db 'a'

160 Capitolul5
db 'b' db 'c'

5.6Operatorispecifici
Exist o serie de operatori specifici macroinstruciunilor. Acetia controleaz n principal substituia parametrilor actuali, fiind utili n special n macroinstruciunilerepetitive.

5.6.1Operatoruldesubstituireideconcatenare(&)
Acest operator, aplicat unui parametru formal, realizeaz substituia i (eventual) concatenarea sa cu un text fix sau cu un alt parametru formal. Este necesar n contextul n care un parametru formal ar fi interpretat ca un simbol (deexemplu,ntrunirconstantdecaracteresauntrunidentificator). Spresupunemcdorimsdefinimautomatliniiledeprogram:
mesaj_1 mesaj_2 mesaj_3 mesaj_4 db db db db 'Text 'Text 'Text 'Text 1', 2', 3', 4', 0 0 0 0

VomapelaevidentlamacroinstruciuneaIRP.Oprimncercarearfi:
irp x, < 1, 2, 3, 4 > mesaj_x db 'Text x', 0 endm

ceea ce este incorect, deoarece se va produce aceeai linie de program. Prima apariie a parametrului x nu poate fi distins de simbolul mesaj_x, iar a doua nu poate fi distins de irul constant 'Text x'. Aici intervine operatorul &, definiiacorectfiind:
irp x, < 1, 2, 3, 4 > mesaj_&x db 'Text &x', 0 endm

prin care, n primul caz, se concateneaz textul fix mesaj_ cu parametrul formal x, iar n al doilea, se substituie parametrul formal x chiar dac apare ntrun ir constantdecaractere. S considerm un exemplu nrudit, codificat prin macroinstruciunea urmtoare:
genereaza macro fix, n X = 1 rept n fix&&x db 'Text &x', 0

Programarenlimbajdeasamblare 161
x = x + 1 endm endm

Aici e necesar concatenarea a doi parametri formali (fix i x): fiecruia i se aplic operatorul &, la stnga sau la dreapta, dup locul n care are loc concatenarea.Unapeldeforma:
genereaza mesaj_ , 4

vaproduceacelaitextcamacroinstruciuneaIRPdemaisus.

5.6.2Operatoriideliteralizareir/caracter(<>,!)
Operatorul de literalizare ir <> se utilizeaz atunci cnd se dorete ca un text n care apar eventuali separatori (spaii albe, virgule etc.) s fie considerat ca un unic parametru (s fie literalizat). Operatorul se utilizeaz att n definiii, ctininvocridemacroinstruciuni.Deexemplu,ndefiniia:
init macro x irp y, <x> db y endm endm

dorimcaparametrulxdelanivelulexteriorsfietransmisca atarectremacroinstruciuneaIRP.Invocareasevafacenforma:
init <'A', 'B', 'C', 'D'>

ceeacearecaefecttransmiterealistei'A','B','C','D'caununicparametru. Operatorul de literalizare caracter ! se aplic unui singur caracter, efectul fiind de a trata acel caracter ca un caracter obinuit (fr al interpreta). Se utilizeaz mpreun cu caractere care au semnificaii speciale n macroinstruciuni. S considermomacroinstruciunecaredefinetemesajedeeroare:
err_gen macro N, X err_&N db 'Eroare &N : &X', 0 endm

Oinvocaredeforma:
err_gen 23, <Parametru ilegal>

sevaexpandan:
err_23 db 'Eroare 23 : Parametru ilegal', 0

Dac dorim ns s generm un mesaj de forma 'par_1 > par_2', intrm n conflict cu semnificaia special a caracterului '>', care intr n componena operatoruluideliteralizareir.Soluiaestesfolosimoperatorul!isscriem:

162 Capitolul5
err_gen 24, <par_1 !> par_2>

ceeacevageneramesajulcorect:
err_24 24, 'Eroare 24 : par_1 > par_2', 0

5.6.3Operatoruldeevaluareexpresie(%)
Acest operator se aplic unei expresii oarecare, efectul fiind evaluarea acelei expresii. Dintrun anumit punct de vedere, operatorul % este inversul operatorilordeliteralizare.Sconsidermmacroinstruciunea:
def macro a, b db '&a', 0 db '&b', 0 endm

caregenereazdate.Oinvocaredeforma:
alfa equ 100 beta equ 200 def <alfa + beta>, %(alfa + beta)

produceliniiledeprogram:
db 'alfa + beta', 0 db '300', 0

n invocarea lui def, primul parametru este literalizat, iar al doilea evaluat, ceea ceexplictextulgenerat.

5.7Invocarerecursivdemacroinstruciuni
O macroinstruciune se poate invoca recursiv, adic pe ea nsi. Ca i la procedurile recursive, cel mai important lucru este oprirea recursivitii, care se poate face cu directivele de asamblare condiionat IFB sau IFNB. S considerm o macroinstruciune de salvare de registre n stiv. Vrem ca aceasta s permit un numr variabil de parametri. Soluia recursiv este s fixm un numr maximal de parametri i s testm explicit dac primul parametruestevid:
push_all_1 macro r1, r2, r3, r4, r5, r6 ifnb r1 push r1 push_all_1 r2, r3, r4, r5, r6 endif endm

Dac primul parametru formal nu este vid, se genereaz instruciunea PUSH i apoi se invoc aceeai macroinstruciune, cu restul de parametri. Aceast

Programarenlimbajdeasamblare 163 form poate fi folosit cu un numr oarecare de registre de la 1 la 6, de exemplu:


push_all_1 ax, bx, cx, dx

Oaltvariantestecearepetitiv:
push_all_2 macro X irp y, <x> push y endm endm

Invocareanecesitnsoperatoruldeliteralizare:
push_all_2 <ax, bx, cx, dx>

5.8Definireamacroinstruciunilornmacroinstruciuni
Se poate spune c macroinstruciunile automatizeaz oarecum procesul de definire a datelor i a instruciunilor. Mai mult dect att, chiar definirea macroinstruciunilorsepoatefaceprinintermediulaltormacroinstruciuni. S considerm un asemenea caz. n cazul procesorului 8086, instruciunile de deplasare i de rotaie cu un numr de bii mai mic sau egal cu 3, se execut mai rapid ca secvene de rotaii de cte un bit, n comparaie cu instruciunile care utilizeaz registrul CL. Dorim s scriem cte o macroinstruciune pentru cele 8 instruciuni de deplasare i rotaie, fiecare cu doi parametri, sursa i numrul de bii, care s se expandeze n secvena optimcatimpdeexecuie. Deexemplu,oinvocaredeforma:
m_shr ax, 5

sseexpandezensecvena:
mov cl, 5 shr ax, cl

iaroinvocaredeforma:
m_shr bx, 3

nsecvena:
shr bx, 1 shr bx, 1 shr bx, 1

Dorim ca generarea macroinstruciunilor (avnd numele de forma m_xxx, undexxxestenumeleinstruciuniicorespunztoare)sfiefcutautomat.

164 Capitolul5
ncepem prin a defini o macroinstruciune care primete (n parametrul formal operation) numele instruciunii respective i genereaz macroinstruciunea corespunztoare:
gen macro operation m_&operation macro operand, nr if nr lt 4 rept nr operation operand, 1 endm else mov cl, nr operation operand, cl endif endm endm

Laoinvocaredeforma:
gen shl

se va genera automat macroinstruciunea m_shl, conform definiiei echivalente:


m_shl macro operand, nr if nr lt 4 rept nr shl operand, 1 endm else mov cl, nr shl operand, cl endif endm

adic exact ce neam propus. Generm acum toate cele 8 macroinstruciuni, observnd c numele operaiilor (instruciunilor) respective se compun din secvenele RO, RC, SH, SA, la care se adaug sufixele R sau L. Exploatm acestfaptprindoumacroinstruciunirepetitive:
irp X, <RO, RC, SH, SA> irp Y, <R, L> gen X&&Y endm endm

Aceast secven va defini macroinstruciunile m_ror, m_rol, m_rcr, m_rcl, m_shr,m_shl,m_sarim_sal.

5.9Tehniciavansatedeutilizareamacroinstruciunilor
5.9.1Macroinstruciunicareseautotransform(seredefinesc)nproceduri

Programarenlimbajdeasamblare 165 Un dezavantaj al utilizrii intensive a macroinstruciunilor este consumul de memorie: dac invocm de 100 de ori o macroinstruciune, textul respectiv se va duplica de 100 de ori. Acest lucru nu deranjeaz n situaia n care textul respectiv trebuia oricum scris (de exemplu, n secvenele de apel ale procedurilor). Sunt ns situaii n care corpul macroinstruciunii reprezint o secven oarecare de instruciuni. Dorim ca invocrile repetate s nu conduc la repetarea corpului macroinstruciunii, ci la apeluri ale unei proceduri, acest lucrufiindtransparentpentruutilizator.Soluiaesteurmtoarea:
macsub macro local gata call subr jmp gata subr proc near ; ; Corpul macroinstructiunii ; ret subr endp gata: macsub macro call subr endm endm

Se nscrie corpul macroinstruciunii ntro procedur cu numele subr i se genereaz un apel al acestei proceduri, urmat de un salt peste procedura respectiv. Se redefinete apoi macroinstruciunea macsub, n aa fel nct s segenerezedoarapelurialeproceduriisubr. Laprimainvocareamacroinstruciuniimacsub,sevageneratextul:
call subr jmp ??0000 subr proc near ; ; Corp macroinstructiune ; ret subr endp ??0000:

Laurmtoareleinvocri,sevageneradoartextul:
call subr

Acest exemplu arat c ntro macroinstruciune putem chiar redefini aceeai macroinstruciune.

5.9.2Macroinstruciunicaregenereazattdate,cticod

166 Capitolul5
n descrierea interfeei cu sistemul DOS, realizat prin fiierul header io.h (vezi 2.7 i Anexa A), sa prezentat macroinstruciunea putsi, care permite afiarea (la momentul execuiei) a unor iruri constante imediate, fr a le definiexplicitntrunsegmentdedate.Puteamdeciscrie:
putsi <'Acesta este un mesaj la consola'>

fr s ne punem problema unde se memoreaz irul constant respectiv. Pentru afiarea propriuzis, utilizm procedura puts_proc din fiierul io.asm (vezi Anexa B), care primete n DS:SI adresa de memorie a unui ir terminat cu0. Problema care se pune este c definiia irului n memorie trebuie fcut chiar n macroinstruciunea putsi. Vom beneficia de faptul c directivele simplificate de definire a segmentelor (n spe .code i .data) pot alterna n cuprinsul unui program.Definiiamacroinstruciuniiesteurmtoarea:
putsi macro X local string .data string db X, 0 .code push si lea si, string call puts_proc pop si endm

Se comut pe segmentul de date i se definete irul transmis prin parametrul formal X, la care se adaug terminatorul 0. Identificatorul string se declar local, pentru a nu fi duplicat n apeluri succesive. Se comut apoi pe segmentul de cod i se genereaz secvena de apel a procedurii puts_proc, cu salvarea irestaurarearegistruluiSI.Unapeldeforma:
putsi <'Acesta este un mesaj la consola'>

sevaexpandantrosecvendeforma:

.data ??0001 db 'Acesta este un mesaj la consola', 0 .code push si lea si, ??0001 call puts_proc pop si

n mod similar, n 2.7 a fost introdus o macroinstruciune geti care citete un ntreg cu semn pe 16 bii de la consol, ntorcnd valoarea citit n registrul

Programarenlimbajdeasamblare 167 AX. Problema care apare este c de la consol se pot citi date numai la nivel de caractere. Presupunem c dispunem de o procedur gets_proc care citete un numr limitat de caractere de la consol. Parametrii acestei proceduri sunt adresa (near) unde se depun caracterele citite, transmis prin SI i numrul maxim de caractere citite, transmis n CX. Citirea nceteaz fie la apsarea pe Enter, fie la atingerea numrului maxim de caractere, iar dup ultimul caracter se depune terminatorul 0. Dac CX = 0, atunci se poate introduce un numr nelimitat de caractere. Dup ce sau citit caracterele care formeaz numrul, acestea trebuie convertite de la ir de caractere ASCII la un ntreg cu semn. Aceast conversie se realizeaz cu o procedur atoi_proc, care primete n SI adresa irului de caractereintoarcevaloareacalculatnAX. Macroinstruciuneagetisedefineteastfel:
geti macro local string .data buffer db 8 dup (0) .code push si lea si, buf mov cx, 7 call gets_proc lea si, buf call atoi_proc pop si endm

Capitolul6
Tehnicideprogramarenlimbajde asamblare
Acest capitol este dedicat tehnicilor de programare n limbaj de asamblare, adic modalitilor de proiectare i implementare a modulelor de program. Dei codul main rezultat este mai scurt, programele surs scrise n ASM tind s aib dimensiuni mari. De aceea, este esenial o abordare sistematic i ordonat a dezvoltrii programelor. Utilizarea disciplinat a procedurilor, a mecanismelor standard de transfer de parametri i a macroinstruciunilor contribuie esenial la obinerea de programe clare, eficiente i uor de ntreinut. n esen, specificarea modulelor de program ASM nu difer de cea specific limbajelor de nivel nalt, n sensul c se pornete de la o descriere abstract a algoritmului care trebuie implementat. O problem specific este asignarea variabilelor. Dac ntrun limbaj de nivel nalt acest lucru nu creeaz probleme (introducem cte variabile dorim, fr a ne pune problema spaiului alocat), n ASMtrebuiesasignmexplicitvariabile. Prima modalitate este s asignm ct mai multe variabile n registrele procesorului. Cum numrul acestora este limitat, vom fi nevoii s asignm variabile i n segmente de date (statice) sau n stiv. Pentru a nu crete numrul variabilelor peste o limit rezonabil, este esenial ca modulele de program s implementeze subprobleme de dimensiuni adecvate (nu foarte mari), ceea ce implic o descompunere a problemei iniiale n subprobleme binespecificate.

6.1Deciziasimplideciziacompus.Evaluareacondiiilor logice
Majoritatea operaiilor de baz din programarea structurat (decizia, selecia, ciclurile cu test la partea inferioar i superioar) implic n mod inerent evaluarea unor condiii logice. n ASM, aceste condiii sunt n general detipcomparaientrevalorinumerice.

169 Capitolul6
Deciziasimpl,codificatnpseudocodprin:
if (conditie) Ramura_if

seimplementeaznASMprinablonul:
Evalueaza conditie Salt conditionat (pe conditie falsa) la eticheta_1 ; Ramura_if eticheta_1:

Deciziacompus,codificatnpseudocodprin:
if (conditie) Ramura_if else Ramura_else

seimplementeazdupablonul:
Evalueaza conditie Salt conditionat (pe conditie falsa) la et_1 ; Ramura_if jmp et_2 et_1: ; Ramura_else et_2:

Evaluarea condiiilor logice simple se realizeaz prin instruciuni de comparaie, aritmetice etc., care poziioneaz bistabilii de condiie. De exemplu,secvenapseudocod:
if (ax < bx) ; Ramura_if else ; Ramura_else

seimplementeazprin:
cmp ax, bx jge et1: ; Ramura_if jmp et2 et1: ; Ramura_else et2:

Evaluarea condiiilor complexe se abordeaz n manier ordonat. Primul caz de baz este cel n care subcondiiile sunt conectate prin operatorul logic AND.Astfel,sconsidermocondiielogicdeforma:
C = C1 AND C2 AND C3 AND ... AND Cn

Programarenlimbajdeasamblare 170 ideciziacompus:


if (C) ; Ramura_if else ; Ramura_else

Implementeareaesteurmtoarea:
Evalueaza C1 Salt conditionat (pe conditie falsa) la et_1 Evalueaza C2 Salt conditionat (pe conditie falsa) la et_1 .......................... Evalueaza Cn Salt conditionat (pe conditie falsa) la et_1 ; ; Ramura_if ; jmp et_2 et_1: ; ; Ramura_else ; et_2:

Sconsiderm,deexemplu,secvenapseudocod:
if (car >= '0' AND car <= '9') { sir [i] = car - '0'; i = i + 1; }

n care presupunem c variabila car se afl n AL, iar indicele i n registrul BX. Implementareaesteurmtoarea:
cmp jb cmp ja sub mov inc et_1: al, '0' et_1 al, '9' et_1 al, '0' sir [bx], al bx ; ; ; ; ; ; ; Evaluare al >= '0' Salt pe cond. falsa (al < '0') Evaluare al <= '9' Salt pe cond. falsa (al > '9') Calcul car - '0' Depunere in sir [i] Incrementare i

Al doilea caz de baz este cel n care subcondiiile sunt conectate prin operatorulOR.Sconsidermcondiiacompus:
C = C1 OR C2 OR C3 OR ... OR Cn

iaceeaiformdedeciziecompus:
if (C) ; Ramura_if else

171 Capitolul6
; Ramura_else

Implementareaesteurmtoarea:
Evalueaza C1 Salt conditionat (pe conditie adevarata) la et_1 Evalueaza C2 Salt conditionat (pe conditie adevarata) la et_1 .......................... Evalueaza Cn Salt conditionat (pe conditie adevarata) la et_1 ; ; Ramura_else ; jmp et_2 et_1: ; ; Ramura_if ; et_2:

Cele dou abloane de implementare pentru condiii compuse de tip AND i OR se bazeaz pe proprietile elementare ale operaiilor logice respective. Astfel, la operaia AND, e suficient ca un singur operand (o subcondiie) s fie fals, pentru ca ntreaga condiie s fie fals. Similar, la operaia OR, e suficient ca un singur operand s fie adevrat, pentru ca ntreaga condiie s fieadevrat. A treia schem de dezvoltare se refer la implementarea condiiilor negate. O secvenpseudocoddeforma:
if (NOT conditie) ; Ramura_if else ; Ramura_else

se implementeaz la fel cu schema ifelse obinuit, dar cu inversarea saltului condiionat:


Evalueaza conditie Salt conditionat (pe conditie adevarata) la et_1 ; ; Ramura_if ; jmp et_2 et_1: ; ; Ramura_else ; et_2:

Programarenlimbajdeasamblare 172 Cu aceste trei operaii de baz (AND, OR, NOT), putem acum evalua orice tip decondiielogic.Sconsidermsecvenapseudocod:
if ((C1 AND C2) OR C3) ; Ramura_if else ; Ramura_else

Considerm subcondiiile C1 AND C2 i C3 i aplicm pentru nceput ablonul delaoperaiaOR:


Evalueaza (C1 AND C2) Salt conditionat (pe conditie adevarata) la et_1 et_3: Evalueaza (C3) Salt conditionat (pe conditie adevarata) la et_1 ; ; Ramura_else ; jmp et_2 et_1: ; ; Ramura_if ; et_2:

Detaliem acum evaluarea subcondiiei (C1 AND C2), observnd c se sare la eticheta et_1 dac ambele subcondiii C1 i C2 sunt adevrate altfel se sare laetichetaet_3:
Evalueaza C1 Salt conditionat (pe conditie falsa) la et_3 Evalueaza C2 Salt conditionat (pe conditie adevarata) la et_1 et_3: Evalueaza (C3) Salt conditionat (pe conditie adevarata) la et_1 ; ; Ramura_else ; jmp et_2 et_1: ; ; Ramura_if ; et_2:

Dup aceste modele, se pot evalua pas cu pas condiii orict de complicate. abloanele de evaluare se utilizeaz i la celelalte operaii din programarea structurat.

6.2Cicluricutestlaparteasuperioariinferioar

173 Capitolul6
Ciclulcutestlaparteasuperioar,descrisnpseudocodprin:
while (conditie) ; Bloc

seimplementeazdupablonul:
et_1: Evalueaza conditie Salt conditionat (pe conditie falsa) la et_2 ; ; ; Bloc jmp et_1

SconsidermsecvenaurmtoarenlimbajulC:
while (*s >= '0' && *s <= '9') { n = 10 * n + *s - '0'; s++; }

unde s este un pointer la char, iar n un ntreg. Aceast secven este tipic pentru conversia ASCIIntreg. Presupunem variabila n asignat n AX, iar pointerul s asignat (ca adres near) n registrul SI i aplicm ablonul de implementare:
et_1: Evalueaza ( [SI] >= '0') Salt pe conditie falsa la et_2 Evalueaza ( [SI] <= '9') Salt pe conditie falsa la et_2 AX = AX * 10 + [SI] - '0' SI = SI + 1 jmp et_1 et_2:

n codificarea propriuzis, se va ncrca [si] n registrul al pentru o operare mai eficient:


mov bx, 10 et_1: mov xor cmp jb cmp ja mul sub add inc jmp cl, [si] ch, ch dl, '0' et_2 dl, '0' et_2 bx cl, '0' ax, cx si et_1 ; ; ; ; ; ; ; ; ; CX <-- caracterul de la adresa SI Prima subconditie Salt pe conditie falsa A doua subconditie Salt pe conditie falsa n = n * 10 *s - '0' Valoare finala n s++

Programarenlimbajdeasamblare 174 Ciclurilecutestlaparteainferioar,descrisnpseudocodprinunadinformele:


do ; Bloc while (conditie) repeat ; Bloc until (conditie)

seimplementeazdupabloanele:
et: ; Bloc Evalueaza conditie Salt pe conditie adevarata la et et: ; Bloc Evalueaza conditie Salt pe conditie falsa la et

S considerm un algoritm tipic pentru conversia ntregASCII, descris n limbajulC:


do { *s++ = n % 10 + '0'; n = n/10; } while (n != 0); *s = 0;

Prin mpriri succesive la 10 se genereaz cifrele corespunztoare ntregului n i se depun n irul de caractere s (cifrele rezult n ordine invers). Implementarea este urmtoarea (considerm n memorat n registrul AX, iar pointerulnnregistrulindexDI):
mov et: xor div add mov inc test jnz mov dx, dx bx dl, '0' [di], dl di ax, ax et byte ptr [di], 0 ; ; ; ; ; ; ; ; Deimpartit = DX:AX AX = n / 10, DX (DL) = n % 10 n % 10 + '0' Depunere in *s si apoi incrementare s Compara n cu 0 Reluare ciclu *s = 0 bx, 10

Un caz particular de ciclu cu test la partea superioar este ciclul cu contor ascendent,descrisnpseudocodprin:
for (contor = vi to vf step pas) ; Bloc

n care se consider c pas este o valoare strict pozitiv. Dac specificaia pasului lipsete, se consider implicit pasul 1. Aceast descriere se poate detaliantruncicludetipwhileioiniializare:
contor = vi; while (contor <= vf) { ; Bloc contor = contor + pas; }

175 Capitolul6
ceeacearatcsepoateaplicaablonuldeimplementaredelaciclulwhile. Ciclulcucontordescendent,descrisnpseudocodprin:
for (contor = vi downto vf step pas) ; Bloc

n care, de asemenea, se consider c pas este pozitiv i implicit 1. i aceast formsepoatedetalian:


contor = vi; while (contor >= vf) { ; Bloc contor = contor - pas; }

S considerm, de exemplu, o secven tipic de translatare la dreapta cu o poziieaelementelorunuitabloudentregi:


for (i = 99 downto 1) TAB [i] = TAB [i-1];

Asignm variabila i la registrul SI. Trebuie observat c indicii variaz dup elementele tabloului, dar adresele variaz cu cte 2 octei la fiecare element. Pentru o implementare ordonat, vom varia variabila indice SI exact ca n specificarea algoritmului i o vom ajusta temporar prin nmulire cu 2 naintea accesriielementelortabloului.Detaliereacicluluieste:
i = 99; et_1: Evalueaza ( i >= 1) Salt pe conditie falsa la et_2 TAB [i] = TAB [i-1]; i = i - 1; et_2:

Dupaceastdetaliere,implementareadevinederutin:
mov di, 99 et_1: cmp di, 1 jl et_2 shl di, 1 mov ax, TAB[si] mov TAB[si-2], ax shr di, 1 dec di et_2: ; i = 99; ; ; ; ; ; ; ; Evalueaza (i >= 1) Salt pe conditie falsa (i < 1) Temporar, DI <-- 2*DI TAB [i] TAB [i-1] Refacere DI i = i - 1

Secvena de mai sus ar putea fi implementat i prin instruciuni specifice irurilor de cuvinte (se presupune c registrele DS i ES indic segmentul n careestememorattabloulTAB):

Programarenlimbajdeasamblare 176
lea lea std mov rep si, TAB [98*2] di, TAB [99*2] cx, 99 movsw ; ; ; ; ; Sursa initiala Destinatie initiala Sens descendent Numar iteratii Transfer

O alt form posibil, care permite generalizri interesante este copierea la niveldeoctet:
lea lea std mov rep si, TAB [98*2 + 1] ; incepem de la di, TAB [99*2 + 1] ; ultimul octet cx, 99*2 movsb ; Numar de octeti ; Copiere

n general, prelucrarea tablourilor de tip oarecare presupune nmulirea indicilor de acces cu numrul de octei ai tipului de baz al tabloului. n acest sens, iniializrile registrelor SI i DI din ultima secven se pot generaliza astfel:
lea si, TAB [98 * (TYPE TAB) + (TYPE TAB - 1)] lea di, TAB [99 * (TYPE TAB) + (TYPE TAB - 1)]

Dacsecvenadecopierepropriuzissenlocuietecu:
mov cx, 99 * (TYPE TAB) rep movsb

atunci se obine o secven care implementeaz algoritmul dat, indiferent de tipultabloului.Sconsidermuntabloudestructuridetipul:


MY_STRUC struc n dw ? text db 10 dup (0) ENDS

idefinimuntabloude20destructuri:
.data tab MY_REC 20 dup (< , >)

Secvenadetranslataresepoatescrie:
lea lea std mov rep si, tab [(LENGTH tab - 1) * (TYPE MY_REC) - 1] di, tab [(LENGTH tab ) * (TYPE MY_REC) - 1] cx, (LENGTH tab - 1) * (TYPE MY_REC) movsb

prin care se poziioneaz DI (destinaia) pe ultimul octet al ultimei nregistrri din tablou, iar SI (sursa) pe ultimul octet al penultimului element din tablou. Numrul de iteraii la nivel de elemente este numrul de elemente al tabloului, micorat cu o unitate la nivel de octei, se nmulete aceast valoare cu dimensiuneaunuielement.

177 Capitolul6
O alt form posibil de scriere exploateaz legtura dintre operatorii LENGTH, TYPEiSIZE.Deexemplu,iniializareacontoruluiCXsarmaiputeascrie:
mov cx, SIZE tab - TYPE tab

ncazurilencareciclulcucontorsepoatedescrieprin:
for (contor = n downto 1) ; Bloc

sau atunci cnd se repet de n ori o anumit operaie, iar valoarea curent a contoruluinuconteaz,ciclulsepoateimplementaprininstruciuneaLOOP:
mov cx, n et: ; Bloc loop et

S considerm o secven de determinare a maximului i a minimului unui tabloudentregicusemn,definitprin:


.data TABLOU n val_max val_min i_max i_min dw dw dw dw dw dw 100 dup(?) ($-TABLOU)/2 ? ? ? ?

Se dorete determinarea att a valorilor maxime i minime, ct i a indicilor pe careaparacesteelemente. Secvenasepoatedescrienpseudocodprin:


val_max = TABLOU [0]; val_min = TABLOU [0]; i_max = 0; i_min = 0; for (i = 1 to n-1) { if (TABLOU [i] > val_max) { val_max = TABLOU [i]; i_max = i; } else if (TABLOU [i] < val_min) { val_min = TABLOU [i]; i_min = i; } }

Pentru implementare, vom presupune c adresa elementului TABLOU[i] este alocat n registrul BX. Se va incrementa direct aceast adres, iar ciclul va fi implementat printro instruciune loop. Indicele elementului curent se obine

Programarenlimbajdeasamblare 178 printro diferen ntre adresa curent (BX) i adresa de nceput a tabloului (SI)iomprirela2.
.code lea bx, TABLOU mov si, bx aici_1: mov cx, n dec cx aici_2: mov mov mov mov mov add et_1: mov ax, [bx] cmp ax, val_max jle et_2 mov val_max, ax push bx sub bx, si shr bx, 1 ; / 2 mov i_max, bx pop bx et_2: cmp ax, val_min jge et_3 mov val_min, ax push bx sub bx, si shr bx, 1 mov i_min, bx pop bx et_3: add bx, 2 loop et_1 ; Adresa elementului urmator ; Ciclu dupa CX ; ; ; ; Evalueaza (TABLOU [i] < val_min) Salt pe conditie negata val_min = TABLOU [i] Similar ; ; ; ; ; ; AX <-- TABLOU [i] Evalueaza (TABLOU [i] > val_max) Salt pe conditie negata val_max = TABLOU [i] Salvare adresa curenta Adr. curenta - adr. de inceput ax, [bx] val_max, ax val_min, ax i_max, 0 i_min, 0 bx, 2 ; ; ; ; ; val_max = TABLOU [0] val_min = TABLOU [0] i_max = 0 i_min = 0 Adresa elementului TABLOU [1] ; Sunt n-1 iteratii ; Adresa elementului TABLOU [0] ; Copiata si n SI

; = indicele i_max ; Refacere adresa curenta

Se observ c implementarea ciclului prin instruciunea LOOP complic determinarea indicelui elementului curent. Dac sar fi implementat un ciclu ascendentobinuit,nlocuindsecvenadintreeticheteleaici_1iaici_2prin:
aici_1: mov cx, 1 cmp cx, n jl et_4 aici_2:

iarsecvenadedupetichetaet_3prin:
et_3: add bx, 2 inc cx

179 Capitolul6
jmp et_1 et_4:

atunci, la fiecare iteraie, indicele elementului curent ar fi fost disponibil n registrul CX, iar secvenele de determinare a indicilor i_max i i_min sar fi reduslasimpletransferurideforma:
mov i_min, cx

Exemplul de mai sus arat c implementarea ciclurilor cu contor prin instruciunea LOOP, aparent mai simpl, poate conduce la complicaii n interiorulciclului. Exist i cicluri cu mai multe puncte de ieire (o ieire normal i una sau mai multe ieiri forate), ca n secvena pseudocod urmtoare, n care prin break samarcatieireaforatdinciclu:
while (conditie_1) { ; Bloc_1 if (conditie_2) break; ; Bloc_2 }

O asemenea situaie se implementeaz combinnd abloanele de la while i if: et_1:


Evalueaza (conditie_1) Salt pe conditie falsa la et_2 ; Bloc_1 Evalueaza (conditie_2) Salt pe conditie adevarata la et_2 ; Bloc_2 jmp et_1 et_2:

6.3Selecia.Tabeledesaltsaudeapeldeproceduri
Operaiadeseleciesedescrienpseudocodprin:
selecteaza (c) dintre { c1: Bloc_1; c2: Bloc_2; ........... cn: Bloc_n; [default: Bloc_d;] }

n care c1, c2, ..., cn sunt aanumitele cazuri (case). Acestea sunt, de fapt, valori de acelai tip cu variabila c. Cazul default corespunde situaiei n care

Programarenlimbajdeasamblare 180 variabila c nu are nici una din valorile c1, c2, ..., cn i este opional. Blocurile deinstruciuniBloc_1,Bloc_2,...,Bloc_npotfiivide. Implementarea natural a seleciei pornete de la observaia c o asemenea operaieesteechivalentcuosuccesiunededecizii,dupcumurmeaz:
if (c = c1) ; Bloc_1 else if (c = c2) ; Bloc_2 ................ else if (c = cn) ; Bloc_n else ; Bloc_d

Se pot aplica acum abloanele de implementare de la operaia de decizie, ceea ce nseamn comparaii succesive i salturi condiionate. Aceast soluie de implementare devine incomod atunci cnd numrul cazurilor este mare. O alt soluie de implementare, mult mai eficient, utilizeaz tabele de salt sau de apel de proceduri. S presupunem c blocurile de instruciuni sunt organizatenfelulurmtor:
et_1: ; Bloc_1 jmp et et_2: ; Bloc_2 jmp et ............... et_n: ; Bloc_n jmp et et_d: ; Bloc_d et:

deciieireadinoperaiadeseleciesefacepelaetichetaet. Ideea soluiei de implementare este definirea unei tabele de salt, iniializat cu punctele de intrare n blocurile de instruciuni (deci cu adresele etichetelor et_i) i calculul automat al adresei corespunztoare de salt, pe baza cutrii valoriicurentecntruntabeldecazuriposibile. Pentru a fixa ideile, presupunem variabila c i cazurile c1,c2, ..., cn ca fiind reprezentabile pe cte un octet de asemenea, presupunem toate blocurile de instruciuni definite n acelai segment de cod registrele DS i ES indic segmentul curent de date. Variabilele n i c au semnificaiile din descrierea operaiei (variabila de selecie, respectiv numrul de cazuri posibile). Definiiacelordoutabeleeste:

181 Capitolul6
.data case db c1, c2, c3, ..., cn tabjmp dw et_1, et_2, ..., et_n c db ? n dw ?

S considerm un exemplu concret. Se citete un caracter de la tastatur i, funcie de valoarea sa, se afieaz un mesaj la consol. Considerm numrul cazurilor posibile ca fiind 4, iar constantele de selecie ca fiind caracterele 'a', 'b', 'c' i 'd'. Citirea caracterelor se execut ntro bucl din care se iese la apsareatasteiEnter.Implementareaesteurmtoarea:
.model large include io.h .stack 1024 .data case db 'a', 'b', 'c', 'd' tabjmp dw et_1, et_2, et_3, et_4 n dw 4 .code start: init_ds_es ; Initializare DS si ES iar: getc ; Citire caracter in AL cmp al, cr ; Este Enter ? je gata ; Daca da, oprire lea di, case ; Adresa tabela de cazuri mov cx, n ; Numar de cazuri explicite cld ; Directie ascendenta repne scasb ; Cautare caz (AL) in tabela jne et_d ; Daca ZF = 0, inseamna ca nu s-a ; identificat nici un caz explicit ; deci este cazul default dec di ; S-a gasit un caz explicit ; DI este pozitionat pe octetul ; urmator, asa ca il decrementam lea bx, case ; Adresa tabela de cazuri sub di, bx ; Diferenta = deplasament, in ; gama: 0 ... n-1 shl di, 1 ; inmultire cu 2 (adrese pe word) jmp tabjmp [di] ; Salt indirect la cazul respectiv gata: exit_dos ; ; Blocurile de instructiuni ; care trateaza ; cazurile explicite si implicite ; et_1: putsi <cr, lf, 'Cazul 1 (a)', cr, lf> jmp et et_2: putsi <cr, lf, 'Cazul 2 (b)', cr, lf> jmp et

Programarenlimbajdeasamblare 182
et_3: putsi <cr, lf, 'Cazul 3 (c)', cr, lf> jmp et et_4: putsi <cr, lf, 'Cazul 4 (d)', cr, lf> jmp et et_d: putsi <cr, lf, 'Cazul default', cr, lf> et: ; ; Punct de iesire din ; operatia de selectie ; jmp iar end start

Cutarea n tabela case se face prin instruciuni cu iruri de caractere, dup modelul standard descris la aceste instruciuni. Din adresa elementului identificat n tabel se calculeaz indicele acestuia (de la 0 la n1) i, prin nmulire cu 2, poziia corespunztoare din tabela de adrese de salt. Se executapoiunsaltindirectintrasegment. Altevarianteposibiledeimplementaresunt: cazurile memorate pe mai mult de un octet se definete tabela case n mod corespunztor, i se execut o secven de cutare explicit, dup modelul:
for (i = 0 to n-1) if (case [i] = c) break; if (i < n) jmp tabjmp [i] else jmp et_d

blocurile asociate cazurilor sunt n segmente de cod diferite se definete tabela de salt cu adrese de tip far, iar etichetele et_i i et_d se definesc cudirectivaLABELiatributulFAR blocurile asociate cazurilor sunt implementate ca proceduri se definete tabela de adrese iniializat cu numele procedurilor respective i se nlocuiete instruciunea de salt indirect cu una de apel indirect de procedur punctul de ieire din operaia de selecie va fi cel imediat urmtorapeluluiindirectdeprocedur.

6.4Transferulparametrilorctreproceduri
Proiectarea ordonat i sistematic a procedurilor este un punct cheie n dezvoltarea unui sistem de programe n limbaj de asamblare. Problemele de bazcaretrebuieurmritesunt: transferulparametrilor

183 Capitolul6
ntoarcerearezultatelor zonededatepropriiprocedurilor controlulstivei recursivitatea proceduricunumrvariabildeparametri. Pentru fiecare din aceste probleme, exist tehnici sistematice de abordare, care vorfiprezentatencontinuare. Prima problem se refer la transferul parametrilor ctre proceduri. Dac n limbajele de nivel nalt acest lucru este impus de sintaxa limbajului (se definete o list de parametri), n limbaj de asamblare exist multiple posibiliti de transfer. Aceasta este, de altfel, i cauza pentru care o proiectare nesistematic a procedurilor, poate conduce la programe greu de citit i neles, predispuse laeroriifoartegreudentreinut. Pe de alt parte, o proiectare ngrijit a procedurilor, combinat eventual cu macroinstruciuni adecvate, care respect tehnicile standard de transmitere a parametrilor, contribuie esenial la dezvoltarea unor programe uor de neles i de ntreinut, asemntoare din acest punct de vedere programelornlimbajedenivelnalt.

6.4.1Tipuridetransfer(prinvaloaresauprinreferin)
O prim chestiune care trebuie decis n proiectarea unei proceduri este tipul detransferalparametrilor.Sepotutilizadouasemeneatipuri: transferprinvaloare,careimplictransmitereaconinutuluiuneivariabile transfer prin referin, care implic transmiterea adresei de memorie a uneivariabile. Alegerea ntre aceste dou tipuri de transfer se poate face dup urmtoarele criterii: dac variabila care trebuie transmis nu este alocat n memorie, ci ntrun registru,sevaalegetransmitereaprinvaloare structurile de date de volum mare (tablouri, structuri, tablouri de structuri etc.)vorfitransmisetotdeaunaprinreferin dac procedura trebuie s modifice o variabil parametru formal, care este alocat n memorie, se va alege transferul prin referin (modificarea unui parametru formal din interiorul procedurii trebuie totui utilizat ct mai puin, deoarece este o cauz major de erori este preferabil un transferprinvaloareintoarcereavaloriimodificate). Pentru a fixa ideile, s considerm o procedur pro_add, de tip near, care adun dou numere pe 32 de bii, ntorcnd rezultatul n perechea de registre DX:AX. Datele sunt memorate n variabilele n1 i n2, iar rezultatul n variabila rez:
.data n1 dd 10000H

Programarenlimbajdeasamblare 184
n2 rez dd 20000H dd ?

S presupunem c transmitem parametrii prin registre, ceea ce nseamn c avem nevoie de 4 registre generale, de exemplu DX:AX pentru primul parametru i CX:BX pentru al doilea. Secvena de apel a procedurii este urmtoarea:
.code mov ax, word ptr n1 mov dx, word ptr n1 + 2 ; DX:AX = primul parametru mov bx, word ptr n2 mov cx, word ptr n1 + 2 ; CX:BX = al doilea parametru call near ptr pro_add mov word ptr rez, ax ; Rezultat n DX:AX mov word ptr rez + 2, dx

Procedurapro_addsedetaliazastfel:
pro_add proc near add ax, bx adc dx, cx ret pro_add endp

S considerm acum varianta transmiterii prin referin a parametrilor, n care se transmit ctre procedur adresele de tip near ale variabilelor n1 i n2, prin registreleSIiDI.Secvenadeapeleste:
lea si, n1 lea di, n2 call near ptr pro_add mov mov word ptr rez, ax ; Rezultat in DX:AX mov word ptr rez + 2, dx

Procedurasedezvoltnfelulurmtor:
pro_add proc near mov ax, [si] add ax, [di] mov dx, [si+2] adc dx, [di+2] ret pro_add endp ; ; ; ; Partea low din primul numar + partea low din al doilea Partea high din primul numar + partea high din al doilea

n esen, se vede c transmiterea prin referin implic operaii de adresareindirectninteriorulprocedurii. Un aspect important este salvarea i restaurarea registrelor implicate n transferulparametrilor,caiacelorutilizateninteriorulprocedurii.

6.4.2Transferprinregistre

185 Capitolul6
Vom trece acum la analiza modalitilor efective de transfer a parametrilor, fie ei valori sau adrese. O prim modalitate este transferul prin registrele mainii. Avantajul acestei soluii este faptul c, n procedur, parametrii actuali sunt disponibiliimediat. Pentru conservarea registrelor, acestea se salveaz n stiv nainte de apel i se refac dup revenirea din procedur. Secvena de apel este, deci, organizatdupablonul:
; ; ; ; Salvare in stiva a registrelor implicate in transfer incarcare registre cu parametrii actuali Apel de procedura Refacere registre din stiva

Dezavantajeleacesteimodalitisunt: numrul limitat de registre ale mainii e posibil s existe registre ocupate saupurisimplusfiemaimuliparametridectregistredisponibile neuniformitatea metodei nu exist o modalitate ordonat de transfer, fiecareproceduravndpropriileregulidetransfer.

6.4.3Transferprinzondedate
n aceast variant, se pregtete anterior o zon de date i se transmite ctre procedur adresa acestei zone de date. n aceast form, organizarea zonei de dateisecvenadeapelaproceduriipro_adddinparagrafulanterioreste:
.data zona n1 n2 rez .code lea call bx, zona pro_add label dword dd 10000H dd 20000H dd ?

Procedurapro_addsescrieacumnforma:
pro_add proc mov ax, add ax, mov dx, adc dx, ret pro_add endp near [bx] [bx+4] [bx+2] [bx+6] ; ; ; ; Partea low din primul numar + partea low din al doilea Partea high din primul numar + partea high din al doilea

Pentru un acces comod la zona de parametri, se recomand definirea unei structuricaresdescrieorganizareazoneidedate:


TIP_ZONA struc nr1 dd ? nr2 dd ? rez dd ?

Programarenlimbajdeasamblare 186
TIP_ZONA ends .data zona TIP_ZONA <10000, 20000, ?> .code lea bx, zona call pro_add

Procedurapro_addsescrieastfel:
pro_add proc mov ax, add ax, mov dx, near [bx].nr1 [bx].nr2 [bx].nr1+2 ; ; ; ; ; ; Partea low din primul numar + partea low din al doilea Partea high din primul numar + partea high din al doilea

adc dx, [bx+6].nr2+2 ret pro_add endp

6.4.4Transferprinstiv.Descrcareastivei
Transferul parametrilor prin stiv este cea mai important modalitate de transfer. Avantajele acestei metode sunt uniformitatea (se asigur un mecanism unic de transfer pentru toate procedurile) i compatibilitatea cu limbajele de nivel nalt (majoritatea compilatoarelor utilizeaz aceast metod). Transferul prin stiv este obligatoriu n situaia n care aplicaia conine att module n ASM,ctimodulenlimbajdenivelnalt. n principiu, transferul prin stiv const n plasarea n stiv (prin instruciuni de tip PUSH) a parametrilor, nainte de apelul procedurii. Astfel, procedura va gsi parametriinstiv,imediatdupadresaderevenire. Problemele de baz care trebuie avute n vedere la implementarea acestui tip detransfersunt: tipulprocedurii(FARsauNEAR) tipulparametrilor,nspecialalcelordetipadres(FARsauNEAR) ordineadeplasareaparametrilornstiv accesullaparametridininteriorulprocedurii descrcareastivei(dectreprogramulapelantsaudectreprocedur). Tipul procedurii, tipul parametrilor i ordinea lor sunt importante pentru calculul deplasamentelornstivipentruaccesulcorectlaparametri. Tehnica de acces standard la parametrii procedurii se bazeaz pe adresarea bazat (eventual i indexat) prin registrul BP, care presupune registrul SS ca registru implicit de segment. Accesul se realizeaz prin operaiile urmtoare, efectuatechiarlaintrareanprocedur: sesalveazBPnstiv secopiazSPnBP sesalveaznstiv(eventual)registreleutilizatedeprocedur

187 Capitolul6
seacceseazparametriiprinadresareindirectcuBP. Lancheiereaprocedurii,seexecutoperaiileurmtoare: serefacregistrelesalvate serefaceBP serevinenprogramulapelantprinRET. S considerm aceeai procedur pro_add (de data aceasta de tip FAR), implementatprinaceasttehnic.Secvenadeapelvafi:
.data n1 n2 rez .code push push push push call add mov mov word ptr n1+2 word ptr n1 word ptr n2+2 word ptr n2 far ptr pro_add sp, 8 word ptr rez, ax word ptr rez+2, dx ; Partea high la adrese mari ; Partea low la adrese mici ; Similar pentru n2 ; ; ; ; Apel Descarcare stiva Depunere rezultat dd 10000H dd 20000H dd ?

Plasarea datelor n stiv trebuie s in seama de modul de reprezentare n memorie. Astfel, numerele pe 32 de bii se plaseaz n stiv n aa fel nct la adrese mici s se gseasc partea mai puin semnificativ. De asemenea, se observ descrcarea stivei (refacerea registrului SP la valoarea dinaintea secvenei de apel), prin adunarea explicit la SP a numrului de octei care a fostplasatnstiv. Pentru a accesa corect parametrii n stiv, este bine s figurm imaginea stivei dup intrarea n procedur i salvarea registrului BP, innd cont de tipul procedurii, de numrul, tipul i ordinea parametrilor n stiv. Aceast imagine este ilustrat n Figura 6.1 (reamintim c, n reprezentarea grafic a spaiului dememorie,adreselecrescdesusnjos). Procedurapro_addsescrienfelulurmtor:
pro_add proc far push bp mov bp, sp mov ax, [bp+10] add ax, [bp+6] mov dx, [bp+12] adc dx, [bp+8] pop bp ret pro_add endp ; ; ; ; ; ; ; ; Secventa tipica de acces n1 low n2 low n1 high n2 high Refacere bp Revenire

Calculul explicit al deplasamentelor parametrilor (de tipul [bp+8], [bp+10] etc.) reprezint o surs potenial de greeli. n plus, ntreinerea procedurii este

Programarenlimbajdeasamblare 188 foarte greoaie. Dac se schimb tipul procedurii din FAR n NEAR sau dac se schimb ordinea celor doi parametri, toate liniile de program care conin deplasamentedeacestgentrebuierescrise.

Figura 6.1 Imaginea stivei la intrarea n procedura pro_add Aceste probleme se rezolv elegant prin definirea unei structuri ablon care s conin imaginea stivei, de la registrul BP n jos. Dac am figurat grafic imagineastivei,definireastructuriiablonesteimediat(veziFigura6.1):
sablon_1 struc _bp _cs_ip n2_low n2_high n1_low n1_high sablon_1 ends dw dw dw dw dw dw ? 2 dup (?) ? ? ? ? ; BP ; Adresa de revenire ; ; Parametri ; ;

Proceduraserescrieacumnforma:
pro_add proc far push bp

189 Capitolul6
mov bp, mov ax, add ax, mov dx, adc dx, pop bp ret pro_add endp sp [bp].n1_low [bp].n2_low [bp].n1_high [bp].n2_high

ceea ce este mult mai clar dect versiunea anterioar. n plus, dac se modific tipul procedurii sau ordinea parametrilor, nu trebuie modificat dect definiia structuriiablonasamblorulvacalculacorectnoiledeplasamente. n forma de mai sus, procedura pro_add corespunde unei funcii C cu prototipul:
long _pro_add (long x1, long x2);

S presupunem acum c procedura este fr tip (nu ntoarce nimic), dar n lista de parametri se transmite adresa rezultatului, ceea ce ar corespunde unui prototipCdeforma:
void _pro_add(long x1, long x2, long *adr_rez);

Dac presupunem c adresa rezultatului este de tip FAR, secvena de apel a proceduriivafi:
push ax ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Salvare temporara AX Aici incepe secventa de apel Partea high la adrese mari Partea low la adrese mici Similar pentru n2 Adresa de segment La 286 se poate direct: push SEG rez Offset Apel Descarcare stiva Aici se termina secventa de apel Refacere AX

push push push push mov push mov push call add

word ptr n1+2 word ptr n1 word ptr n2+2 word ptr n2 ax, SEG rez ax ax, OFFSET rez ax far ptr pro_add sp, 12

pop ax

Plasarea unor adrese FAR n stiv trebuie s in seama de modul de reprezentare al pointerilor de tip FAR (definii de exemplu prin directiva Define DoubleWord): la adrese mici se memoreaz offsetul, iar la adrese mari, adresa de segment. Dac este cazul, se salveaz n stiv registrele utilizate n secvenadeapel(ncazuldefa,AX).

Programarenlimbajdeasamblare 190 Structura de tip ablon de acces se rescrie, adugnd noul parametru de tip adres:
sablon_2 struc _bp _cs_ip adr_rez n2_low n2_high n1_low n1_high sablon_2 ends dw ? dw 2 dup dd dw dw dw dw ; (?); ? ; ? ; ? ; ? ; ? ; BP Adresa de revenire Adresa rezultat (FAR) Parametri

naceastvariant,procedurapro_addeste:
pro_add proc far push bp mov bp, sp push ax push bx push es les mov add mov mov adc mov bx, [bp].adr_rez ax, [bp].n1_low ax, [bp].n2_low es:[bx], ax ax, [bp].n1_high ax, [bp].n2_high es:[bx+2], ax ; Secventa tipica de acces ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

Salvari registre utilizate Pointer la rezultat Calcul parte low Depunere rezultat low Calcul parte high Depunere rezultat high Refacere registre Refacere BP Revenire

pop es pop bx pop ax pop bp ret pro_add endp

n procedur nu putem face presupuneri despre segmentul n care este definit variabila rezultat. Ca atare, pentru a o accesa, utilizm perechea de registre ES:BX, ncrcat cu adresa parametrului, preluat din stiv. Aici apare necesitatea ca datele de orice fel (n cazul de fa adresa FAR a rezultatului) s fie reprezentate n stiv n acelai fel ca n memoria de date. Dac nu am fi respectat convenia de reprezentare a adreselor FAR (offsetul la adrese mici), instruciunea LES BX nu ar fi ncrcat corect adresa n perechea de registreES:BX.AccesullavariabilarezultatesteilustratnFigura6.2. n toate exemplele de mai sus, descrcarea stivei a fost fcut de ctre programul apelant, printro instruciune ADD SP. Este posibil i varianta n care descrcarea stivei se face de ctre procedur. Acest lucru se implementeazprintroinstruciunereturndeforma:

191 Capitolul6
ret N

unde N este numrul octeilor care au fost pui pe stiv ca parametri. Evident, nacestcaznusemaiscrieinstruciuneaADDSPnprogramulapelant.

Figura 6.2 Transmiterea unei adrese FAR ca parametru Problematica transferului parametrilor prin stiv trebuie cunoscut n amnunt atunci cnd interfam module ASM cu module scrise n limbaje de nivel nalt. Este posibil ca diverse proprieti s difere de la limbaj la limbaj sau chiar de lacompilatorlacompilator. Spre exemplu, compilatoarele Borland C utilizeaz urmtoarea tehnic de transferaparametrilor: parametrii sunt evaluai i plasai n stiv n ordinea invers a listei de argumente a funciei, adic primul parametru din list este n vrful stivei,imediatdupadresaderevenire stivaestedescrcatdeprogramulapelant. nschimb,compilatoareleBorlandPascallucreazexactpedos:

Programarenlimbajdeasamblare 192 parametrii sunt plasai n stiv n ordinea din lista de argumente a procedurii (funciei), adic ultimul parametru din list este n vrful stivei,imediatdupadresaderevenire stivaestedescrcatdeprogramulapelant. ImagineastiveilaintrareantroprocedurC,respectivPascaldeforma:
void f_C (int par_a, int par_b, int par_c); procedure f_Pascal (int par_a, par_b, par_c)

esteilustratnFigura6.3.

Figura 6.3 Transferul parametrilor n C i Pascal Secveneledeapelalecelordouprocedurisarscrie:


push par_c push par_b push par_a call f_C add sp, 6 ; ; Secventa de apel ; ; pentru o functie C ;

respectiv:
push push push call par_a par_b par_c f_Pascal ; ; Secventa de apel ; pentru o procedura ; (functie) Pascal

6.5ntoarcereadatelordectreproceduri
Procedurile care ntorc valori corespund funciilor din Pascal sau funciilor cu tip nevid din C. n limbaj de asamblare, ne punem problema n sens mai larg,

193 Capitolul6
anume ce modaliti exist pentru a furniza un rezultat programului apelant (inclusivprintehnicineortodoxe).Acestemodalitisunt: a) n lista de parametri apar adresele rezultatelor sau adresa unei zone de date careconinecmpuripentrurezultate b)rezultatelesentorcprinregistre c)rezultatelesentorcnvrfulstivei. Tehnica a) a fost deja descris la transmiterea parametrilor prin zon de date sau prin stiv. Practic, n interiorul procedurii se depun explicit rezultatele la adreseleconinutenparametriiformalirespectivi. Dei aceast tehnic nu este recomandat ca model n programarea structurat, ea nu se poate evita atunci cnd rezultatele au dimensiuni mari i sunt prin natura lor gestionate prin adrese. Un exemplu clar este cel al irurilor decaracteresaualtablourilorngeneral. Mai mult dect att, compilatoarele de nivel nalt utilizeaz aceast tehnic (n mod transparent pentru utilizator) atunci cnd trebuie ntoarse tipuri de volum mare prin numele funciei. Concret, se transmite ctre funcie adresa unei zone temporare de date (ca parametru suplimentar al funciei), n care s se depunrezultatul. Tehnica b) este folosit cel mai frecvent. De obicei, se folosete registrul acumulator, eventual extins (adic AL, AX, respectiv DX:AX, dup cum rezultatulestepe1,2sau4octei). Dezavantajul acestei tehnici este limitarea la 32 de bii a tipului de date returnat. Totui, compilatoarele Borland o utilizeaz ca metod standard de returnareatipurilordedatedemaxim32debii. Tehnica c) se folosete destul de rar, fiind total nestandard. Const n plasarea rezultatelor n vrful stivei din momentul revenirii n programul apelant. Aceasta nseamn c, practic, rezultatele se suprapun n stiv peste parametrii de apel (se descarc implicit stiva) i chiar peste adresa de revenire, ceea ce face foartecomplicatscriereaprocedurii. Vom prezenta totui aceast tehnic pentru c este un exemplu de operaie complex asupra stivei. Considerm ca de obicei procedura pro_add, de tip far. Parametriiseplaseaznstivnordinean1,n2.Secvenadeapeleste:
push push push push call word ptr n1+2 word ptr n1 word ptr n2+2 word ptr n2 far ptr pro_add

pop ax mov word ptr rez, ax

; ; ; ; ; ;

in acest moment, in varful stivei se gaseste rezultatul adunarii Preia rezultat

Programarenlimbajdeasamblare 194
pop ax mov word ptr rez + 2, ax ; si descarca ; stiva

tim acum ce ar trebui s execute procedura pro_add. Pentru a vedea exact ce aciuni trebuie implementate, se pornete de la coninutul stivei n momentul intrrii n procedur i de la cum trebuie s arate stiva nainte de instruciunea de revenire (RET) din procedur. Aceste dou situaii sunt ilustrate n Figura 6.4.

Figura 6.4 ntoarcerea rezultatelor n vrful stivei Evident, procedura trebuie s construiasc imaginea stivei din momentul revenirii n programul apelant, iar secvena de apel trebuie s readuc registrulSPlavaloareainiial. Pornind de la aceste considerente, definim structuri de acces la stiv conform ablonului de la intrare, respectiv de la ieire. Pentru ablonul de intrare utilizm structurasablon_3:
sablon_3 struc _bp_3 _ip_3 _cs_3 n2_low n2_high n1_low n1_high sablon_3 ends dw dw dw dw dw dw dw ? ? ? ? ? ? ? ; ; ; ; ; ; ; BP Offset revenire Segment revenire Parametri

195 Capitolul6

Pentruablonuldeieire,definimstructurasablon_4:
sablon_4 struc _bp_4 _ip_4 _cs_4 rez_low rez_high sablon_4 ends dw dw dw dw dw dw dw ? ? ? ? ? ? ?

Cmpurile _bp_3 i _bp_4 se gsesc n aceeai poziie din memorie. Sau utilizatnumediferite,deoarecesintaxastructurilorimpuneacestlucru. Din imaginile stivei din Figura 6.4 rezult i operaiile care se execut. Dup calculul sumei, adresa de revenire va trebui deplasat cu 4 octei n jos n stiv, rezultatul se va depune dup noua poziie a adresei de revenire, se va poziiona registrul SP pe adresa de revenire i se va executa RET. Procedura pro_addseimplementeazastfel:
pro_add proc far push bp mov bp, sp push ax push dx mov ax, [bp].n1_low add ax, [bp].n2_low mov dx, [bp].n1_high adc dx, [bp].n2_high mov [bp].rez_low, ax mov [bp].rez_high, dx mov mov mov mov pop pop pop add ax, [bp]._ip_3 [bp]._ip_4, ax ax, [bp]._cs_3 [bp]._cs_4, ax dx ax bp sp, 4

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

Salvare registre folosite Calcul rezultat Depunere rezultat conform sablonului de iesire Pregatire offset adresa de revenire Pregatire segment adresa de revenire Refacere registre folosite Refacere BP Pozitionare SP pe adresa de revenire

ret pro_add endp

n unele situaii, este posibil ca zona de stiv n care se depun rezultatele s fie suprapus peste vechea zon n care se gsete adresa de revenire. n acest caz, se plaseaz nti adresa de revenire n noua poziie din stiv i apoi sedepunerezultatul.

Programarenlimbajdeasamblare 196

6.6Proceduricuzonededateproprii(variabilelocale)
n multe cazuri, nu putem aloca toate variabilele dintro procedur n registrele procesorului. n aceast situaie, procedura trebuie s utilizeze variabile locale proprii, altele dect parametrii formali i dect variabilele alocate n registre. Evident, se pune problema zonelor de memorie n care s fie alocate aceste variabilelocale. Exist trei modaliti de baz pentru aceast alocare: n segmentul de date global (.data) vizibil din toate modulele, n stiv sau ntrun segment de date propriu. Prima modalitate, care este evident, contrazice, de fapt, caracterul local al acestor variabile i nu se recomand a fi folosit. Vor fi, deci, detaliate celelalte doumetode.

6.6.1Variabilelocaledefinitenstiv
Ca i tehnica de transmitere a parametrilor prin stiv, aceast metod este standardizat, fiind de fapt o extensie a tehnicii de transfer prin stiv. Operaiilecareseexecutlaintrareanprocedursunturmtoarele: sesalveazBPnstiv se decrementeaz registrul SP cu numrul necesar de octei pentru variabilelelocale secopiazSPnBP sesalveaz(eventual)registrelefolositenprocedur se acceseaz parametrii formali i variabilele locale conform ablonului stivei. nsecvenadeieiredinprocedur,seexecuturmtoareleoperaii: serefacregistrelesalvate se incrementeaz SP cu acelai numr de octei cu care a fost incrementatnsecvenadeintrare serefaceregistrulBPdinstiv se revine n programul apelant (eventual cu descrcarea stivei de parametri. Pentru exemplificare, s considerm o procedur pro_local, de tip NEAR care are doi parametri formali de tip WORD i trei variabile locale, toate de tip word. Presupunem c stiva este descrcat de parametrii formali de ctre procedur. Conform operaiilor de mai sus, definim o structur ablon pentru accesul n stiv:
sablon struc loc_1 dw loc_2 dw loc_3 dw _bp dw _ip dw ? ? ? ? ?

197 Capitolul6
par_2 dw ? par_1 dw ? sablon ends

Schemadedezvoltareaproceduriipro_localeste:
pro_local proc near push bp sub sp, 6 mov bp, sp ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Salvare BP Spatiu pentru variabile locale Acces prin BP Acces la parametrii formali prin expresiile [bp]. par_1, [bp].par_2 Acces la variabilele locale prin expresiile [bp].loc_1, [bp].loc_2, [bp].loc_3 Refacere spatiu local Refacere BP Revenire cu descarcare

add sp, 6 pop bp ret 4 pro_local endp

Imaginea stivei dup secvena de intrare n procedur este ilustrat n Figura 6.5.

Figura 6.5 Variabile locale alocate n stiv

Programarenlimbajdeasamblare 198 Variabilele alocate n stiv au unele caracteristici care deriv din metoda de alocare: spaiuldememoriealocatnuexistdectpedurataprocedurii variabilele nu au alocate adrese fixe de memorie: adresele depind de poziiacurentastivei variabilelenuipstreazvaloareadelaunapellaaltul. Cea dea doua proprietate este mai important, deoarece exist situaii n care se dorete n mod explicit ca o variabil local si pstreze valoarea de la un apel la altul al procedurii. n acest caz, e obligatorie alocarea n segmente propriidedate,decilaadresefixe.

6.6.2Variabilelocalealocatestatic
Alocarea variabilelor n segmente proprii de date se mai numete i alocare static,deoarecevariabileleauasociateadresefixedememorie. Ca mod practic de implementare, se definete un segment de date local cu ajutorul directivei SEGMENT, ceea ce previne gruparea acestui segment cu alte segmente. Accesul la segmentul local se va realiza prin unul din registrele DS sau ES, urmnd ca cellalt registru de segment de date s fie utilizat (dac este cazul)pentruaccesullasegmentuldedatealprogramuluiapelant. S considerm aceeai procedur pro_local, de data aceasta de tip FAR, cu treivariabilelocaleidoiparametriformali.Definimsegmentullocalprin:
local_data segment loc_1 dw ? loc_2 dw ? loc_3 dw ? local_data ends

i convenim s accesm acest segment prin registrul ES. Ca atare, definiia proceduriipro_localvafincadratdedirectiveASSUMEcorespunztoare. Parametriiformalisunttransmiiprinstiv,conformablonuluideacces:
sablon struc _bp _cs_ip par_2 par_1 sablon ends dw dd dw dw ? ? ? ?

ASSUME es:local_data pro_local proc far push bp mov bp, sp push es mov es, SEG local_data ; ; DS : asa cum vine ; din programul apelant

199 Capitolul6
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; pop es pop bp ret 4 pro_local endp ASSUME es:nothing ES : pozitionat pe segmentul local Acces la parametrii formali prin expresiile [bp]. par_1, [bp].par_2 Acces la variabilele locale prin expresiile loc_1, loc_2, loc_3 sau, mai clar, es:loc_1, es:loc_2, es:loc_3

Exist situaia n care unul sau mai muli parametri formali sunt pointeri (adrese) far. n acest caz, se salveaz unul din registrele DS i ES n stiv i se ncarc pointerul respectiv ntro pereche adecvat de registre (cu instruciunileLDSsauLES). S presupunem, de exemplu, c unul din parametrii formali, descris n ablonul de acces prin par_far, indic un cuvnt care trebuie copiat n variabila local loc_1.Secvenadecopierevafi:
push ds lds bx, [bp].par_far mov ax, [bx] mov es:loc_1, ax pop ds ; ; ; ; Salvare incarcare pointer Acces Copiere in segment local

Dac unul din parametri este o adres far de procedur, se poate executa directunapelindirect,prin:
call dword ptr [bp].par_far

S considerm un exemplu n care utilizarea variabilelor locale statice este obligatorie, anume un generator simplu de numere aleatoare pe 16 bii, implementat prin procedura de tip FAR rand_asm. Procedura are ca parametru un ntreg pe 16 bii fr semn (notat generic n) i ntoarce n AX un numr aleatorfrsemnndomeniul0...n1. Metoda de generare se bazeaz pe o variabil local X, asupra creia se executoperaia: Xparteamedian(XX+C)

Programarenlimbajdeasamblare 200 unde XX este ptratul lui X (pe 32 de bii), iar C este o constant pe 32 de bii. Prin parte median se neleg biii 8...23 din cei 32 de bii ai expresiei calculate(veziFigura6.6). Dup ce sa calculat noua valoare a lui X, se ntoarce programului apelant valoarea X MOD n, deci un numr ntre 0 i n1. Toi operanzii se consider frsemn. n astfel de operaii, trebuie analizat cu atenie problema depirilor. Calculul X mod n se face printro mprire a lui X la n, unde att X, ct i n sunt pe 16 bii. Se va executa de fapt o mprire DX:AX la n, cu DX = 0, fapt care asigur evitarea depirii: cea mai mare valoare posibil a lui X (65535), mpritlaceamaimicvaloarenebanalaluin(2)nuproducedepire. Caracterul pseudoaleator al algoritmului de mai sus provine n mod esenial din faptul c variabila X i pstreaz valoarea de la un apel la altul al procedurii (vecheavaloarealuiXparticiplacalcululnoiivalori). Pentruaccesullaparametruln,seutilizeazostructurablon.

Figura 6.6 Un generator simplu de numere aleatoare Conform metodei de dezvoltare expuse mai sus, definim un segment local n care rezervm spaiu pentru variabila de tip word X i pentru constanta de tip doublewordC(ambeleiniializatecucteovaloareoarecare). Deoarece va trebui s executm o adunare pe 32 de bii, avem nevoie de acces explicit la prile low i high ale constantei C, pstrnd definiia ei ca

201 Capitolul6
variabil doubleword. Acest lucru este realizat prin operatorul THIS, cu ajutorul cruiasedefinescconstantelesimbolicec_loic_hi. Calculele vor folosi registrul AX, respectiv perechea de registre DX:AX, care este operand implicit la nmuliri i mpriri. Implementarea este urmtoarea (presupunemunfiiersurscunumelerand.asm):
; ; Fisier RAND.ASM ; .model large public rand_asm, init_asm sablon struc _bp dw ? _cs_ip dd ? n dw ? sablon ends local_data segment x dw 111 c_lo equ this word c_hi equ c_lo + 2 c dd 115321 local_data ends .code assume es:local_data rand_asm proc far push bp mov bp, sp pushf cmp [bp].n, 2 mov ax, [bp].n jb gata push es push dx mov ax, SEG local_data mov es, ax mov mul add adc mov mov mov xor div mov ax, es:x es:x ax, c_lo dx, c_hi al, ah ah, dl es:x, ax dx, dx [bp].n ax, dx ; sablon de ; de acces ; la stiva

; Variabila locala statica X ; Constanta C

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

Secventa standard de intrare Salvare bistabili Test caz banal (n = 0,1) Se intoarce chiar n Salvari registre folosite Pozitionare ES pe segmentul local Variabila X Ridicare la patrat (DX:AX) Adunare cu C Luarea partii mediane din DX:AX in AX Depunere in X Pregatire impartire impartire (0:X) la n Catul se pune in AX Refaceri

pop dx

Programarenlimbajdeasamblare 202
pop es gata: popf pop bp ret rand_asm endp ; Refacere bistabili ; ; Secventa standard ; de iesire ; ; Initializare generator ; init_rand proc far push bp mov bp, sp push es push ax mov ax, SEG local_data mov es, ax mov ax, [bp].n mov es:x, ax pop ax pop es pop bp ret init_rand endp end ; registre

; Salvari

; Copiere parametru ; in variabila X ; Refaceri

Procedura rand_asm este completat cu o rutin de iniializare a generatorului, avnd un parametru de tip word transmis prin stiv, care iniializeaz variabila X. Se folosete aceeai structur ablon pentru accesul lastiv. S considerm un exemplu de apel al acestor proceduri, pe care le presupunem definite n fiierul surs rand.asm. Dorim iniializarea cu valori aleatoare n gama 0...9999 a unui tablou de 256 de ntregi, pe care l afim, l sortm cresctor i apoi l afim din nou. Pentru afiare i sortare utilizm procedurile tipvec i bubble, dezvoltate n 2.7, pe care le presupunem definite ntrun fiier surs cu numele bubble.asm, care conine declaraii PUBLIC aleprocedurilorncauz. n programul principal (presupus n fiierul surs main.asm), cele patru proceduri se declar ca simboluri externe i se folosesc conform metodei proprii detransferalparametrilor:
; ; Fisier MAIN.ASM ; .model large include io.h extrn rand_asm: far, init_rand: far, tipvec: far, bubble: far .stack 1024 .data vector dw 256 dup (?) dim dw ($-vector)/2

203 Capitolul6
.code start: init_ds_es mov ax, 1131 push ax call init_rand add sp, 2 ; mov cx, dim ; Dimensiune vector lea bx, vector ; Adresa vector reluare: mov ax, 10000 ; Domeniu 0...9999 push ax call rand_asm add sp, 2 ; Descarcare stiva mov [bx], ax ; Depunere valoare add bx, 2 ; Actualizare adresa loop reluare ; putsi <'Vector nesortat', cr, lf> lea si, vector ; Adresa tablou mov cx, dim ; Numar de elemente call tipvec ; Afisare tablou nesortat ; lea bx, vector ; Adresa tablou mov cx, dim ; Numar de elemente call bubble ; Sortare tablou ; putsi <cr,lf,'Vector sortat', cr, lf> lea si, vector mov cx, dim call tipvec ; Afisare tablou sortat ; exit_dos ; Iesire in DOS end start ; Valoare initiala ; a generatorului ; Descarcare stiva

Secvenadedezvoltareaacesteiaplicaiieste:
> > > > tasm rand.asm tasm bubble.asm tasm main.asm tlink main rand bubble io, main

nurmacreiarezultunfiierexecutabilmain.exe. Exemplul de mai sus constituie i un model de dezvoltare modular a unei aplicaii. Se observ c o proiectare ngrijit a modulelor permite refolosirea lorndiversecontexte.

6.7Procedurirecursive
n limbaj de asamblare, nu exist restricii asupra recursivitii: orice procedur proc_a se poate apela pe ea nsi (recursivitate direct) sau poate

Programarenlimbajdeasamblare 204 apela o procedur proc_b care, la rndul ei apeleaz procedura proc_a (recursivitateindirect). n dezvoltarea unei proceduri recursive, trebuie pornit de la specificarea algoritmului recursiv. Specificarea unui asemenea algoritm pune n eviden un caz de baz (care oprete recursivitatea) i un caz general, n care se invoc acelai algoritm, aplicat altui set de date. Specificarea corect a cazului de baz i garantarea faptului c acesta este atins ntotdeauna, indiferent de setul de date de intrare primit, sunt punctelecheie ale proiectrii unui algoritm recursiv. S considerm, ca exemplu, o procedur de afiare n baza 10 a unui numr pe 16 bii fr semn. La nivelul funciilor de intrare/ieire, avem posibilitatea de a afia caractere ASCII. Dorim deci un algoritm recursiv care s genereze cifrele zecimale ale numrului, n ordinea afirii. n 2.2.5 a fost dat un algoritm nerecursiv,careproduceacifrelezecimalealenumruluinordineinvers. Algoritmulrecursivsespecificnfelulurmtor:
putu_proc (n) { daca (n < 10) afiseaza (n + '0') altfel { putu_proc (n/10) afiseaza (n MOD 10 + '0') } }

Cazul de baz este (n < 10), pentru care se face doar afiarea cifrei i revenirea n programul apelant. n Figura 6.7 sunt ilustrate apelurile recursive n cazul afiriinumrului123ivalorilesuccesivealeparametruluin.

205 Capitolul6

Figura 6.7 Apelul recursiv al procedurii putu_proc Regulilegeneraledeimplementareaprocedurilorrecursivesunt: fiecare apel al procedurii nu trebuie s afecteze datele apelurilor precedente(procedurasfiereentrant) nu se folosesc variabile locale alocate static, ci numai n stiv sau n registre parametrii se transmit prin stiv (se asigur implicit faptul c parametrii suntlocalifiecruiapel) registrele ale cror valori au semnificaie de la un apel la altul se salveaz nstiv dac procedura ntoarce valori prin registre, rezultatele intermediare trebuiememoratenstiv. Pentru implementarea procedurii putu_proc, se va utiliza funcia DOS 2, care afieaz la consol caracterul primit n registrul DL. Pentru accesul la stiv, considermstructuraablon:
sablon struc _bp dw ? _cs_ip dw ? n dw ? sablon ends

Pentruoimplementaremaieficient,rescriemalgoritmulrecursivnforma:
putu_proc (n) { daca (n < 10)

Programarenlimbajdeasamblare 206
x n altfel { putu_proc (n/10) x n MOD 10 } afiseaza x + '0' }

Alocareavariabileloresteurmtoarea: nnstiv,accesibilprinexpresia[bp].n xnregistrulDL(caresesalveaz/restaureaz) Implementareaesteurmtoarea:


putu_proc proc far push bp mov bp,sp push dx push ax push bx mov cmp mov jb mov xor div ax, [bp].n ax, 10 dl, al p_u_1 bx, 10 dx, dx bx ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Secventa standard Salvari registre folosite Test caz de baza x <-- n Salt la afisare Caz general Se calculeaza n/10 si n MOD 10 AX = n/10 DX (DL) = x = n MOD 10 Apel recursiv cu n/10 ca parametru

push ax call far ptr putu_proc p_u_1: add mov int dl, '0' ah, 2 21H

; x + '0' ; Cod functie DOS ; Afisare ; Refaceri ; registre ; Return cu descarcare

pop bx pop ax pop dx pop bp retf 2 putu_proc endp

n implementarea de mai sus, este esenial integritatea variabilei x de la un apel la altul, deci salvarea/restaurarea registrului DX. Pentru a preveni depirile, se face mprirea 32 de bii la 16 bii, deci constanta 10 se ncarc ntrun registru de 16 bii. Dup mprire, DX (de fapt DL) conine restul n MOD 10, iar AX ctul (n/10). Se pune, deci, AX n stiv i se apeleaz recursivprocedura.Duprevenire,seafieazcifradinDL.

207 Capitolul6
Putem acum dezvolta o procedur care s afieze un numr pe 16 bii cu semn,dupalgoritmul:
puti_proc (n) { daca (n < 0) { n - n afiseaza ('-') } putu_proc (n) }

Dac numrul e negativ, se complementeaz fa de 2 i se afieaz semnul '', dup care se afieaz numrul complementat. Implementarea este urmtoarea:
puti_proc proc far push bp mov bp, sp push ax push dx mov or jns mov mov int neg p_i_1: push [bp].n call far ptr putu_proc pop dx pop ax pop bp retf 2 puti_proc endp ; ; ; ; ; Pregatire parametru Apel putu_proc Refaceri registre ax, [bp].n ax, ax p_i_1 dl, '-' ah, 2 21H word ptr [bp].n ; ; ; ; ; ; ; ; ; ; Secventa standard Salvari registre Parametrul n Pozitionare bistabili Test bit de semn Afisare semn '-'

; Complementare n

; Return cu descarcare

Se observ forma direct de plasare a parametrului [bp].n n stiv, pentru apelul proceduriiputu_proc. Putemscrieacumimacroinstruciunideapeladecvate:
puti macro push call endm putu macro push call endm X X far ptr puti_proc X X far ptr putu_proc

Dup modelul procedurii putu_proc, putem scrie o procedur care s afieze la consol reprezentarea unui numr pe 16 bii fr semn ntro baz de

Programarenlimbajdeasamblare 208 numeraie dat. Baza se consider n domeniul 2...36, iar cifrele ntro baz mai mare ca 10 sunt '0'...'9', 'A', 'B' etc. Limitarea bazei la valoarea 36 deriv din aceastalegereacifrelor. Algoritmulesteurmtorul:
put_base (n, baza) { daca (baza < 2 sau baza > 36) return daca (n < baza) x n altfel { put_base (n/baza, baza) x n MOD baza } daca (x < 10) afiseaza (x + '0') altfel afiseaza (x + 'A' - 10) }

Se ncepe printrun test de corectitudine a bazei: dac aceasta nu este n domeniul admisibil, se revine imediat n programul apelant. Se execut apoi acelai algoritm recursiv ca n procedura putu_proc, nlocuind constanta 10 cu variabila baza. Afiarea cifrei curente x se face difereniat: dac este mai mic sauegalcu10,seafieazcacifrzecimalaltfel,seafieazcaliter. Pentruaccesullastiv,seutilizeazstructuraablondemaijos:
sablon struc _bp _cs_ip baza n ends dw dd dw dw ? ? ? ?

sablon

Implementarea este urmtoarea (se consider c stiva este descrcat de programulapelant):


put_base proc far push bp mov bp, sp cmp word ptr [bp].baza, 2 jb err_exit cmp word ptr [bp].baza, 36 ja err_exit ; push ax push dx mov ax, [bp].n cmp ax, [bp].baza mov dl, al jb p_b_1 ; Secventa standard ; Test baza corecta ; baza < 2 ; baza > 36 ; ; ; ; ; ; Salvari registre Test n < baza ? x <-- n Salt la afisare

209 Capitolul6
xor div ; ; ; dx, dx [bp].baza ; ; ; ; Calcul n/baza si n MOD baza AX = n/baza DX (DL) = n MOD baza

Pregatire parametri pentru apelul recursiv push push call add ax [bp].baza far ptr put_base sp, 4 ah, 2 dl, 10 p_b_2 dl, '0' p_b_3 dl, 'A' - 10 ; ; ; ; n/baza baza Apel recursiv Descarcare stiva

p_b_1: mov cmp jae add jmp p_b_2: add p_b_3: int 21H pop dx pop ax err_exit: pop bp ret put_base endp ; Afisare ; Refaceri ; registre ; Revenire ; x + 'A' - 10 ; Cod functie DOS ; x < 10 ? ; x + '0'

Deoarece toate variabilele implicate sunt fr semn, se folosesc salturi condiionatedebelowiabove. Un mic program de test (listat n continuare) citete un numr i o baz de la consol i afieaz numrul n baza dat, dup care reia procesul de citire. Dacnumrulintroduseste0,programulsetermin.
.model large include io.h .stack 1024 .code start: init_ds_es reluare: putsi <cr,lf,'Numar = '> getu or ax,ax jz exit push ax putsi <'Baza = '> getu push ax call far ptr put_base add sp, 4 jmp reluare exit:

; ; ; ; ; ; ; ; ; ; ;

Prompter Citire intreg Test oprire ? Salt la iesire Plasare n in stiva Prompter Citire intreg Plasare baza in stiva Apel Descarcare stiva Reluare

Programarenlimbajdeasamblare 210
exit_dos end start

Un caz deosebit l constituie funciile recursive, adic procedurile care ntorc valori. Trebuie acordat atenie memorrii valorilor ntoarse de apelurile recursive. S considerm o funcie recursiv care ntoarce numrul Fibonacci deordinuln,definitrecursivprin:
fib (0) = fib (1) = 1 fib (n) = fib (n-1) + fib (n-2), pentru n >= 2

Aceast funcie a fost evaluat prin iteraie n 2.4.4. Vom studia acum implementarearecursiv. Se observ c, pentru valoarea lui fib(n), sunt necesare dou apeluri recursive i salvarea rezultatului ntors de primul apel. Presupunem c parametrul n se transmite prin stiv, c procedura este de tip FAR, c ntoarce rezultatul n AX (ca numr fr semn) i c stiva este descrcat de programul apelant. ablonuldeaccesestedefinitprinstructura:
sablon struc _bp dw ? _cs_ip dd ? n dw ? sablon ends

iarimplementareaesteurmtoarea:
fib proc far ; ; Primeste in stiva numarul n ; Intoarce n AX valoarea fib (n) ; push bp mov bp, sp push bx ; Salvare registru folosit ; mov ax, [bp].n ; Preia argumentul n cmp ax, 1 ; Cazul de baza: n <= 1 jbe fib_1 ; Salt la evaluare imediata ; dec ax ; Pregatire apel push ax ; pentru n-1 call fib ; AX = fib (n-1) add sp, 2 ; Descarcare stiva mov bx, ax ; Rezultat intermediar ; mov ax, [bp].n ; Pregatire dec ax ; apel dec ax ; pentru push ax ; n-2 call fib ; AX = fib (n-2)

211 Capitolul6
add sp,2 ; Descarcare stiva ; ; in acest moment, AX = fib (n-2), BX = fib (n-1) ; add ax, bx ; Calcul fib (n) jmp fib_2 fib_1: mov ax, 1 ; Evaluare fib (0) si fib (1) fib_2: pop bx ; Restaurare pop bp ret ; Revenire fib endp

n implementarea de mai sus, este esenial salvarea i restaurarea registrului BX, care memoreaz rezultatul intermediar fib (n1). Programul de test al acesteiproceduriestelsatcaexerciiupentrucititor. Nu putem ncheia discuia despre proceduri recursive fr a vorbi despre problema clasic a turnurilor din Hanoi. n aceast problem, se consider n discuri de diametre distincte, aezate pe un suport vertical (turn surs), n ordinea descresctoare a diametrelor (vezi Figura 6.8). Se cere s se mute ntreg ansamblul pe un alt turn (destinaie), folosind un turn de manevr. Discurile se pot muta unul cte unul, cu restricia c un disc nu se poate aezadectdeasupraunuidiscdediametrumaimare.

Figura 6.8 Turnurile din Hanoi Algoritmul care rezolv aceast problem este n mod natural recursiv i se bazeaz pe observaia c, dac n = 1, adic exist un singur disc, acesta se poate muta direct pe turnul destinaie. Dac notm simbolic operaia de mutareprin:
move (n, sursa, destinatie, manevra)

Programarenlimbajdeasamblare 212 unde surs, destinaie i manevr sunt cele trei turnuri, algoritmul se implementeazprin:
move (n, sursa, destinatie, manevra) { daca (n = 1) Muta discul de pe sursa pe destinatie altfel { move (n-1, sursa, manevra, destinatie) move (1, sursa, destinatie, manevra) move (n-1, manevra, destinatie, sursa) } }

Se mut primele n1 discuri de pe turnul surs pe turnul manevr, folosind ca spaiu de lucru turnul destinaie. n acest moment, turnul surs conine un singur disc, turnul destinaie este liber, iar turnul manevr conine n1 discuri. Se mut unicul disc de pe turnul surs pe turnul destinaie. n acest moment, turnul surs este liber, turnul destinaie conine discul cu diametrul cel mai mare, iar turnul manevr conine celelalte n1 discuri. Se aplic recursiv algoritmul, mutnd n1 discuri de pe turnul manevr pe turnul destinaieifolosindturnulsurscaspaiudelucru. Pentru un n dat, se deplaseaz explicit discul cu diametrul cel mai mare, ceea ceasigurndeplinirearestricieidinenun. Implementarea algoritmului se va face prin mesaje explicite la consol, turnurile fiindcodificateprincaractere. Implementarea algoritmului, mpreun cu un program de test, este listat n continuare. Structura ablon definete ordinea de plasare a parametrilor n stiv: n, surs, destinaie, manevr, toate de tip word. Toate apelurile recursivevorutilizaaceastordine. Simularea mutrilor se face prin afiarea unui mesaj, definit n zona de date. Cmpurile sursa_asc i dest_asc sunt variabile i vor identifica (prin cte un caracter) turnurile respective. Cnd n = 1 (cazul de baz), se depun caracterele care identific turnurile n irul de caractere mesaj i se afieaz acest ir. Implementarea apelurilor recursive const n plasarea n stiv a parametrilor n ordineaprecizatiapelulprocedurii. Programul principal citete ciclic de la consol numrul n, afieaz un mesaj de identificare, pregtete parametrii n stiv i apeleaz procedura move. Bucla seopretecndseintroducevaloarea0pentrun.
.model large include io.h .stack 4096 sablon struc _bp dw ? _cs_ip dw 2 dup (?) manevra dw ?

213 Capitolul6
dest sursa n sablon ends .data mesaj sursa_asc dest_asc .code move proc far ; ; Muta n discuri de pe sursa pe dest ; folosind manevra ca zona de lucru ; push bp mov bp, sp cmp word ptr [bp].n, 1; Test caz de baza (n = 1) jne move_1 ; Salt la cazul general ; ; Mutare explicita ; mov bx, [bp].sursa ; Pregatire mesaj mov sursa_asc, bl ; Disc sursa mov bx,[bp].dest mov dest_asc,bl ; Disc destinatie puts mesaj ; Afisare mesaj pop bp retf 8 ; Revenire cu descarcare move_1: ; ; Cazul general ; mov ax, [bp].n ; Pregatire parametri dec ax ; n-1 push ax push [bp].sursa ; Sursa push [bp].manevra ; Actuala manevra devine ; destinatie push [bp].dest ; Actuala destinatie ; devine manevra call far ptr move ; Primul apel recursiv ; mov ax, 1 ; Pregatire parametri push ax ; n = 1 push [bp].sursa ; Sursa push [bp].dest ; Destinatie push [bp].manevra ; Manevra call far ptr move ; Al doilea apel recursiv ; mov ax, [bp].n ; Pregatire parametri dec ax push ax ; n-1 push [bp].manevra ; Actuala manevra devine db db db db db cr, lf, 'Muta discul de pe turnul ' ? ' pe turnul ' ? 0 dw ? dw ? dw ?

Programarenlimbajdeasamblare 214
; ; ; ; ; sursa Destinatie Actuala sursa devine manevra Al treilea apel recursiv

push push call ; pop retf move

[bp].dest [bp].sursa far ptr move bp 8 endp

; Revenire cu ; descarcare

; ; Program principal ; start: init_ds_es reluare: putsi <cr,lf,'Numar discuri: '> geti or ax, ax jz exit ; n = 0, stop putsi <cr,lf,'Muta '> puti ax ; Afisare n putsi <' turnuri, de pe A pe B,'> putsi <' folosind C ca'> putsi <' manevra', cr, lf> ; push ax ; n mov ax, 'A' push ax ; Sursa mov ax, 'B' push ax ; Destinatie mov ax, 'C' push ax ; Manevra call far ptr move ; Apel jmp reluare ; Reluare exit: exit_dos end start

La implementarea algoritmilor recursivi, trebuie fcut o estimare a spaiului necesar de stiv. Spre exemplu, procedura move de mai sus necesit n nivele de apel recursiv. La fiecare nivel, se consum 12 octei din stiv (vezi structura ablon). Ca atare, volumul necesar de stiv este de ordinul 12*n. Dac estimm c, ntro aplicaie dat, valoarea lui n nu va crete peste 100, stivaaceleiaplicaiitrebuiesfiedecelpuin1200deoctei. nainte de a trece la implementarea unui algoritm recursiv, trebuie s ne convingem (uneori prin demonstraii teoretice complicate), c algoritmul se termin (se atinge cazul de baz) dup un numr finit de pai. Nu toate funciile definite recursiv au aceast proprietate. De exemplu, funcia f, definitpentruoricenpozitivprin:
f(n) = 5, pentru n = 7 f(n) = f(f(n+2)), pentru n diferit de 7

215 Capitolul6
nu este nici mcar o funcie corect definit. ncercarea de a evalua f(5) conduce imediat la o tautologie (f(5) depinde de f(5)), iar pentru n diferit de 5 i de7seobineuncicluinfinit. Trebuie deci acordat atenie descrierii teoretice a algoritmului recursiv, naintedeatrecelaimplementare. Observaiile despre implementarea algoritmilor recursivi sunt valabile i n cazullimbajelordenivelnalt.

6.8Proceduricunumrvariabildeparametri
Dezvoltarea procedurilor cu numr variabil de parametri are ca scop, pe de o parte, punerea n eviden a flexibilitii limbajului de asamblare i, pe de alt parte, ilustrarea modului de implementare a unui mecanism care exist n anumitelimbajedenivelnalt(deexemplunC). Dezvoltarea unei proceduri cu numr variabil de parametri se bazeaz pe urmtoarelereguli: parametriisetransmitprinstiv exist un numr (cel puin 1) de parametri fici (care nu pot lipsi) i care setransmitnvrfulstivei(imediatdupadresaderevenire) unul din parametrii care sunt totdeauna prezeni conine informaii (codificate ntro form oarecare) despre numrul i tipul parametrilor actuali n procedur se analizeaz parametrii fici, deducnduse numrul i tipul parametrilorvariabili,caresuntapoiextraidinstiv parametrii variabili ca numr transmii n stiv trebuie s corespund cu descrierealornparametriifici stivaestedescrcatdectreprogramulapelant. Regulile de mai sus nu sunt alese ntmpltor. Astfel, faptul c parametrii fici se gsesc n vrful stivei face ca acetia s fie accesibili prin metoda standard. Programul apelant este cel care tie precis ci octei a plasat n stiv nainte deapel,deciestenaturalcaacestasdescarcestiva. Se nelege acum de ce, n limbajul C, ordinea plasrii argumentelor unei proceduri n stiv este de la dreapta la stnga: n acest fel, la o procedur cu numr variabil de parametri, parametrii fici (care se afl la nceputul listei de argumente)vorfiplasaiimediatdupadresaderevenire. ImagineastiveilaintrareanproceduresteilustratnFigura6.9.

Programarenlimbajdeasamblare 216

Figura 6.9 Stiva la intrarea ntr-o procedur cu numr variabil de parametri S considerm un exemplu tipic de procedur cu numr variabil de parametri: o procedur printf_proc de afiare cu format. Exist un parametru fix, de tip adres NEAR a unui ir de caractere care descrie formatul de afiare. irul de caracterepoateconine: caractereobinuite,careseafieazcaatare secveneescape: '\n'pentruCRiLF '\\'pentrucaracterul'\' '%%'pentrucaracterul'%' descriptori de format, compui din caracterul % i un al doilea caracter caredescrietipulafirii: %spentruiruridecaractere %dpentruntregipe16biicusemn %upentruntregipe16biifrsemn. Pentru fiecare specificator de format, se presupune c exist un parametru variabil n stiv, care trebuie afiat corespunztor. Pentru ntregi, se transmite n stiv coninutul care trebuie afiat, iar pentru iruri, se transmite adresa de nceput, de tip NEAR. Se observ c, n toate situaiile, se transmite n stiv un cuvnt (word), ceea ce faciliteaz implementarea. Dac dimensiunile

217 Capitolul6
parametrilor variabili ar fi diferite, ar trebui folosit operatorul de conversie de tip PTR,pentruancrcaparametrulnmodcorect. Pentru afiarea propriuzis se vor folosi macroinstruciunile de apel puts (iruri), puti (ntregi cu semn), putu (ntregi fr semn) i putc (afiare caracter), descrisenCapitolul2. Procedura i toate adresele implicate se consider de tip NEAR. n Figura 6.10 estedescrisconinutulstiveilaunapeltipicalacesteiproceduri.

Figura 6.10 Coninutul stivei la intrarea n printf_proc Pentruaccesullastiv,sevautilizaablonul:


sablon struc _bp _ip format par sablon ends dw ? dw ? dw ? dw ?

; Adresa sir format ; Primul parametru

Procedura va consta dintro bucl de analiz a caracterelor din irul format, a crui adres e gestionat n BX. Astfel, [BX] va reprezenta caracterul curent. Pentru specificatorii de format, se gestioneaz un contor de parametri variabili, n registrul DI, care va lua valorile 0, 2, 4 etc. (toi parametrii variabili sunt pe 16 bii). Accesul la parametrii variabili se va face prin expresia [BP][DI].PAR, deci printro adresare bazat i indexat, cu deplasament. Se trateaz corespunztor secvenele escape (care ncep cu \) i specificatorii de format (care ncep cu %), ambele situaii presupunnd citirea unui caracter suplimentar din irul care descrie formatul. Dac parametrii nu ar avea toi aceeai dimensiune, sar utiliza expresii de genul DWORD PTR [BP][DI].PAR, caz n care registrul DI ar fi actualizat cu dimensiunea parametrului (n cazul de fa,cu4). Implementareaesteurmtoarea:
printf_proc proc push bp near ; Salvare BP

Programarenlimbajdeasamblare 218
mov mov mov pr_loop: mov test jnz jmp aici1: cmp jne inc mov cmp je cmp je cmp je cmp je jmp bp,sp bx, [bp].format di, 0 al, [bx] al, al aici1 pr_end al, '%' pr_char bx al, [bx] al, 's' pr_str al, 'd' pr_int al, 'u' pr_u al, '%' aici2 ; pr_err

; Adresa sir format ; Contor parametri ; variabili ; Caracter curent ; Test sfarsit de sir ; care descrie formatul ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Test spec. format Nu este spec. Daca da, se citeste caracterul urmator Este %s ? Da, salt la afisare Este %d ? Da, salt la afisare Este %u ? Da, salt la afisare Este %% ? Nu a fost nici unul din specificatorii asteptati: se afiseaza un mesaj de eroare

aici2: putc inc jmp pr_char: cmp je putc inc jmp pr_esc: inc mov cmp jne putc putc inc jmp esc1: cmp jne putc inc jmp ; al bx pr_loop al, '\' pr_esc al bx pr_loop bx al, [bx] al, 'n' esc1 cr lf bx pr_loop al, '\' pr_err al bx pr_loop ; Afisare caracter ; Avans adresa sir ; Reluare ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Este secventa escape ? Da, salt la tratare Daca nu, e vorba de un car. obisnuit, care se afiseaza si se reia bucla de parcurgere Tratare secventa escape Luam urmatorul caracter Este \n ? Nu, salt Da, se afiseaza CR LF si se reia bucla de parcurgere Este \\ ? Nu, secventa escape gresita Da, afiseaza \ si reia bucla de prelucrare

219 Capitolul6
; Afisarea parametrilor variabili ; pr_str: push bx ; Afisare sir. Preluam mov bx, [bp+di].par ; adresa din stiva puts [bx] ; si afisam sirul (cu pop bx ; salvare/restaurare BX pr_next: inc bx ; Car. urmator in format add di, 2 ; Contor par. variabili jmp pr_loop ; Reluare pr_int: puti [bp+di].par ; intreg cu semn jmp pr_next ; Reluare pr_u: putu [bp+di].par ; intreg fara semn jmp pr_next ; Reluare pr_err: ; Mesaj de eroare putsi <cr, lf, 'printf: Eroare format', cr, lf> pr_end: pop bp ; Refacere BP ret ; Revenire printf_proc endp

Ne propunem acum s dezvoltm o macroinstruciune de apel, numit printf, care s se apropie ct mai mult de un limbaj de nivel nalt, deci s putem scrie ntextulsurscevadegenul:
printf <"Numerele m n si p sunt: %d %d\n">, <m, n, p>

Macroinstruciunea va avea, deci, un prim parametru (irul care descrie formatul)iolistdeparametrivariabili(carepoatechiarlipsi):


printf macro format, param

Scrierea unei astfel de macroinstruciuni ridic probleme deosebite, dar pe careoperatoriiidirectivelelimbajuluideasamblarelepotrezolva. irul care descrie formatul se definete n segmentul de date, printro tehnic similarceleidelamacroinstruciuneaputsi,descrisnCapitolul5. Problema cea mai dificil este c parametrii variabili trebuie pui n stiv n ordine invers dect apar n lista din apelul macroinstruciunii. Lista poate fi parcurscuinstruciuneaIRP,darnumaidelastngaladreapta. Pentru a pune parametrii n ordinea dorit, se va parcurge lista lor de dou ori. La prima parcurgere, se contorizeaz numrul de parametri (cu operatorul de atribuire=)isecreeazspaiunstiv,prinsecvena:
N = 0 irp x, <param> sub sp, 2 N = N + 1

Programarenlimbajdeasamblare 220
endm

La a doua parcurgere, se plaseaz parametrii n stiv. Problema este c indicatorul SP trebuie s fie incrementat cu 2, deci nu se poate utiliza o simpl instruciunePUSH.Seexecutdecisecvena:
irp x, <param> add sp, 2 push x add sp, 2

endm

carepuneparametriixnstiv,desusnjos(veziFigura6.11).

Figura 6.11 Plasarea parametrilor n stiv la macroinstruciunea printf Toat aceast secven se execut numai dac lista param este nevid. Dup depunerea parametrilor variabili, se decrementeaz SP cu 2*N (deci se aduce SP pe primul parametru), se depune n stiv adresa formatului i se apeleaz procedura printf_proc. Contorizarea parametrilor n constanta simbolic N asigur i o descrcare comod a stivei, prin adunarea valorii 2*(N+1). Dac irulformatlipsete,seforeazoeroaredeasamblare. Implementareacompletamacroinstruciuniiesteurmtoarea:
printf macro format, param local loc_for ifb <format> %out : Lipsa format.... .err .exitm endif .data loc_for db format ;; Definire sir format db 0 .code N = 0 ;; Contor par. variabili ifnb <param> ;; Daca exista par. var.

221 Capitolul6
irp endm irp x, <param> add sp, 2 push x add sp,2 sp, 2*N ax, loc_for ax printf_proc sp, 2*(N+1) ;; in jos ;; in sus ;; in jos ;; SP pe primul par. var. ;; ;; ;; ;; Adresa format Depunere in stiva Apel Descarcare stiva x, <param> sub sp, 2 N = N + 1 ;; Creare spatiu ;; Contor

endm sub endif lea push call add endm

Sconsidermunexempludeapel,ncareavemdefinitedatele:
.data n1 n2 n3 sir1 sir2 sir3 s1 s2 s3 dw dw dw db db db dw dw dw 1234 -3 4321 "abcdef",0 "1234567890",0 "Acesta e un sir...",0 sir1 sir2 sir3

Secvenadetest(programulprincipal)esteurmtoarea:
.code start: init_ds_es printf <"Numarul 1: %d\n">, <n1> printf <"Numerele 2 si 3: %d %d">, <n2,n3> printf <"\nSirul 1: %s %% \\ %%">, <s1> printf <"\nSirul 2: %s\nSirul 3: %s">, <s2,s3> printf <"\nDoar format (fara descriptori) \n"> printf <"n2 cu semn = %d, n2 fara semn = %u\n">, <n2,n2> exit_dos end start

Se observ necesitatea definirii unor variabile pointer (s2, s2, s3) care conin adresele irurilor de caractere sir1, sir2 i sir3. Rularea acestui exemplu produceieirealaconsol:
Numarul 1: 1234 Numerele 2 si 3: -3 4321 Sirul 1: abcdef % \ % Sirul 2: 1234567890

Programarenlimbajdeasamblare 222
Sirul 3: Acesta e un sir... Doar format (fara descriptori) n2 cu semn = -3, n2 fara semn = 65533

Mai trebuie observat c tehnica de transfer a parametrilor variabili, expus mai sus, asigur i o bun protecie a controlului programului n situaii de eroare, adic atunci cnd descriptorii de format nu coincid cu parametrii, att ca numr,cticatip.Sconsiderm,deexemplu,apelurile:
printf <"Ceva gresit %d %d %d\n">, <n1, n2> printf <"Ceva si mai gresit %d %d\n">, <n1, s2, s3>

n primul caz, formatul precizeaz c n stiv sunt trei parametri de tip ntreg, dar la apel nu se transmit dect doi. Procedura va afia un al treilea parametru fictiv, dar, deoarece stiva este descrcat de programul apelant, revenirea se face corect i programul nu se distruge. n al doilea caz, primul parametru se afieaz corect, al doilea (o adres de ir) este afiat incorect ca ntreg, iar al treilea este pur i simplu ignorat. i n acest caz, revenirea n programul apelant icontinuareasanusuntcompromise.

6.9Tehniciavansatedeprogramare
n subcapitolele anterioare au fost descrise elementele de baz ale programrii n ASM (aciunile principale din programarea structurat, proceduri, definiii de date etc.). Cu aceste elemente de baz, se pot aplica orice tehnici de programare cunoscute de la limbaje de nivel nalt. Vom exemplifica o asemeneatehnic,anumeceaaautomatelordestare. Considerm problema elementar a numrrii cuvintelor dintrun ir de caractere. Se consider o serie de caractere speciale, numite delimitatori (n cazul de fa: spaiu, punct, virgul, semn de ntrebare, semn de exclamare icratim).Evident,sepotspecificaoricefeldedelimitatori. Incrementarea numrului de cuvinte nu depinde numai de caracterul curent din ir. De exemplu, un caracter care nu este delimitator va conduce la incrementarea numrului de cuvinte numai n cazul n care caracterul anterior a fost un delimitator. Acest tip de decizie, care se bazeaz pe o informaie anterioar, sugereaz utilizarea unei variabile de stare, care s memoreze stareacurentaprelucrrii. n cazul de fa, vom avea dou stri: n interiorul unui cuvnt i n exteriorul unui cuvnt. Notm cele dou stri cu IN_W i OUT_W. Pentru memorarea lor, estesuficientovariabildestarebinar. Algoritmul se modeleaz ca un automat, care accept intrri i genereaz ieiri. Funcie de intrri i de starea curent, se trece ntro stare urmtoare, emindsaunuoieire.ncazuldefa,intrrilesunt: in_1=caracterulcurentdinirnuestedelimitator in_2=caracterulcurentdinirestedelimitator.

223 Capitolul6
Ieireaautomatuluieste: out=incrementeaznumruldecuvinte Trebuie acum s codificm strile, intrrile i ieirile. Pentru simplitate, vom utilizaregistreleprocesorului: stare=IN_W: CX=1 stare=OUT_W: CX=0 in_1: BX=1 in_2: BX=0 out: IncrementeazAX. Descriemacumfuncionareaautomatului,prindiagramadinFigura6.12. Dac suntem n interiorul unui cuvnt (starea IN_W), atunci un delimitator (intrarea in_2) provoac trecerea n exteriorul unui cuvnt (starea OUT_W), iar un caracter care nu este delimitator (intrarea in_1) menine starea IN_W. Dac suntem n exteriorul unui cuvnt (starea OUT_W), atunci un delimitator (intrarea in_2) menine starea OUT_W, iar un caracter care nu este delimitator (intrarea in_1) provoac trecerea n starea IN_W i forarea semnalului de ieire out. Iniial, automatul se afl n starea OUT_W. Se remarc faptul c, n codificarea aleas, starea urmtoare este dictat de codificarea intrrii (mai precis, comutarea strii va nsemna o simpl instruciuneMOVCX,BX).

Figura 6.12 Descrierea funcionrii unui automat de stare Evoluia variabilei de stare, a intrrilor in_1 i in_2, precum i a ieirii out n cazul prelucrrii irului de caractere Un text oarecare. sunt ilustrate n Figura 6.13.

Programarenlimbajdeasamblare 224 Implementarea algoritmului urmrete ndeaproape funcionarea automatului iconstnprincipaldin: evaluareaintrrilor comutareastrii forareaieirii.

Figura 6.13 Evoluia automatului de stare n cazul irului Un text oarecare. Presupunem c adresa irului este transmis procedurii n DS:SI i c rezultatul estentorsnAX.Implementareaesteurmtoarea:
count proc near push cx push bx push si mov cx, 0 mov reluare: cmp je cmp je cmp je cmp je cmp je cmp je ax, cx byte ptr [si], 0 gata byte ptr [si], ' ' et_1 byte et_1 byte et_1 byte et_1 byte et_1 ptr [si], tab ptr [si], '.' ptr [si], ',' ptr [si], '?' ; Salvari ; registre ; Stare initiala ; = OUT_W ; Numar de cuvinte = 0 ; Test sfarsit de sir ; Evaluare intrari: ; Blank ; Tab ; Punct ; Virgula ; Semn de intrebare

225 Capitolul6
cmp je cmp je mov jmp et_1: mov bx, 0 ; ; ; in acest moment, intrarile sunt ; BX = 1 (in_1) sau BX = 0 (in_2) et_2: cmp cx, 0 ; je et_3 mov cx, bx ; jmp et_5 et_3: cmp bx, 1 ; jne et_4 ; inc ax ; ; ; ; et_4: mov cx, bx ; et_5: inc si ; jmp reluare ; gata: pop si ; pop bx ; pop cx ret ; count endp Delimitator pozitionate Stare = OUT_W ? Stare = intrare In starea OUT_W si cu intrarea in_1, se genereaza iesirea out (incrementeaza numarul de cuvinte) Stare = intrare Trecere la caracterul urmator Refaceri registre Rezultat in AX byte ptr [si], '!' et_1 byte ptr [si], '-' et_1 bx, 1 et_2 ; Semn de exclamare ; Cratima ; Nu e delimitator

Un program de test al procedurii count este listat mai jos. Se citesc de la consol iruri de caractere (pn la introducerea irului vid), se apeleaz proceduracountiseafieaznumruldecuvintedinirulintrodus.
.model small include io.h .data sir db 80 dup (0) .stack 1024 .code start: init_ds_es iar: putsi gets mov test <'Introduceti un sir: '> sir ; Citire sir al, sir ; Test sir al, al ; vid

; Spatiu de lucru

Programarenlimbajdeasamblare 226
jz putsi lea call puti putsi jmp exit: end exit_dos start exit <'Sirul are '> si, sir count ax <' cuvinte', cr, lf> iar

; Apel procedura ; Nr. cuvinte in AX ; Afisare ; Reluare

6.10Programareacoprocesoarelormatematice
n Capitolul 2, a fost prezentat setul de instruciuni al coprocesoarelor matematice 80x87. Coprocesorul recunoate variabile ntregi i toate cele trei tipuridenumerereale(preciziesimpl,dubliextins). n acest subcapitol, ne propunem s dezvoltm un set de proceduri i macroinstruciuni care s rezolve problema conversiei din formatul real (n simpl precizie), n format ASCII (ir de caractere), ceea ce va permite apoi i introducereaiafiareadenumererealelaconsol.

6.10.1ConversiaASCIIreal
Dezvoltm o procedur de tip far, cu numele ATOF_PROC, care primete n stiv o adres near a unui ir de caractere i o adres near a unui numr real. ablonuldeacceslastiveste:
sablon_atof struc adr_num adr_sir sablon_atof ends dw dd dw dw ? ? ? ? ; Loc pentru BP ; Loc pentru adresa de revenire

Proceduradeconversiesebazeazpeurmtorulalgoritm:
valoare = 0; divizor = 1.0 punct = FALSE; minus = FALSE; preia caracter din sirul sursa; if (caracter == '-' ) { minus = TRUE; preia urmatorul caracter din sirul sursa; } while (caracterul curent este cifra zecimala sau '.') { if (caracter == '.') punct = TRUE; else { cifra = caracter - '0';

227 Capitolul6
cifra_float = (float) cifra; valoare = 10.0 * valoare + digit_float; if (punct) divizor = divizor * 10.0; } preia urmatorul caracter din sir; } if (punct) valoare = valoare/divizor; if (minus) valoare = - valoare; return valoare;

Ideea general este calculul numrului ca i cnd nu ar avea punctul zecimal i mprirea apoi la o putere a lui 10, calculat dup numrul de zecimale. De exemplu, irul 123.456 va conduce la calculul valorii 123456, care se mparte apoila1000. Implementareaesteurmtoarea:
.data _zece _punct _minus _cifra .code atof_proc proc far push bp mov bp, sp push bx push si fld1 fldz ; ; ; dd db db dw 10.0 ? ? ?

; Salvari ; registre ; ST <- 1.0 ; ST <- 0.0, ST(1) <- 1.0

Asignam valoare in ST si divizor in ST(1) _punct, 0 _minus, 0 bh, bh si, [bp].adr_sir byte ptr [si], '-' atof_1 _minus, 1 si bl, [si] bl, '.' atof_2 _punct, 1 atof_3 bl, '0' atof_4

mov mov xor mov cmp jne mov inc atof_1: mov cmp jne mov jmp atof_2: cmp jb

; Necesar la depunere intreg ; Adresa sir ; Test '-'

; Preia caracter ; Test '.' ; Salt la reluare ; Test ; cifra

Programarenlimbajdeasamblare 228
cmp ja sub mov fmul fiadd cmp jne fxch fmul fxch atof_3: inc si jmp atof_1 atof_4: fdivr cmp jne f_comp je fchs atof_5: mov fstp _minus, 1 atof_5 _zero atof_5 bx, [bp].adr_num dword ptr [bx] bl, '9' atof_4 bl, '0' _cifra, bx _zece _cifra _punct, 1 atof_3 _zece ; zecimala ; ; ; ; ; ; ; ; ; ; ; ; Conversie la intreg Memoram ca intreg valoare = 10*valoare valoare = valoare + cifra Test punct Schimbam ST cu ST(1) pentru ca vrem sa inmultim divizorul cu zece, apoi schimbam la loc

; Reluare ; bucla ; ; ; ; impartire ST la ST(1) cu descarcarea stivei Rezultat in ST Test semn

; Daca e 0.0 nu ; schimba semnul ; Schimbare semn ; Adresa numar real ; Depunere ST ; cu descarcarea ; stivei, apoi FWAIT ; Refaceri ; registre ; Revenire

fwait pop si pop bx pop bp retf atof_proc endp

Se observ c stiva coprocesorului este lsat n starea n care era la intrarea n procedur, lucru care trebuie avut n vedere la toate programele care lucreaz cu 80x87. ntro implementare mai pretenioas, sar salva toate cele 8 registre ale coprocesorului ca variabile de tip TBytes, ntro zon proprie de memorieisarrefacelarevenireanprogramulapelant. De asemenea, bucla de citire caractere ar trebui s testeze dac sa ntlnit deja punctul zecimal. Pentru simplitate, sa presupus aprioric c irul surs coninecelmultunpunctzecimal. Scriem acum o macroinstruciune de apel, cu numele atof, care are ca parametri irul de caractere surs i variabila real n care se va depune

229 Capitolul6
rezultatul. Ambii parametri sunt folosii n instruciuni LEA, care preiau adreseleneariletransmitctreproceduraatof_proc.
atof macro push lea push lea push call add pop a_sir, a_num si si, a_sir si si, a_num si far ptr atof_proc sp, 4 si

endm

Dispunnd de macroinstruciunea atof, putem scrie o macroinstruciune cu numele getf, care s citeasc un numr real de la consol. Operaia se compune dintro citire de ir de caractere i o conversie ASCIIreal. Parametrul macroinstruciuniiestevariabiladwordncaresedepunenumrulrealcitit.
getf macro local sir .data sir .code gets atof endm sir sir, a_num a_num db 80 dup (0)

6.10.2Comparareanumerelorreale
O problem important care se pune este compararea a dou numere reale. Procesorul dispune de instruciuni de comparare, n urma crora se poziioneaz o serie de flaguri interne din cuvntul de stare (Status Word). Acest cuvnt poate fi depus n memorie cu instruciuni FSTSW i citit apoi prin instruciuni 80x86. Preferm totui o alt abordare, mai simpl, anume efectuarea diferenei celor doi operanzi i poziionarea corespunztoare a bistabililor ZF i CF din 80x86. Astfel, se vor putea utiliza instruciuni de salt condiionat specifice 80x86 (JE, JB, JGE etc.). Testarea semnului diferenei se face prin examinarea fizic a bitului de semn din reprezentarea intern a numerelor n simpl precizie. Testarea cazului de egalitate se face testnd dac toiceipatruocteiaidifereneisuntnuli,ignorndbituldesemn. Dezvoltm macroinstruciunea F_COMP, cu un operand, care compar numrulrealdinvrfulstiveicoprocesoruluicuoperandulspecificat.
f_comp macro local .data temp dd val temp, etgt, etlt, eteq, gata ? ; Spatiu de lucru

Programarenlimbajdeasamblare 230
.code push fld fsub fstp mov and jnz mov or jz etgt: mov cmp jmp etlt: mov or and jz mov cmp jmp eteq: mov cmp gata: pop endm ax st dword ptr val dword ptr temp al, byte ptr temp+3 al, 10000000B etlt ax, word ptr temp ax, word ptr temp+2 eteq ax, 2 ax, 1 gata ax, word ptr temp ax, word ptr temp+2 ax, 7FFFH eteq ax, 1 ax, 2 gata ax, 1 ax, 1 ax ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Salvare AX Se face o copie a varfului stivei, pentru a nu altera ST initial ST <- ST - val Depunem diferenta Luam ultimul octet din reprezentare Filtru bit de semn Diferenta negativa ? Nu, testam daca nu este zero Zero real are toti cei 4 octeti nuli Este zero ? Nu, inseamna ca e mai mare Facem o comparatie pentru a pozitiona indicatorii

; -0 si 0 sunt identice ; Cazul mai mic ; Cazul egal ; Refacere AX si gata

6.10.3ConversiarealASCII
Dezvoltm acum procedura ftoa_proc, care primete n stiv adresa near a unui numr real i adresa near a unui ir de caractere. Procedura convertete numrul real ntrun ir de caractere care conine reprezentarea valorii reale n formattiinific:
x.xxxxxxEyy

Accesullaparametriidinstivsefaceprinstructuraablon:
sablon_ftoa struc val siradr sablon_ftoa end dw dd dd dw ? ? ? ?

Implementarea folosete o serie de constante i variabile de lucru, definite mai jos.Algoritmuldeconversieesteurmtorul:


; ; val = Valoarea reala care se converteste

231 Capitolul6
; sir = Adresa sirului destinatie ; if (val < 0.0) { *s++ = '-'; val = -val; } _exp = 0; if (val != 0.0) { if (val >= 0.0) { do { val = val / 10.0; _exp = _exp + 1; } while (value >= 10.0) } else { while (val < 1.0) { val = val * 10.0; _exp = _exp - 1; } } val = val + 0.0000005; if (value > 10.0) { value = value / 10.0; _exp = _exp + 1; } } _cifra = (int) val; /* Obligatoriu cu trunchiere, nu cu rotunjire */ *s ++ = _cifra + '0'; *s++ = '.'; for (i = 1; i <= 6; i++) { val = 10.0 * (val - (float) _cifra); _cifra = (int) val; /* Obligatoriu cu trunchiere, nu cu rotunjire */ *s++ = _cifra + '0'; } *s++ = 'E'; if (_exp < 0) { *s++ = '+'; _exp = - _exp; } else *s++ = '+'; /* scrie _exp ca dou cifre n sir */ *s = 0; /* Terminator de sir */

Se aduce numrul n intervalul [1.0, 10.0), prin mpriri sau nmuliri succesive cu 10. nmulirile sau mpririle cu 10 sunt contorizate n variabila ntreag _exp (exponent zecimal). n acest moment, partea ntreag a numrului are o singur cifr, care se poate extrage i depune n ir. Se determin partea fracionar, prin scderea prii ntregi, se nmulete cu 10 i se reia generarea cifrelor. Acest proces se repet de 5 ori, pentru cifrele dedupvirgul.

Programarenlimbajdeasamblare 232 n prealabil, se realizeaz o rotunjire a numrului, prin adunarea valorii reale 0.000005. Algoritmul depinde esenial de modul n care se face conversia realntreg. Este obligatoriu ca aceast conversie s se realizeze prin trunchiere, nu prin rotunjire.Deexemplu,valoarea2.999trebuiesgenerezeprimacifr2,inu3. Coprocesorul poate opera n mai multe moduri de rotunjire/trunchiere. Aceste moduri sunt controlate de biii 10 i 11 (cmpul RC sau Round Control), din cuvntul de control (Control Word). Pentru situaia de fa, este adecvat modul RC = 1. Procedura trebuie deci s poziioneze cmpul RC din cuvntul de control, printro salvare/ncrcare n memorie. La revenirea n programul apelant,sevarefacecmpulRCoriginal. Procedura necesit o serie de constante reale i variabile de manevr, definite mai jos. Numele variabilelor coincid cu cele de la descrierea algoritmului. Evident, vom aloca variabila real n vrful stivei 80x87. Exponentul este gestionatcanumrntreg.
.data _zece _unu _zero _round _exp _cifra _temp _cw dd dd dd dd dw dw dd dw 10.0 1.0 0.0 0.0000005 ? ? ? ?

Implementareapropriuzisesteurmtoarea:
.code ftoa_proc proc far push bp mov bp, sp push push push push fstcw mov and or mov fldcw mov mov fld ax bx si cx _cw ax, _cw ax, NOT 0000110000000000B ax, 0000010000000000B _cw, ax _cw _exp, 0 si, [bp].siradr dword ptr [bp].val ; Salvare ; registre

; Salvare Control Word ; ; ; ; ; ; ; ; Filtru bitii 10 si 11 Fortare RC = 1 inapoi in memorie inapoi in 80x87 Exponent Adresa sir de caractere Valoare reala n ST

233 Capitolul6
f_comp jg mov inc fchs ftoa_poz: f_comp jne jmp ftoa_aici: f_comp jnge ftoa_3: fdiv add _zero ftoa_poz byte ptr [si], '-' si _zero ftoa_aici ftoa_1 _zece ftoa_2 _zece _exp, 1 ; ; ; ; Este > 0 ? Nu, depunem '-' in sir si schimbam semnul numarului real

; Este diferit de 0.0 ? ; Da, il convertim ; Este < 10 ? ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Nu, il impartim la 10 si tinem minte la exponent pana cand ajunge mai mic strict decat 10 Este mai mare sau egal ca 1 ? Da, salt Nu, il inmultim cu 10 si tinem minte la exponent, pana ajunge mai mare sau egal ca 1 Rotunjim la 7 zecimale Poate a depasit acum 1o ?

f_comp _zece jnl ftoa_3 ftoa_2: f_comp _unu jge fmul sub jmp ftoa_1: fadd ftoa_1 _zece _exp, 1 ftoa_2 _round

f_comp _zece jna fdiv add ftoa_4: fist mov add mov inc mov inc mov ftoa_5: fisub fmul ftoa_4 _zece _exp, 1 _cifra bl, byte ptr _cifra bl, '0' [si], bl si byte ptr [si], '.' si cx, 6 _cifra _zece

; Daca da, corectam ; ; ; ; ; ; ; Generam partea intreaga Luam cifra propriu-zisa, o convertim la caracter ASCII si o depunem in sir

; Apoi punctul zecimal ; Bucla de 6 cifre ; dupa punct ; ST = partea ; fractionara ; ST = ST * 10

Programarenlimbajdeasamblare 234
fist mov add mov inc loop fstp mov inc cmp jge mov neg jmp ftoa_6: mov ftoa_7: inc mov aam or mov inc mov inc mov pop pop pop pop pop retf ftoa_proc _cifra bl, byte ptr _cifra bl, '0' [si], bl si ftoa_5 _temp byte ptr [si], 'E' si _exp, 0 ftoa_6 byte ptr [si], '-' _exp ftoa_7 byte ptr [si], '+' si ax, _exp ax, 3030H [si], ah si [si], al si byte ptr [si], 0 cx si bx ax bp ; Revenire endp ; Partea intreaga ; Determinare cifra

; Descarcam stiva 8087 ; Notatie stiintifica ; Test semn exponent ; Negativ ; Schimbam semnul ; Pozitiv ; ; ; ; ; ; Exponent AH = _exp / 10; AL = _exp MOD 10 Ambele cifre convertite la ASCII Depunere in sir

; in fine, terminatorul ; de sir ; Refacere ; registre

Se observ utilitatea foarte mare a macroinstruciunii f_comp, care face ca implementarea algoritmului s fie o simpl transpunere a descrierii de tip pseudocod. Dezvoltm acum o macroinstruciune de apel cu numele ftoa i cu parametri adecvai(valoarearealiiruldestinaie):
ftoa macro push lea push mov push mov val, sir ax ax, sir ax ax, word ptr val + 2 ax ax, word ptr val

235 Capitolul6
push call add pop endm ax far ptr ftoa_proc sp, 6 ax

Dispunnd de macroinstruciunea ftoa, putem dezvolta o macroinstruciune putf, care s afieze la consol un numr real, prin conversie realASCII i afiareir:
putf macro val local .data sir .code ftoa puts sir db 30 dup (0) val, sir sir

endm

6.10.4Unprogramdetest
Dac presupunem macroinstruciunile de mai sus definite ntrun fiier float.h, putem scrie un mic program de test, care citete un numr real de la consol i afieazvalorileincrementatede10ori.
.model large .8087 include io.h include float.h .stack 1024 .data numar dd ? unu dd 1.0 .code start: init_ds_es finit putsi <'Introduceti un numar real: '> getf numar putsi <'Valorile incrementate sunt:', cr, lf> mov cx, 10 iar: putf numar putsi <cr, lf> fld numar fadd unu fstp numar loop iar exit_dos end start

Se observ instruciunea FINIT, care iniializeaz coprocesorul matematic. Directiva .8087 instruiete asamblorul s accepte mnemonice specifice

Programarenlimbajdeasamblare 236 coprocesorului 8087. Funcie de tipul coprocesorului i al procesorului de baz,sepotutilizadirectivele.287,.387sau.486. Procedurile de mai sus opereaz cu numere n simpl precizie. Trecerea la precizie dubl i extins se face ns foarte uor. Trebuie doar ca variabilele externe i constantele reale utilizate s fie declarate de tip qword (8 octei), respectiv tbytes (10 octei), deoarece formatul intern al procesorului este cel depreciziemaxim. Dei procedurile care implic operaii cu numere reale par complicate, implementrile din acest subcapitol arat c o abordare sistematic i disciplinat permite dezvoltarea unui cod surs clar, uor de urmrit i de ntreinut.

Capitolul7
InterfaaASMlimbajedenivelnalt
O parte important a programrii n limbaj de asamblare o constituie legarea modulelor de program ASM cu module de program dezvoltate n limbaj de nivel nalt. n acest mod, se poate crete eficiena aplicaiilor, prin dezvoltarea modulelorcritice(careseutilizeazfoartedes)nASM. n acest capitol, va fi exemplificat dezvoltarea de aplicaii mixte n limbaj de asamblare i n limbajul C. Alegerea limbajului C ca limbaj reprezentativ de nivel naltestejustificatdeurmtoareleproprieti: rspndirea foarte mare a limbajului C, ca limbaj destinat att programelor desistem,cticeloraplicative existena unor medii de dezvoltare evoluate, total compatibile cu asambloarele 8086 (un exemplu semnificativ fiind familia de produse Borland) caracterul modular al limbajului C, prin care se permite compilarea separatamodulelorsurs compatibilitatea total a modulelor obiect (un modul obiect rezultat n urma compilrii unui text surs C are exact acelai format ca un modul obiect rezultatalasamblriiunuitextASM). Se va utiliza deci mediul de dezvoltare Borland (compilatorul bcc, editorul de legturitlink,asamblorultasm,respectivmediulintegratbc).

7.1Transferulparametrilor.Simboluriexterne
n mod concret, interfaa dintre module C i module ASM va consta din apeluri de funcii ASM din C i invers, respectiv din accesul din C la date definite n ASMiinvers. Compilatorul Borland C realizeaz transferul parametrilor prin stiv, n ordinea de la dreapta la stnga a listei de parametri. Descrcarea stivei este fcut de ctre modulul apelant. ntoarcerea de tipuri simple de date din funcii se realizeaz prin registrul acumulator, eventual extins (deci prin AL, AX sau DX:AX, corespunztor unui tip pe 1, 2 sau 4 octei). Tipurile reale (float, double, long double) sunt ntoarse printro zon special a bibliotecii de virgul

237 Capitolul7
mobil sau n vrful stivei coprocesorului matematic. Pentru a nu complica interfaa, vom considera c funciile C folosite n ASM nu ntorc valori reale. Dac este absolut necesar, se poate adopta soluia ca funciile C s ntoarc pointerilavariabilerealestatice. Un alt caz complicat este transferul structurilor i al uniunilor, care este definit n C prin copierea bit cu bit a tuturor membrilor, att la transfer spre funcie, ct i la ntoarcere din funcie. Este i aici de preferat soluia mult mai eficient deatransferasauantoarceunpointerctrestructurasauuniunearespectiv. Numele simbolurilor externe n C (funcii i variabile externe) sunt generate implicit cu caracterul _ (subliniere) ca prim caracter. De exemplu, simbolul var este generat ca _var i vizibil ca atare ntrun modul ASM. Pentru variabile, numeleestesinonimcuadresaundeestememoratvariabila. Deoarece, n C, vizibilitatea extern este permis numai variabilelor definite la nivel exterior (n afara tuturor funciilor), acestea sunt implicit alocate static, deci au adrese fixe de memorie. Dac, de exemplu, var este un ntreg definit n C,atuncielpoateficititnASMprintroinstruciunedetipulmovax,_var. Trebuie cunoscute dimensiunile fizice ale tipurilor de baz din C. Acestea sunt: char (1 octet), int (2 octei), short (2 octei), long (4 octei), float (4 octei), double (8 octei), long double (10 octei), pointeri (2 sau 4 octei, funcie demodeluldememoriefolosit). Trebuie inut seama i de faptul c operaiile cu stiva sunt operaii pe 16 bii, deci cnd se transmite un char la o funcie, se pune pe stiv un cuvnt de 16 bii, cu partea mai semnificativ 0. Este recomandabil ca, asemenea funciilor din biblioteca C standard, variabilele de tip char s fie transmise i ntoarse la i de la funcii ca variabile de tip unsigned int, ceea ce asigur protecie la o eventual extensie de semn la 16 bii. De exemplu, variabila char '\x81' devine, prin extensie de semn, ntregul 0xff81, dar variabila unsigned char '\x81' devine ntregul 0x0081. Extensia de semn poate aprea dac tipul char este implicit signed (ceea ce se ntmpl la Turbo C). Exist o opiune de compilare care face ca tipul char s fie implicit unsigned, dar este bine s se scrieprogramecaresnudepinddeaceastopiune. Un alt fapt care trebuie avut n vedere este c Cul este un limbaj de tip case sensitive, deci conteaz dac identificatorii sunt scrii cu litere mici sau mari. Trebuie forat la TASM opiunea /ml sau /mx care genereaz simbolurile inndcontdeacestfapt.SconsidermurmtoareasecvenC:
include <stdio.h> int n = 5; char sir[] = "Un sir"; void main(void) { printf("%s %d\n", sir, n); }

Programarenlimbajdeasamblare 238 Presupunnd modelul de memorie small (adic toate adresele sunt pe 2 octei),imagineastiveilaintrareanfunciaprintfesteceadinFigura7.1.

Figura 7.1 Imaginea stivei la un apel al funciei printf Apelul lui printf din ASM se poate face cu secvena ASM de mai jos (echivalentcusecvenaC):
.model small extrn printf: near .data n dw 5 sir db 'Un sir', 0 _format db '%s %d\n', 0 .code _main proc near push _n lea ax, sir push ax lea ax, format push ax call near ptr printf add sp, 6 retn _main endp

239 Capitolul7

7.2Dezvoltareanmediuintegratsauprinliniide comand
Sunt posibile dou moduri de dezvoltare a aplicaiei: n mediul integrat C sau prinliniadecomand. n mediul integrat (lansat prin comanda bc) trebuie definit un proiect care s specifice explicit modulele n limbaj de asamblare. Definirea proiectului permite specificareaprogramuluitranslator(CompilersauAssembler). Astfel, se poate lucra n regim de editare, compilare, depanare etc., cu ambele tipuri de module (ASM i C), mediul integrat recunoscnd modulele scrise n ASM. Acest context este foarte util pentru depanare, deoarece toate facilitile specifice mediilor integrate de dezvoltare pentru limbaje de nivel nalt (rulare pas cu pas, vizualizarea permanent a unor variabile etc.), se aplic i modulelorscrisenASM. O alt variant de depanare o constituie Turbo Debuggerul, care poate fi apelat direct sau din mediul integrat, acesta recunoscnd, de asemenea, att moduleASM,ctimoduleC. Opiunile necesare la compilarea programelor C (cea mai important fiind modeluldememorie),sestabilescprincomandaOptionsamediuluiintegrat. A doua posibilitate este compilarea, respectiv asamblarea separat a modulelor surs, prin lansri ale compilatorului bcc i ale asamblorului tasm de la consol i apoi legarea explicit a modulelor obiect, prin lansarea editorului de legturi tlink. n acest caz, opiunea de model de memorie pentru modulele C se stabilete n linia de apel a compilatorului (opiunea mx, unde x este un caracter ce identific modelul). De asemenea, trebuie precizat opiunea c (compile only), astfel nct compilatorul C s produc numai modul obiect. Tot n linia de comand se precizeaz cile pentru fiierele header i pentru biblioteci(opiunileIiL). Cnd se lucreaz n regim de linie de comand, trebuie inut seama de structura unui program C. Pe lng modulele definite de utilizator, trebuie adugate modulul de iniializare c0x (se pune pe prima poziie n lista de module obiect la tlink) i bibliotecile C (aflate n subdirectorul \lib), care se specific dup numele fiierului executabil. Att modulul de iniializare, ct i bibliotecile sunt specifice modelului de memorie folosit, fiind identificate prin ultimaliteranumeluifiieruluirespectiv. Bibliotecile care trebuie specificate depind de funciile utilizate n modulele C. Practic, se va lega totdeauna bibioteca cx.lib i, eventual, mathx.lib, emu.lib (pentru emularea operaiilor n virgul mobil), fp87.lib (dac sistemul are coprocesor), graphics.lib (dac sau folosit funcii grafice). n specificarea numelor fiierelor care conin modulul de iniializare i bibliotecile respective, caracterulxdepindedemodeluldememoriefolosit.

Programarenlimbajdeasamblare 240 Este util o vizualizare a coninutului subdirectorului \lib din implementarea Borland C, pentru a identifica bibliotecile C. Este, de asemenea, util vizualizarea opiunilor posibile de compilare, asamblare i linkeditare, ca i sintaxa acestor comenzi (se poate obine prin bcc, tasm sau tlink urmate imediatde<Enter>). n cazul n care modulul de program principal este scris n limbaj de asamblare, trebuie inut seama de faptul c main este o funcie ca oricare alta. De fapt, modulul de program principal este modulul precompilat c0, care, dup ce face o serie de iniializri, apeleaz procedura main. Din aceast cauz, dac funcia main este scris n ASM, ea trebuie declarat ca o procedur i specificatcasimbolpublic:
public _main _main proc ... ret _main endp end

Procedura _main trebuie ncheiat prin instruciunea ret, ca orice procedur, iar modulul de program respectiv nu trebuie s conin etichet de start. ncheierea execuiei se va face la returnul din _main, controlul revenind modulului c0, care a apelat _main i care este rspunztor de ieirea n sistemul de operare. Nu este necesar o ieire n DOS din procedura _main. De asemenea, nu este necesar nici iniializarea registrelor DS i ES, deoarece este fcut n modulul c0. Modulul c0 definete i o stiv minim (dac modelul nu este tiny), care se poate mri, dac este necesar, prin directivaASM.stack. n cazul n care funcia cmain este scris n C, modulele ASM vor conine, practic proceduri i definiii de date, care trebuie declarate publice (cu ajutorul directivei ASM public). De asemenea, dac modulele ASM apeleaz funcii C, acestea trebuie declarate n ASM ca simboluri externe (cu ajutorul directivei ASMextern).

7.3Modeledememorie
Modelele de memorie corespund organizrii segmentelor de date, cod i stiv, specifice adresrii de la procesoarele INTEL. Att asamblorul TASM, ct i compilatorul Borland C recunosc aceleai modele de memorie, genernd segmente cu acelai nume. La TASM, acest lucru corespunde folosirii directivelor de definire simplificat a segmentelor. Aceast compatibilitate total simplificfoartemultefortuldedezvoltareaaplicaiilormixte. n ASM, modelul se specific prin directiva .model, iar n C prin opiunea Options/Compiler/Code generation.../Model n mediul integrat sau prin opiuneamxnliniadecomand,lalansareacompilatorului.

241 Capitolul7
Modelele disponibile sunt tiny, small, compact, medium, large i huge. Funcie de aceste modele, se vor genera apeluri de funcii implicit de tip far sau near ipointerilafunciisauladateimplicitdetipfarsaunear. Implementrile Borland C permit definirea explicit a pointerilor i a funciilor de tip far sau near, dar acest lucru nu este recomandabil. Este indicat s fie lsat compilatorul s genereze implicit pointeri i apeluri de funcii, conform modelului de memorie definit. Dac modulele C includ fiierele header predefinite, n care se gsesc prototipurile pentru funciile de bibliotec folosite, apelurile de funcii i legarea cu modulele de bibliotec se vor realiza nmodcorect. n modulele ASM, se va folosi acelai model de memorie, dar trebuie inut cont de tipurile pointerilor i ale funciilor definite sau folosite n modulele C, deoarece, n ASM, accesul la date, funcii, adrese de segment, offseturi etc. se face explicit. Se recomand ca, n ASM, s se foloseasc explicit apeluri de tip near/far, definiii de proceduri explicite near/far i return explicit de tip near/far, dei asamblorul genereaz corect apeluri i definiii de proceduri implicite, pe baza modelului ales. Totui, pentru a scoate n eviden tipurile respective,estebinessefoloseascvarianteexplicitenASM. Nu se recomand n nici un caz ca, n aceeai aplicaie, module diferite de programsaibmodelediferitedememorie. Portabilitatea modulelor C la schimbarea modelului de memorie nu necesit, practic, nici un efort de ntreinere. Portabilitatea modulelor ASM fa de modelele de memorie este ns o problem dificil. Apelurile de proceduri i instruciunile de revenire pot fi gestionate corect de ctre asamblor. Restul operaiilor trebuie gestionate explicit, eventual prin directive de asamblare condiionat. S presupunem c transmitem unei proceduri un parametru de tip adres de variabil (de date) i dorim s definim o structur de acces la stiv, care s nu depind de modelul de memorie utilizat. Soluia const n folosirea directivelor deasamblarecondiionatiasimboluluipredefinit@MODEL(vezi4.2).
_TINY_ equ _SMALL_ equ _MEDIUM_ equ _COMPACT_ equ _LARGE_ equ _HUGE_ equ DATE_MARI equ COD_MARE equ DATE_MICI equ COD_MIC equ sablon struc _bp _ip IF COD_MARE 1 2 3 4 5 6 (@MODEL EQ COMPACT) OR (@MODEL EQ LARGE) (@MODEL EQ MEDIUM) OR (@MODEL EQ LARGE) NOT (DATE_MARI) NOT (COD_MARE) dw dw ? ?

Programarenlimbajdeasamblare 242
_cs ENDIF IF DATE_MICI adr_var ELSE adr_var ENDIF sablon ends portabila push bp mov bp, IF DATE_MARI les bx, ELSE lea bx, ENDIF pop bp ret portabila proc sp adr_var adr_var dd ? dw ? dw ?

endp

ablonul de acces se modific att la schimbarea tipului datelor, ct i la cea a codului. Similar, accesul la adr_var presupune ncrcarea offsetului sau a perechii(segment:offset). Segmentele definite care au importan din punct de vedere ASM sunt urmtoarele: _TEXT sau SURSA_TEXT Corespund directivei .code din ASM sau codului generat de compilatorul C. La modelele de cod mare (compact, large, huge) se genereaz numele SURSA_TEXT, unde SURSA este numele fiierului sursa C sau ASM. La ASM se poate folosi directiva .code nume, caz n care se va genera un segment cu numele nume_TEXT. La modelele de cod mic (tiny, small, compact), se genereaz segmente cu numele _TEXT, cu tipul de combinare PUBLIC, ceea ce va face ca toate segmentele _TEXT s se combine ntrunul singur, rezultndastfelununicsegmentdecod. _DATA sau SURSA_DATA Corespund directivei .data din ASM sau datelor din C n clasa extern i static internal (deci cele cu alocare static) iniializate explicit. La modelul huge, compilatorul C genereaz numele SURSA_DATA, unde SURSA este numele fiierului surs, iar la celelalte, numele _DATA. Tipul de combinare este PUBLIC, deci toate segmentele cu numele _DATA se vor combina ntrunul singur. _BSS

243 Capitolul7
Corespunde directivei .data? din ASM sau datelor cu alocare static neiniializate explicit. Acestea vor fi iniializate de modulul c0 cu valoarea 0. La modelul huge, att datele neiniializate, ct i cele iniializate sunt definite n segmentele SURSA_DATA. Tipul de combinare este PUBLIC, deci toatesegmentelecunumele_BSSsevorcombinantrunulsingur. _STACK Corespunde stivei programului. Stiva este declarat cu o lungime minim n c0, darpoatefiextinsnASMprindirectiva.stack,saunCprindeclaraia:
extern unsigned _stklen = ... ;

La modelele diferite de huge i tiny, se genereaz un grup de segmente numit DGROUP, care cuprinde segmentele _DATA i _BSS (ntre altele). La modelul tiny, acest grup cuprinde i segmentele _TEXT i _STACK. La modelulhuge,DGROUPnucuprindesegmenteleSURSA_DATA. Compilatorul C genereaz urmtoarele segmente, funcie de modelul de memoriefolosit: tiny Se va genera un unic segment de cod, cu numele _TEXT, un unic segment de date iniializate _DATA i un unic segment de date neiniializate _BSS. Se genereaz un grup de segmente, numit DGROUP, care va include segmentele _TEXT, _DATA i _BSS. Nu se definete segment de stiv. Acest model corespunde programelor de tip .COM din DOS. n ASM, se vor folosi directivele .code pentru cod, .data pentru date iniializate i .data? pentru date neiniializate. Registrul DS este iniializat cu DGROUP. Toi pointerii sunt de tip near. Apelurile de funcii sunt implicit near. Modulul de iniializare este c0t.obj,iarbibliotecilespecificesuntcs.libimaths.lib. small Se va genera un unic segment de cod, cu numele _TEXT i un grup de segmente, numit DGROUP, care va include segmentul de date iniializate _DATA i segmentul de date neiniializate _BSS. Se definete explicit un segment de stiv. Toi pointerii sunt implicit de tip near. Apelurile de funcii sunt implicit de tip near. Registrul DS este iniializat n modulul c0 cu DGROUP. Modulul de iniializare specific este c0s.obj, iar bibliotecile specificesuntcs.libimaths.lib. compact Se va genera un unic segment de cod, cu numele _TEXT i un grup de segmente de date, numit DGROUP care conine segmentele _DATA

Programarenlimbajdeasamblare 244 (accesibil n ASM prin directiva .data) i _BSS (accesibil n ASM prin .data?). Pointerii la funcii sunt implicit de tip near, iar pointerii la date sunt implicit de tip far. Apelurile de funcii sunt implicit de tip near. Registrul DS este iniializat n modulul c0 cu DGROUP. Modulul de iniializare specific este c0c.obj,iarbibliotecilespecificesuntcc.libimathc.lib. medium Se vor genera mai multe segmente de cod, cu numele SURSA_TEXT, unde SURSA este numele fiierului surs C sau ASM. n ASM, dac directiva .code are un parametru, se va genera un segment de cod cu numele respectiv. Se consider c n cuprinsul segmentului de cod respectiv, este activ o directiv ASSUME CS: cu numele segmentului respectiv. Se genereaz grupul DGROUP care include segmentele _DATA i _BSS (accesibile n ASM prin .data i .data?). Pointerii la date sunt implicit de tip near, iar pointerii la funcii sunt implicit de tip far. Apelurile de funcii sunt implicit de tip far. Registrul DS este iniializat n modulul c0 cu DGROUP. Modulul de iniializare specific este c0m.obj, iar bibliotecile specifice sunt cm.lib i mathm.lib. large Se vor genera mai multe segmente de cod, cu numele SURSA_TEXT, unde SURSA este numele fiierului surs C sau ASM. n ASM, dac directiva .code are un parametru, se va genera un segment de cod cu numele respectiv. Se consider c, n cuprinsul segmentului de cod respectiv, este activ o directiv ASSUME CS: cu numele segmentului respectiv. Se genereaz grupul DGROUP care include segmentele _DATA i _BSS (accesibile n ASM prin .data i .data?). Toi pointerii sunt implicit de tip far. Apelurile de funcii sunt implicit de tip far. Registrul DS este iniializat n modulul c0 cu DGROUP. Modulul de iniializare specific este c0l.obj, iar bibliotecile specificesuntcl.libimathl.lib. huge Se vor genera mai multe segmente de cod, cu numele SURSA_TEXT, unde SURSA este numele fiierului surs C sau ASM. n ASM, dac directiva .code are un parametru, se va genera un segment de cod cu numele respectiv. Se vor genera mai multe segmente de date, cu numele SURSA_DATA, unde SURSA este numele fiierului surs C sau ASM. Nu se genereaz segmente _BSS, toate datele fiind definite n segmentele SURSA_DATA. Se consider c n cuprinsul modulului respectiv este activ o directiv ASSUME CS:SURSA_TEXT, DS:SURSA_DATA. Grupul de segmente DGROUP nu include segmentele SURSA_DATA. Asamblorul TASM genereaz ns un

245 Capitolul7
segment cu numele _DATA, corespunztor directivei .data, care se include n grupul DGROUP. Registrul DS este iniializat n modulul c0 cu DGROUP, iar la fiecare intrare ntro funcie C (inclusiv main), registrul DS este iniializat cu SURSA_DATA. Evident, la intrarea n funciile ASM, va trebui fcut o iniializare cu DGROUP, salvnd n prealabil registrul DS n stiv i refcndu l la ieirea din funcia ASM. Pentru accesul la segmentele de date definite n C se poate folosi operatorul SEG aplicat unei variabile externe sau direct numele segmentului,nformaSURSA_DATA. Toi pointerii sunt implicit de tip far i sunt normalizai, adic offsetul este redus la intervalul de valori 0...15. Astfel, corespondena segment:offset cu adresa fizic de memorie devine biunivoc. Incrementarea/decrementarea pointerilor se va reflecta acum att n offset, ct i n adresa de segment, spre deosebire de modelele celelalte, la care incrementarea/decrementarea pointerilor de tip far acioneaz numai asupra offsetului. Este posibil deci definirea unor structuri de date de dimensiuni mai mari dect 64K, ceea ce la celelaltemodeledememorienuesteposibil. Apelurile de funcii sunt implicit de tip far. Modulul de iniializare specific este c0h.obj,iarbibliotecilespecificesuntch.libimathh.lib. O problem special poate aprea la modelele de memorie aazise de date mici (small i medium). Se pot defini date de orice fel, att n clasa de alocare automatic (cu spaiu rezervat n stiv, deci accesibile prin registrul de segment SS), ct i n clasa de alocare static (cu spaiu rezervat ntrunul din segmentele ce compun grupul DGROUP, deci accesibile prin registrul de segmentDS). n aceste modele de memorie, pointerii ctre date sunt de tip near, deci ei memoreaz numai deplasamentele obiectelor n cadrul segmentelor respective (de date, pentru obiecte n clasa static, respectiv de stiv, pentru obiecte n clasa auto). Dac se acceseaz obiecte (date) prin pointeri, nu se poate ti n ce tip de segmente sunt definite aceste obiecte. Problema este rezolvat (n cazul modelelor small i medium) prin generarea segmentelor de aa manier, nct adresele de nceput ale segmentului de stiv i ale grupului DGROUP s coincid. Practic, pe parcursul execuiei, registrele DS i SS vor aveaaceeaivaloare. S observm c problema nu se pune n cazul modelului tiny (exist un unic segment) i nici n cazul modelelor large i huge (toi pointerii sunt de tip far). De asemenea, problema nu se pune n cazul modelului de cod mic i date mari compact, deoarece pointerii ctre funcii vor conine (indiferent de locul unde sunt definii) deplasamente n cadrul unicului segment de cod care se genereaz. Apelurile de funcii prin pointeri se traduc n simple salturi

Programarenlimbajdeasamblare 246 indirecte intrasegment (instruciuni de tip call word ptr ...). Exemple de asemeneaapelurisunt:
call call word ptr [bp-4] word ptr _p ; ; ; ; Apel indirect, pointer in clasa auto Apel indirect, pointer in clasa static

Dac se fac indirectri multiple, acestea presupun definirea unor pointeri ctre pointeri ctre funcii, adic a unor pointeri ctre date. Aceti pointeri vor fi deci de tip far i vor fi ncrcai i derefereniai totdeauna ca adrese complete (segmentioffset). n concluzie, s reinem c, la modelele small i medium, registrele DS i SS vor avea acelai coninut la execuie. Mediul integrat ofer opiunea Options/Compiler/Code Generation/Assume DS not equal SS, care esterecomandabilsfieplasatpeDefault for memory model. Pe lng segmentele descrise mai sus, modulul de iniializare c0 mai definete o serie de segmente, folosite la iniializare, la ieirea n sistemul de operare etc, dar care nu prezint interes din punct de vedere ASM. Se poate vedea exact ce segmente se genereaz, studiind fiierul surs c0.asm, furnizatnkitulimplementriiC(ndirectorul\examples\startup). Cnd exist ndoieli asupra a ceea ce se genereaz concret de ctre compilatorul C, se poate folosi opiunea S la compilare n linia de comand, obinnduse n acest fel un fiier surs ASM, corespunztor modulului C respectiv sau se poate lansa Turbo Profilerul din mediu integrat, care, ntre alte informaii,furnizeazicodulASMgenerat.

7.4Oaplicaiemixtcutipuridedatesimple
Pentru a fixa ideile, considerm un exemplu de program, compus dintrun modul C i un modul ASM, care va fi detaliat n trei cazuri de modele: compact, medium i huge. Codul ASM pentru celelalte modele se deduce simplu: la modelul small se trateaz datele ca la medium i codul ca la compact, iar la modelullargesetrateazdatelecalacompacticodulcalamedium. Modulul surs C, presupus n fiierul test1c.c, este acelai n toate situaiile, i anume:
#include <stdio.h> extern int f (int); extern int (*pf) (int); extern int *g (void); extern int *gg (void); extern int ext_i; extern int ext_n; int extc_i = 2;

247 Capitolul7
int *ff (int *pi) { *pi *= 2; return pi; } void main(void) { int n; printf("\nIntroduceti un intreg: "); scanf("%d",&n); n = f(n); printf("Valoarea dubla este: %d\n",n); n = (*pf)(n); printf("Valoarea dubla este: %d\n",n); printf("Variabila externa initializata este: %d\n", ext_i); ext_n = 5; printf("Variabila externa neinitializata este: %d\n", *g()); printf("Valoarea dubla este: %d\n", *gg()); }

Modulele ASM sunt presupuse n fiierele test1ca.asm, test1ma.asm i, respectiv,test1ha.asm,corespunztoaremodelelorcompact,mediumihuge. n aplicaia studiat, se consider urmtoarele entiti de program definite n ASM: funciaf,cutipulinticuunparametrudetipint pointerullafunciepf,iniializatcuadresafuncieif funciag,cutipulintifrparametri funciagg,cutipulint*ifrparametri ntregulext_i,iniializatcuvaloarea11 ntregulext_n,neiniializat. nmodululC,seconsiderurmtoareleentiti: ntregulextc_i,iniializatcuvaloarea2 funciaff,cutipulint*icuunparametrudetipint*. Funcia ff primete o adres de ntreg i nmulete cu 2 ntregul de la adresarespectiv,ntorcndadresaprimit. Funcia f primete un ntreg, afieaz la consol mesajul ntregul este: i valoarea variabilei extc_i. Se ntoarce programului apelant valoarea dubl a parametruluiprimit. Funciagntoarceprogramuluiapelantadresavariabileiext_n. Funcia gg apeleaz funcia ff, cu parametrul adresa variabilei ext_n, ntorcnd programului apelant adresa returnat de funcia ff, adic adresa aceleiaivariabileext_n. Programul principal, scris n C, citete de la consol un ntreg n i apeleaz de dou ori funcia f, cu parametrul n, prima dat direct, iar a doua oar prin

Programarenlimbajdeasamblare 248 pointerul pf. n ambele apeluri, valoarea ntoars este depus n aceeai variabil n. Se afieaz apoi variabila ext_i, se modific explicit variabila ext_n i se apeleaz funciile g i gg, afind la ntregii de la adresele ntoarse de acestefuncii,adicvariabilaext_n. Afirile din modulul ASM sunt realizate prin macroinstruciunile putsi i puti, care presupun datele adresabile prin registrul DS. Rezult, deci, c aplicaia vatrebuiscuprindimodululobiectio.obj(veziAnexaB).

7.4.1Dezvoltarenmodeluldememoriecompact
Modulultest1ca.asm,corespunztormodeluluicompact,este:
.model compact include io.h public _f, _pf, extrn _ff: near, sablon _f struc _bp dw ? _ip dw ? n dw ? sablon_f ends .data _ext_i dw _pf dw .data? _ext_n dw ? ; intreg neinitializat .code _f proc near push bp mov bp, sp ; Pozitionare bp pentru acces mov ax, [bp].n ; Preluare parametru add ax, ax ; Dublare putsi <cr,lf,'Intregul este: '> mov bx, DGROUP:_extc_i ; Segmentul este DGROUP puti bx ; Tipareste ; intregul (bx) putsi <cr, lf> pop bp ret ; (ax) = rezultat _f endp _g proc near mov dx, DGROUP lea ax, DGROUP:_ext_n ret _g endp _gg proc near mov ax, DGROUP ; Segment ; Offset ; Rezultat in (dx:ax)

_g, _gg, _ext_i, _ext_n _extc_i: word ; Sablon pentru accesul ; in stiva, in procedura ; de tip near f 11 _f ; intreg initializat ; Pointer near initializat cu ; adresa (offset-ul) lui _f

; Pregatire parametri ; apel

249 Capitolul7
push lea push call add ret _gg endp end ax ax,DGROUP:_ext_n ax near ptr _ff sp, 4 ; Segment ; ; ; ; Offset Apel _ff Descarcare stiva Rezultat in (dx:ax)

Deoarece modelul de memorie este compact, toate apelurile de funcii sunt de tip near, pointerul pf la funcie este de tip near, iar toi pointerii la date sunt de tip far. Funciile f, g i gg vehiculeaz adrese de 32 de bii, transmise prin stivsauntoarseprinperechea(DX:AX). Programulvaafialaconsoltextul:
Introduceti un intreg: 13 Intregul C este: 2 Valoarea dubla este: 26 Intregul C este: 2 Valoarea dubla este: 52 Variabila externa initializata este: 11 Variabila externa neinitializata este: 5 Valoarea dubla este: 10

Presupunnd directorul mediului C ca fiind C:\BC, secvena de linii de comandpentrudezvoltareaaplicaieieste:


bcc -mc -c -Ic:\bc\include test1c.c tasm test1ca.asm/ml tlink c:\bc\lib\c0c test1c test1ca io,test1c,,c:\bc\lib\cc

7.4.2Dezvoltarenmodeluldememoriemedium
Modulultest1ma.asm,corespunztormodeluluidememoriemedium,este:
.model medium include io.h public _f, _pf, _g, _gg, _ext_i, _ext_n extrn _ff: far, _extc_i :word sablon_f struc _bp dw ? ; Sablon pentru accesul _ip_cs dd ? ; in stiva, in procedura n dw ? ; de tip far _f sablon_f ends .data _ext_i dw 11 ; intreg initializat _pf dd _f ; Pointer far initializat cu ; adresa completa a lui _f .data? _ext_n dw ? ; intreg neinitializat .code _f proc far

Programarenlimbajdeasamblare 250
push mov mov add mov putsi puti putsi pop retf endp bp bp, sp ; ax, [bp].n ; ax, ax ; bx, DGROUP:_extc_i; <cr, lf,'Intregul C bx ; <cr, lf> bp ;

Pozitionare bp pentru acces Preluare parametru Dublare Segmentul este DGROUP este: '> Tipareste intregul (bx) (ax) = rezultat

_f _g

proc far lea ax,DGROUP:_ext_n retf _g endp _gg

; Offset ; Rezultat in (ax)

_gg end

proc far lea ax, DGROUP:_ext_n ; Pregatire parametri apel push ax ; Offset call far ptr _ff ; Apel _ff add sp, 2 ; Descarcare stiva retf ; Rezultat in (ax) endp

Ceea ce se schimb fa de modelul anterior este faptul c apelurile i pointerii la funcii sunt de tip far, iar adresele i pointerii la variabile sunt de tip near. ablonul de acces n stiv se modific, innd cont c un apel far salveaz i registrul CS n stiv. Pointerul pf se definete cu directiva dd (define doubleword). Adresa lui ext_n (offset) este ntoars de funciile g i gg prin AX. Secvenadeliniidecomandeste:
bcc -mm -c -Ic:\bc\include test1c.c tasm test1ma.asm/ml tlink c:\bc\lib\c0m test1c test1ma io,test1m,,c:\bc\lib\cm

7.4.3Dezvoltarenmodeluldememoriehuge
Modulultest1ha.asm,corespunztormodeluluihuge,este:
.model huge include io.h public _f, _pf, _g, _gg, _ext_i, _ext_n extrn _ff:far, _extc_i:word sablon_f struc _bp _ip_cs n sablon_f ends dw ? dd ? dw ? ; Sablon pentru accesul ; in stiva, in procedura ; de tip far _f

251 Capitolul7
.data _ext_i _pf .data? _ext_n .code _f proc far push bp mov bp,sp push ds push es push bx mov ax,DGROUP mov ds,ax mov add push mov mov mov ax,[bp].n ax,ax ax ax,SEG _extc_i es,ax bx,es:_extc_i ; ; ; ; Pozitionare bp pentru acces Salvare ds Salvare es Salvare bx dw ? ; intreg neinitializat dw 11 dd _f ; intreg initializat ; Pointer far initializat cu ; adresa completa a lui _f

; Segment local de date ; Preluare parametru ; Dublare ; Salvare rezultat ; Seg. asociat lui _extc_i

; Preluare _extc_i ; ; Sirul din macroinstructiunea putsi se defineste intr-o ; directiva .data, deci in segmentul local, de aceea ds ; trebuie sa indice DGROUP ; putsi <cr,lf,'Intregul C este: '> puti bx ; Tipareste intregul (bx) putsi <cr,lf> pop ax ; Rezultat pop pop pop bx es ds ; Refacere bx ; Refacere es ; Refacere ds ;(ax) = rezultat

pop bp retf _f endp _g proc far mov dx,DGROUP lea ax,DGROUP:_ext_n retf _g endp _gg proc far mov ax,DGROUP push ax lea ax,DGROUP:_ext_n push ax call far ptr _ff add sp,4

; Segment ; Offset ;Rezultat in (dx:ax)

; Pregatire parametri ; Segment local ; Offset ; Apel _ff ; Descarcare stiva

Programarenlimbajdeasamblare 252
retf _gg endp end ; Rezultat in (dx:ax)

Se observ c, n procedura f, unde se face acces la date, se poziioneaz explicit registrul DS pe grupul de segment DGROUP, pentru a putea utiliza macroinstruciunile de afiare i se ncarc explicit n ES adresa de segment a variabilei externe ext_c. Registrele DS i ES se salveaz la intrarea n funcie iserefacnaintedentoarcereanprogramulapelant. Secvenadeliniidecomandeste:
bcc -mh -c -Ic:\bc\include test1c.c tasm test1ha.asm/ml tlink c:\bc\lib\c0h test1c test1ha io,test1h,,c:\bc\lib\ch

7.5Oaplicaiemixtcutipuridedatestructurate
SeconsidermodululsursC,presupusnfiierultest2c.c:
#include <string.h> struct tips { int n; char *sir; }; void f (struct tips *); struct tips *g (struct tips *); struct tips * (*pg) (struct tips *) = g; struct tips a = { 100, "Iata un sir..." }; struct tips *g(struct tips *x) { static int contor = 0; contor++; f(x); (x -> n) ++; if(contor % 2) strupr(x -> sir); else strlwr(x -> sir); f(x); return x; }

Se consider tipul de structur tips, care cuprinde un ntreg i un pointer la un ir de caractere. Structura a este iniializat cu valoarea 100, respectiv cu irul Iataunsir.... Funcia de tip void f, scris n ASM, primete o adres de structur i afieaz la consol cele dou cmpuri (ntreg i ir de caractere) cu ajutorul macroinstruciunilorputiiputs,definitenfiierulheaderio.h. Funcia g, scris n C, primete adresa x a unei structuri i realizeaz urmtoareleoperaii:

253 Capitolul7
apelulfuncieif,cuparametruladresax(carevaafiastructuraindicatde x) incrementareacmpuluinumericalstructuriidelaadresax modificarea succesiv a irului de caractere din structura indicat de variabila x, din litere mici n litere mari i succesiv acest lucru este realizatprinincrementareamodulo2auneivariabilelocalestatice apelulfuncieif,cuparametruladresax(carevaafiastructuraindicatde x). Programulprincipal,scrisnASM,realizeazurmtoareleoperaii: apeleazfunciagnmoddirect,cuparametruladresastructuriia pregtete n stiv adresa ntoars de g (deci adresa structurii a), pentru unapelviitor apeleaz funcia f n mod direct, cu parametrul ntors de apelul lui g (deci cuadresastructuriia) apeleaz indirect funcia g, prin intermediul pointerului pg, cu parametrul adresapregtitanteriornstiv apeleaz funcia f, cu parametrul ntors de apelul indirect al lui g (deci cu adresastructuriia).

7.5.1Dezvoltarenmodeluldememoriecompact
Modulultest2ca.asm,corespunztormodeluluidememoriecompact,este:
.model include public extrn tips tips compact io.h _f, _main _g: near, _a: far, _pg: word ; Sablon pentru ; structura tips

struc n dw ? sir dd ? ends dw ? dw ? dd ?

sablon struc _bp _ip _adr_struc sablon ends .stack .code _f 1024 proc near push bp mov bp, sp push ds push di push si

; Sablon pentru acces ; in stiva ; Parametrul

; Salvari ; registre ; folosite

Programarenlimbajdeasamblare 254
; ; incarcare adresa far din stiva ; les di, dword ptr [bp]._adr_struc ; ; Acces la membrul n al structurii ; mov ax, es:[di].n ; ; Tiparire n ; putsi <cr, lf, 'Intregul este: '> puti ax putsi <cr, lf, 'Sirul este: '> ; Acces la membrul sir (pointer far) al structurii ; lds si, dword ptr es:[di].sir ; ; Tiparire sir ; call far ptr puts_proc pop si ; Refaceri pop di ; registre pop ds ; folosite pop bp ret _f endp _main proc near mov ax,DGROUP ; Pregatire parametri push ax ; Segmentul structurii a lea ax,DGROUP:_a push ax ; Offset-ul structurii a call near ptr _g ; Apel g add sp,4 ; Descarcare stiva ; ; g intoarce un pointer far in (dx:ax) ; Este pregatit acest pointer in stiva, ; pentru un apel viitor al lui g ; (altfel ar fi trebuit salvat intr-o zona de date) ; push dx ; Segment push ax ; Offset ; ; Pregatire parametru pentru apelul lui f ; push dx ; Segment push ax ; Offset call near ptr _f ; Apel f add sp, 4 ; Descarcare stiva ; ; Acum se face apelul lui g, indirect, prin pointerul ; de tip near pg, cu parametrul de tip pointer far, ; pregatit anterior in stiva

255 Capitolul7
; ; Descarcare stiva ; ; g intoarce un pointer far in (dx:ax) ; Se pregateste acest pointer in stiva, pentru apelul lui f ; push dx ; Segment push ax ; Offset call near ptr _f ; Apel f add sp, 4 ; Descarcare stiva ret ; Terminare program _main endp end call add word ptr _pg sp, 4

Pointerii la date sunt de tip far, iar pointerul lka funcie este de tip near. Se observ declararea simbolului extern a ca o etichet de tip far, ceea ce este n concordan cu convenia c numele unei variabile este sinonim cu adresa variabileirespective. Laconsolsevatipri:
Intregul este: 100 Sirul este: Iata un Intregul este: 101 Sirul este: IATA UN Intregul este: 101 Sirul este: IATA UN Intregul este: 101 Sirul este: IATA UN Intregul este: 102 Sirul este: iata un Intregul este: 102 Sirul este: iata un sir... SIR... SIR... SIR... sir... sir...

Secvenadeliniidecomandeste:
bcc -mc -c -Ic:\bc\include test2c.c tasm test2ca.asm/ml tlink c:\bc\lib\c0c test2ca test2c io,test2c,,c:\bc\lib\cc

7.5.2Dezvoltarenmodeluldememoriemedium
Modulultest2ma.asm,corespunztormodeluluimedium,este:
.model medium include io.h public _f, _main extrn _g:far, _a:near, _pg:dword tips struc n dw ? sir dw ? tips ends sablon struc

; Sablon pentru ; structura tips

Programarenlimbajdeasamblare 256
_bp _ip_cs _adr_struc sablon ends .stack .code _f proc far push mov push push ; mov ; mov ; putsi puti putsi ; mov ; call pop pop pop retf _f endp _main proc far lea push call add far ptr puts_proc si ; Refaceri di ; registre bp si,word ptr DGROUP:[di].sir <cr,lf,'Intregul este: '> ax <cr,lf,'Sirul este: '> ax,DGROUP:[di].n di,word ptr [bp]._adr_struc 1024 dw ? dd ? dw ? ; Sablon pentru acces ; in stiva ; Parametrul

bp bp,sp di si

; Registre ; folosite

ax,DGROUP:_a ax far ptr _g sp,2

; ; ; ;

Pregatire parametru Offset-ul structurii a Apel g Descarcare stiva

; ; g intoarce un pointer near n (ax) ; push ax ; Offset ; ; Pregatire parametru pentru apelul lui f ; push ax ; Offset call far ptr _f ; Apel f add sp,2 ; Descarcare stiva ; call dword ptr _pg add sp,2 ; Descarcare stiva ; ; g intoarce un pointer near in (ax) ;

257 Capitolul7
push call add sp,2 retf _main endp end ax far ptr _f ;Offset ; Apel f ; Descarcare stiva ; Terminare program

Diferenele fa de cazul precedent rezult din faptul c funciile i pointerii la funcii sunt de tip far, iar adresele variabilelor i pointerii la date sunt de tip near. Simbolulexterna(detipstructur)sedeclarnASMcaoetichetdetipnear. Secvenadeliniidecomandeste:
bcc -mm -c -Ic:\bc\include test2c.c tasm test2ma.asm/ml tlink c:\bc\lib\c0m test2ma test2c io,test2m,,c:\bc\lib\cm

7.5.3Dezvoltarenmodeluldememoriehuge
Modulultest2ha.asm,corespunztormodeluluihugeeste:
.model huge public _f, _main extrn _g:far, _a: far, _pg:dword include io.h tips struc n sir tips ends sablon struc _bp _ip_cs _adr_struc sablon ends .stack .code _f proc far push mov push push push ; mov mov ; les mov putsi di,dword ptr [bp+6] ax,es:[di].n <cr,lf,'Intregul este: '> ax,DGROUP ds,ax 1024 dw ? dd ? ; Sablon pentru ; structura tips

dw ? dd ? dd ?

; Sablon pentru acces ; in stiva ; Parametrul

bp bp,sp ds di si

;Salvari ;registre ;folosite

Programarenlimbajdeasamblare 258
puti putsi lds call ; pop pop pop pop retf _f endp _main proc far push push mov mov ; mov mov push lea push call add sp,4 ; ; ; ; ; ; ; ; ; ax,SEG _a es,ax es ax,es:_a ax far ptr _g ; Pregatire parametru ; Segmentul structurii a ; Offset-ul structurii a ; Apel g ; Descarcare stiva si di ds bp ; Refaceri ; registre ; folosite ax <cr,lf,'Sirul este: '> si,dword ptr es:[di].sir far ptr puts_proc

ds es ax,DGROUP ds,ax

; Comutare pe segmentul ; propriu de date

g intoarce un pointer far in (dx:ax) Este pregatit acest pointer in stiva, pentru un apel viitor al lui g (altfel ar fi trebuit salvat intr-o zona de date) push dx push ax ; Segment ; Offset

Pregatire parametru pentru apelul lui f push push call add dx ax far ptr _f sp,4 ; ; ; ; Segment Offset Apel f Descarcare stiva

; ; ; ; ;

Acum se face apelul lui g, indirect, prin pointerul de tip near pg (care e in alt segment de date), cu parametrul de tip pointer far, pregatit anterior in stiva mov ax, SEG _pg mov es,ax call dword ptr es:_pg add sp,4

; ; g intoarce un pointer far in (dx:ax) ; Se pregateste acest pointer in stiva, pentru apelul lui f ; push dx push ax

259 Capitolul7
call add ; pop es pop ds retf _main endp end far ptr _f sp,4

Diferena fa de celelalte cazuri este c datele externe nu mai sunt n mod necesar definite n acelai segment (grup) cu datele din modulul ASM. Adresarea structurii a i a pointerului pg trebuie fcut n consecin, folosind operatorul SEG pentru luarea segmentelor n care aceste simboluri sunt definite. Secvenadeliniidecomandeste:
bcc -mh -c -Ic:\bc\include test2c.c tasm test2ha.asm/ml tlink c:\bc\lib\c0h test2ha test2c io,test2h,,c:\bc\lib\ch

7.6Dezvoltareantrunlimbajmixt(CiASM)
Mediul de dezvoltare Borland C ofer posibilitatea inserrii de cod ASM n programe surs C. Fiecare instruciune ASM trebuie precedat de cuvntul cheieasmsausfieinclusntrunblocdetipASM,deforma:
asm { ; Instructiuni ASM }

Acest model de dezvoltare este foarte comod, deoarece vizibilitatea obiectelor definite n C se extinde i asupra blocurilor ASM. Astfel, putem folosi nume de variabile, nume de parametri formali ai funciilor etc., fr a mai scrie caracterul _ n faa numelor respective. Se evit astfel i secvenele de intrareireveniredinfuncii,caresuntrealizateautomatdecompilatorulC. O alt facilitate este accesul direct din C asupra registrelor procesorului, realizat prin variabilele C predefinite _AX, _BX, _CX etc., care pot fi utilizate, de exemplu,ninstruciunideatribuire. Exist restricii de utilizare asupra etichetelor. Mai precis, etichetele trebuie definitecaeticheteC,decinafarablocurilorASM. Ca i la dezvoltarea n module separate, programatorul trebuie s gestioneze explicit modelele de memorie, n sensul definirii precise a adreselor far sau near. Pentru aceasta, se utilizeaz modelele de memorie C i/sau cuvintele cheienearifaraleimplementriiBorlandC.

Programarenlimbajdeasamblare 260 Un modul dezvoltat n aceast manier este scris de fapt ntrun limbaj mixt (C i ASM). De altfel, fiierele surs de acest tip se creeaz de obicei cu extensia.CAS(delaCiASM). Pentru exemplificare, s considerm o funcie de cutare liniar ntrun tablou dentregi.nlimbajulC,amscrieaceastfuncienforma:
int cauta (int *a, size_t n, int x) { int i; for (i = 0; i < n; i++) if (x == a[i]) return i; /* S-a gasit intregul x */ return -1; /* Nu s-a gasit intregul x */ }

Dorim acum s scriem aceeai funcie n limbajul CAS. Presupunem pentru nceputunmodeldedatemici.Implementareafuncieiesteurmtoarea:
int cauta (int near *a, size_t n, int x) { asm { push si /* Salvari */ push cx /* registre */ push dx mov mov jcxz mov sub } reluare: asm { add cmp si, 2 [si], dx */ */ */ */ */ */ */ */ */ */ */ */ */ Element curent */ din tablou */ Comparam cu */ cel cautat */ Nu este, se reia */ bucla */ Am iesit din bucla */ Daca ZF a fost 1, */ calculam */ indicele elementului */ gasit */ ca n - CX - 1 */ Salt la iesire */ si, a cx, n not_gasit dx, x si, 2 */ */ */ */ */ */ */ Adresa near */ a tabloului */ Numar elemente */ Test n == 0 */ Element cautat */ Pornim cu o pozitie */ mai la stanga */

loopnz reluare jnz mov sub dec jmp } not_gasit: asm final: mov not_gasit ax, n ax, cx ax final ax, -1

*/ Nu s-a gasit */ */ elementul x */

261 Capitolul7
asm { pop pop pop } return } dx cx si _AX */ Refaceri */ */ registre */ */ Instructiune */

Se observ tehnica de scriere a buclei de cutare (prefixul LOOPNZ) i calculul indicelui elementului gsit, ca diferen dintre dimensiunea n a tabloului i valoarea incrementat a contorului CX la ieirea din bucl. Revenirea n funcia apelant se face cu instruciunea C return _AX (ne amintim conveniadentoarcereadatelorsimple). Un punct important este ncrcarea adresei tabloului. Dac adresa este near, o ncrcm cu o instruciune MOV (n stiv se gsete deplasamentul n cadrul segmentului curent de date). n cazul unui model de date mari, n stiv se gsete un pointer far (o variabil de tip DoubleWord), caz n care ncrcarea sarfacecuoinstruciune:
les si, a */ Adresa far a tabloului */

Comparareaelementuluicurentcucelcutatsarscrie:
cmp es:[si], dx */ Comparam cu cel cautat */

n fine, ar mai trebui salvat i restaurat registrul ES, iar prototipul funciei ar trebuiscrisnforma:
int cauta (int far *a, size_t n, int x);

Modificrile de mai sus transform funcia ntruna adecvat modelelor de datemari. Unprogramdetestpentrufunciademaisussarscriengenul:
#include <stdio.h> int x [ ] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, }; #define NREL(a) (sizeof(a)/sizeof(a[0])) void main (void) { int i, val = 6; i = cauta (x, NREL(x), val); if (i > 0) printf("Elementul %d se afla pe pozitia %d din tablou\n", val, i); else printf("Elementul %d nu se afla in tablou\n", val); }

Trebuie totui observat c aceast tehnic mixt de dezvoltare are i dezavantaje. Un modul CAS este destul de greu de ntreinut, iar transportul su n alt mediu de dezvoltare dect Borland ar putea crea probleme de

Programarenlimbajdeasamblare 262 compatibilitate. Tehnica mixt merit folosit atunci cnd avem de implementat secvene relativ scurte de program, pentru care nu se justific un modul (fiier surs)separat.

7.7PerformanenASMiC
n acest subcapitol, vom face o analiz comparativ a unui algoritm implementat n C i ASM. Algoritmul ales este un algoritm de sortare intern, anume sortarea prin partiionare i interschimbare, numit i sortare rapid (quicksort). Algoritmul este recursiv i se poate implementa foarte comod att n C, ct i n ASM. O implementare polimorfic a acestui algoritm este oferit i de biblioteca standardalimbajuluiC.

7.7.1ImplementareanC
Varianta C considerat va fi de asemenea polimorfic (capabil s sorteze tablourideoricefel).PrototipulfuncieiCeste:
void qsort (void *tab, size_t n, size_t size, PFCMP cmp);

Semnificaiaparametriloreste: tabadresadenceputatabloului nnumruldeelementealetabloului sizedimensiuneanocteiaunuielement cmppointerlaofuncieexterndecomparaie,definitprin:


typedef int (*PFCMP) (void *a, void *b);

Funcia de comparaie (scris de utilizator) primete adresele a dou elemente din tablou i ntoarce o valoare negativ, zero sau pozitiv, dup cum elementul de la prima adres este mai mare, egal sau mai mic dect elementul de la a doua adres. Sensul noiunilor mai mare, egal sau mai mic este complet abstract, fiind definit de utilizator chiar prin funcia de comparaie. Pentru transferul datelor, se vor utiliza funciile ajuttoare swap i copy, listate maijos.
typedef unsigned char BYTE; void swap(void *a, size_t size, int i, int j) { /* Schimba a[i] cu a[j]. Elementele tabloului a[] au size octeti */ register BYTE *b = ((BYTE *)a) + i * size; register BYTE *c = ((BYTE *)a) + j * size; register BYTE temp; while(size--) {

263 Capitolul7
temp = *b; *b++ = *c; *c++ = temp; } } void copy(void *a, void *b, size_t size) { /* Copiaza obiectul de la adr. b in cel de la adr. a. Obiectele au size octeti */ memcpy(a, b, size); }

Algoritmul de sortare rapid este recursiv. Funcia care implementeaz algoritmul recursiv primete ca date de intrare o parte a tabloului care trebuie sortat, prin adresa de nceput i doi indici notai left i right. Iniial, funcia seapeleazcuindicii0in1. Se alege un element arbitrar al tabloului v, numit pivot, notndul cu mark (variante uzuale sunt v[left] sau v[(left+right)/2]). Se partiioneaz tabloul n raport cu mark, n sensul c toate elementele aflate la stnga lui mark s fie mai mici sau egale cu acesta, iar toate elementele aflate la dreapta lui mark s fiemaimarisauegalecuacesta. n acest moment, pivotul se afl pe poziia sa final, iar tabloul este partiionat n dou subtablouri. Se apeleaz acum aceeai funcie, cu indicii left i k1, respectiv k+1 i right, unde k este indicele pivotului n urma partiionrii. n felul acesta, se sorteaz cele dou subtablouri. Dac left >= right,algoritmulseoprete. Algoritmul se poate mbunti n felul urmtor. S pornim cu doi indici i i j, iniializai cu left i, respectiv, cu right. Ct timp v[i] < mark, incrementm i, apoi, ct timp v[j] > mark, decrementm j. Dac acum i <= j, interschimbm v[i] cuv[j],actualizndsimilarindiciiiij.Totacestprocescontinupncndi>j. Acum se apeleaz recursiv funcia, cu indicii left i j, respectiv i i right (dac left<j,respectivdaci<right). n implementarea polimorfic, deoarece la compilare nu se cunoate dimensiunea unei nregistrri, se aloc spaiu dinamic pentru nregistrarea mark, copiinduse elementul din mijlocul tabloului i elibernd spaiul la ieirea dinfuncie. O mbuntire posibil a metodei este recurgerea la o metod direct de sortare, dac lungimea tabloului este inferioar unei limite prestabilite, evitnd astfel apelul recursiv. De exemplu, la un tablou de 1000 de nregistrri, cnd dimensiunea partiiei ajunge 2, se vor face 500 de apeluri ale funciei, pentru a sorta de fiecare dat un tablou de 2 elemente. Este mult mai eficient dac acest lucru se face direct. n implementarea de fa, sa ales limita 2, caz n care cele dou nregistrri se compar direct. Pentru eficien, variabilele

Programarenlimbajdeasamblare 264 intens folosite n etapa de partiionare (i i j) sunt declarate n clasa register. Implementareaesteurmtoarea:
void quick_sort(BYTE *v, size_t size, int left, int right, PFCMP cmp) { register int i, j; BYTE *mark; i = left; j = switch(j - i) case 0: case 1: right; { return; if(cmp(v + i*size, v + j*size) > 0) swap(v, size, i, j); return; default: break;

} mark = (BYTE *) malloc(size); copy(mark, v + ((left + right)/2)*size, size); do { while(cmp(v + i*size, mark) < 0) i++; while(cmp(v + j*size, mark) > 0) j--; if(i <= j) swap(v, size, i++, j--); } while (i <= j); if(left < j) quick_sort(v, size, left, j, cmp); if(i < right) quick_sort(v, size, i, right, cmp); free(mark); } void Quick_C (void *v, size_t n, size_t size, PFCMP cmp) { quick_sort(v, size, 0, (int) n-1, cmp); }

7.7.2ImplementareanASM
S considerm acum implementarea algoritmului de sortare rapid n limbaj de asamblare, ntro versiune specializat (pentru tablouri de ntregi). Toate adresele se consider de tip near, fiind offseturi n cadrul segmentului adresat prinregistrulDS. Algoritmul este acelai cu cel prezentat n 7.7.1, implementarea ASM urmrind exact programul C. Variabilele din descrierea n C a algoritmului sunt meninutenregistreleprocesoruluiinstiv. Parametrii se transmit prin stiv, conform ablonului definit n program, iar stiva este descrcat de programul apelant. Aceast modalitate de apel permite ca

265 Capitolul7
funcia ASM s poat fi apelat din C, dac modelul cu care se lucreaz este small.
.286 .model small .code public _qasm ; ; qasm(int v[], int left, int right) ; sablon struc _bp_ip dw 2 dup(?) v dw ? left dw ? right dw ? sablon ends _qasm proc near push bp mov bp,sp push a ; ; Asignarea variabilelor ; ; i = si, j = di, v = bx, ; left, right = n stiv ; mov bx, [bp].v mov si, [bp].left mov di, [bp].right mov ax, di sub ax, si cmp ax, 1 jng et00 jmp et1 et00: je et0 jmp gata et0: ; ; Sunt 2 elemente ; Se compara si eventual se schimba ; shl si, 1 ; intregii sunt pe shl di, 1 ; doi octeti mov ax, [bx][si] ; v[left] cmp ax, [bx][di] ; v[right] jnle aici jmp gata ; Sunt O.K. aici: xchg mov jmp ax, [bx][di] [bx][si], ax gata ; Daca nu, se ; schimba ; si gata ; right = left + 1 ; left = right: iesire

mark = dx ; ; ; ; ; ; v i = left j = right compara right - left cu 1

; mai mare: se executa ; rutina normal

Programarenlimbajdeasamblare 266
et1: ; ; Sunt mai mult de doua elemente ; mov ax, si add ax, di shr ax, 1 push bx shl ax, 1 add bx, ax mov dx, [bx] pop bx _do: while_i: shl cmp jge si, 1 [bx][si], dx end_i

; Calcul ; (left + right)/2 ; Adresa se aduna ; la v ; mark = v[(left+right)/2] ; ; ; ; ; ; ; Ciclu do Ciclu while dupa v[i] < mark Compara v[i] cu mark Sfarsit ciclu daca v[i] >= mark

shr si, 1 inc si jmp while_i end_i: shr si, 1 while_j: shl cmp jle di, 1 [bx][di], dx end_j

; Daca nu, se face i++ ; si se reia ; Ciclu while dupa ; v[j] > mark ; Compara v[j] cu mark ; Sfarsit ciclu daca ; v[j] <= mark ; Daca nu, se face j-; si se reia

shr di, 1 dec di jmp while_j end_j: shr di, 1 ; cmp jg ; shl shl mov xchg mov shr shr inc dec _while: cmp si, di jle _do cmp jge [bp].left, di not_rec di, 1 si, 1 ax, [bx][si] ax, [bx][di] [bx][si], ax si, 1 di, 1 si di si, di _while

; Compara i cu j ; Salt daca i > j ; ; ; ; ; intregii sunt pe doi octeti Schimba v[i] cu v[j]

; i++ ; j-; Compara i cu j ; Daca i <= j se continua ; ciclul _do ; Compara left cu j ; Salt daca j <= left

267 Capitolul7
; j > left: se apeleaza ; _qasm pentru ; prima partitie ; ; ; qasm(v, left, j) push di push [bp].left push bx call _qasm add sp, 6 not_rec: cmp jge si, [bp].right gata ; ; ; ; ; Compara i cu right Salt daca i >= right i < right: se apeleaza _qasm pentru a doua partitie ; j ; left ; v

; ; qasm(v, i, right) ; push [bp].right ; right push si ; i push bx ; v call _qasm add sp,6 gata: popa pop bp ret _qasm endp end ; ; ; Interfata cu limbajul C se realizeaza prin functia Quick_a, ; care are un prototip asemanator cu functia Quick_C. ; ; void Quick_a(void *v, size_t n, size_t size, PFCMP cmp); ; { ; qasm(v, 0, (int) n-1); ; } ;

7.7.3Comparareaperformanelor
Evaluarea performanelor unui algoritm de sortare intern const n estimarea sau n msurarea numrului de operaii de comparaie ntre elemente i a numrului de operaii de copiere sau interschimbare a dou elemente. Aceste evaluri se efectueaz n trei situaii distincte de tablouri: tablou aleator, tablou deja sortat (cazul cel mai favorabil) i tablou sortat invers (cazul cel mai defavorabil). n cazul de fa, au fost considerate dou dimensiuni de tablouri, de 1000 i respectiv10000dentregi,msurnduseitimpuldeexecuie.

Programarenlimbajdeasamblare 268 Pentru algoritmul de sortare rapid considerat, sau testat 3 variante: prima (Quick_C) este implementarea polimorfic prezentat n 7.7.1, a doua (Quick_a) este implementarea n ASM din 7.7.3, iar a treia variant (qsort) este funcia polimorfic din biblioteca standard C. Rezultatele sunt date n tabelele 7.2,7.3i7.4. Dimensiune=1000 Alg. Quick_C Quick_a qsort Timp 0.3 0.0 0.2 Comp 12901 12901 13321 Move 2443 2443 Copy 608 0 Timp 4.3 0.8 2.9 Dimensiune=10000 Comp 187234 187234 172655 Move 31508 31508 Copy 6219 0

Tabelul 7.2 Performane n cazul unui tablou aleator

Dimensiune=1000 Alg. Quick_C Quick_a qsort Timp 0.1 0.0 0.1 Comp 8963 8963 10819 Move 488 488 Copy 488 0 Timp 2.3 0.4 2.2

Dimensiune=10000 Comp 121821 121821 145262 Move 4095 4095 Copy 4095 0

Tabelul 7.3: Performane n cazul unui tablou sortat

Dimensiune=1000 Alg. Quick_C Quick_a qsort Timp 0.2 0.0 0.1 Comp 8972 8972 10818 Move 988 988 Copy 489 0 Timp 2.4 0.4 2.3

Dimensiune=10000 Comp 121832 121832 145260 Move 9094 9094 Copy 4095 0

Tabelul 7.4: Performane n cazul unui tablou sortat invers Din tabelele de mai sus rezult c eficiena tuturor celor trei implementri este ridicat. Atunci cnd timpul de rulare este ns esenial, trebuie folosit implementarea specializat n limbaj de asamblare. Implementarea Quick_a asigur un timp de rulare de 3.5 ori mai scurt n cazul unui tablou aleator i de 5.5 ori mai scurt n cazul unui tablou sortat sau sortat invers. Toate implementrileauutilizatmodeluldememoriesmall.

Capitolul8
InterfaacusistemuldeoperareDOS
n acest capitol, vor fi prezentate elementele de baz ale interaciunii programelor scrise n ASM cu cele dou componente software de baz dintrun calculator personal, subsistemul BIOS i sistemul de operare DOS, fr a se prezenta o list exhaustiv a funciilor de sistem sau BIOS. Asemenea liste de funciisuntdisponibilenmanualespecificealesistemuluideoperareDOS.

8.1ComponenteledebazalesistemuluiDOS
ComponentelesistemuluideoperareDOSsunt: DOS-BIOS. Aceast component este memorat pe disc ntrun fiier cu numele IBMBIO.COM sau IBMIO.SYS sau IO.SYS, depinznd de furnizor. Ea conine driverele pentru dispozitivele CON (tastatur i display), PRN (imprimant), AUX (interfa serial) i CLOCK (ceas de timp real). De asemenea, modulul DOSBIOS conine drivere pentru discurile flexibile i pentru discul hard. Accesul la aceste drivere va implica apelul unor rutine din ROMBIOS (poriunea de BIOS aflat n ROM,careconineproceduriledependentedehardware). DOS-Kernel (nucleul DOS). Aceast component este memorat pe disc n fiierul IBMDOS.COM sau MSDOS.SYS, depinznd de furnizor i conine funcii de acces la fiiere, funcii de intrare/ieire la nivel de caracter etc. Aceste funcii opereaz ntrun mod independent de hardware(evorbadefunciileDOSapelateprininstruciuniINT21H). Interpretorul de comenzi (Shell) standard. Este memorat pe disc n fiierul COMMAND.COM. Interpretorul este cel care afieaz prompterul DOS la consol, acceptnd i executnd comenzi de la tastatur. Interpretorul de comenzi este la rndul su compus din 3 pri: poriunea rezident, care conine handlere (rutine de tratare) pentru aciunile CTRLBreak (CTRLC) de la tastatur i pentru erori critice (erori la citirea sau scrierea la dispozitive periferice,

35 Capitolul8
cum ar fi discurile sau imprimanta). Erorile critice conduc la afiarealaconsolaunormesajedeforma:
Error on device ... Abort, Retry, Fail ?

poriunea tranzitorie, care afieaz prompterul la consol (de exemplu C:\>), citete comanda de la consol i o execut. Poriunea tranzitorie conine comenzile DOS interne (de genul DIR, TYPE, COPY etc.). Cnd un program executabil i ncheie execuia, controlul revine poriunii rezidente a interpretorului de comenzi, care verific o sum de control, detectnd astfel dac s a modificat cumva poriunea tranzitorie din memorie. n caz afirmativ,poriuneatranzitorieserencarcdepedisc rutina de iniializare, care este ncrcat n memorie o dat cu ncrcarea sistemului DOS de pe disc. Cnd operaia de ncrcare sa terminat, aceast component nu mai este necesar ispaiulrespectivdememorievafifolositnaltescopuri. Comenzileacceptatedeinterpretoruldecomenzistandardsuntde3tipuri: comenzi interne (cum ar fi COPY, DIR, RENAME etc.), care nu au corespondentnfiiereexecutabilepedisc comenzi externe, coninute n fiiere disc de tip .EXE sau .COM, care sunt ncrcate n memorie n zona TPA (zona de procese tranzitorii) fiiere de comenzi indirecte (.BAT), care sunt fiiere text ce conin comenzi interne, externe sau alte invocri de fiiere de comenzi indirecte. Interpretorul testeaz nti dac linia introdus de la tastatur este o comand intern. Dac nu este, se caut un fiier cu extensia .COM, .EXE sau .BAT (n aceast ordine), nti n directorul curent, apoi n toate directoarele specificate n comanda PATH. Dac nu se gsete nici un fiieradecvat,seafieazlaconsolmesajul:
Bad command or file name

Dac sa identificat un fiier cu extensia .COM sau .EXE, interpretorul ncarc fiierul executabil n memorie utiliznd funcia EXEC (4BH) a sistemului de operare i i d controlul. Funcia EXEC construiete n memorie un bloc special numit PSP (Program Segment Prefix), n zona de procese tranzitorii TPA, la prima adres disponibi. Se ncarc apoi programul executabil, imediat dup PSP i se execut operaiile de relocare, adic se ajusteaz valorile simbolurilor care conin referine la memorie, conform cu poziia fizic din memorie unde a fost ncrcat programul.

Programarenlimbajdeasamblare 36 ROM-BIOS. Aceast component este rezident n memoria ROM a calculatorului i conine partea de autotestare de la punerea sub tensiune (numit i POST, de la Power-On Self Test), programul primar de ncrcare de pe disc (bootstrap), rutinele de intrare/ieire de nivel sczut (dependente de hardware) etc. n general, aceast component nu rezid numai pe placa de baz a calculatorului, anumite poriuni fiind localizate pe plachetele de interfee furnizate de productor.

8.2ncrcareasistemuluiDOS
La punerea sub tensiune, procesorul ncepe s execute instruciuni de la adresa fix 0FFFF0H (care este situat n memoria de tip ROM). La aceast adres se gsete o instruciune JMP FAR la o poriune de program din ROMBIOS, numit POST (Power- On Self Test). Acest cod execut teste hardware pentru unitatea central, memoria intern, dispozitivele periferice etc., nscriindtotodatvectoriidentreruperepentruntreruperilehardwareexterne.

Figura 8.1 Harta memoriei imediat dup ncrcarea programului Disk-Bootstrap

37 Capitolul8
Se trece apoi la execuia unei zone de cod numit ROM-Bootstrap (ncrctor primar), care testeaz dac exist dischete n unitile de disc flexibil. Dac nu, se trece la examinarea discului hard. Se citete apoi primul sector de pe pista 0 a discului (fie de pe discul flexibil, fie de pe discul hard). Acest sector este numit sector de boot (Boot Sector) i conine un alt program ncrctor (numit Disk-Bootstrap), precum i informaii despre organizarea discului. Programul Disk-Bootstrap este citit n memorie la nivel fizic i i se d controlul. Unele calculatoare de generaie mai nou permit specificareaordiniideexaminareaunitilordedisc. Trebuie remarcat c, n acest moment, sistemul de operare nu este ncrcat n memorie, deci nu se dispune de nici o funcie DOS. Harta memoriei la acest momentesteilustratnFigura8.1. Programul ncrctor citete primul sector al directorului rdcin, determinnd dac primele dou fiiere din acest director sunt, n ordine: IO.SYS (sau IBMBIO.COM sau IBMIO.SYS) i MSDOS.SYS (sau IBMDOS.COM), care conin componentele DOS-BIOS i DOS-Kernel ale sistemului de operare. Dac aceste fiiere nu sunt identificate, se afieaz la consol mesajul:
Non-System disk or disk error Replace and strike any key when ready

Dac fiierele sunt identificate corect, programul Disk-Bootstrap le citete n memorieitransfercontrolullapunctuldestartalmodululuiIO.SYS. Componenta DOS-BIOS const din dou module: BIOSul propriuzis i modulul SYSINIT. Harta memoriei din acest moment este ilustrat n Figura 8.2.

Programarenlimbajdeasamblare 38

Figura 8.2 Harta memoriei dup ncrcarea modulelor IO.SYS i MSDOS.SYS

39 Capitolul8
Figura 8.3 Harta memoriei nainte de ncrcarea interpretorului de comenzi ncrcarea celor dou fiiere se face la adrese mici de memorie, deoarece nu se cunoate nc dimensiunea memoriei. Modulul SYSINIT, apelat de ctre partea de iniializare a BIOSului, determin dimensiunea memoriei continue i se autorealoc (adic se mut) la o adres mare de memorie (ctre coada memoriei). n continuare, modulul SYSINIT mut modulul MSDOS.SYS din locul unde a fost ncrcat iniial n poziia sa final din memorie, suprascriind vechea copie a modulului SYSINIT (ncrcat iniial la adrese mici), precum i alte poriuni iniiale de cod coninute n IO.SYS i care nu mai sunt necesare. Se d apoi controlul poriunii de iniializare a modului DOS-Kernel. Acesta iniializeaz tabelele interne i zonele de lucru ale sistemului DOS, seteaz vectorii de ntrerupere de pe nivelele 20H...2FH (adic ntreruperile soft specifice funciilor DOS) i iniializeaz driverele rezidente ale dispozitivelor periferice(discuri,consoletc.).ControlulrevineapoimodululuiSYSINIT. n acest moment, sistemul DOS este operaional, deci modulul SYSINIT poate apela funcii DOS. SYSINIT ncearc s deschid fiierul CONFIG.SYS, care conine diverse comenzi specifice prin care se poate configura sistemul. n acest fiier, se pot specifica drivere suplimentare care s fie ncrcate (aanumitele drivere instalabile), se poate specifica numrul de buffere pentru disc, numrul maxim de fiiere care pot fi deschise simultan, numele fiierului care conine interpretorul de comenzi etc. Dac fiierul CONFIG.SYS este identificat n directorul rdcin, el este ncrcat n memorie i se execut fiecare comand specificat. Harta memoriei din acest momentesteilustratnFigura8.3. Dup ce toate driverele instalabile au fost ncrcate, SYSINIT nchide toate fiierele (dispozitivele) folosite i apoi redeschide dispozitivele consol (CON), imprimant (PRN) i interfa serial (AUX), asociindule handlerele de fiiere 0 (standard input), 1 (standard output), 2 (standard error), 3 (standard list) si 4 (standard auxiliary). Handlerele 0, 1, 2 sunt asignate la dispozitivul CON, handlerul 3 este asignat la dispozitivul PRN, iar handlerul 4 la dispozitivul AUX. Aceste handlere pot fi reasignate prin apeluri de funcii sistem adecvate. n final, modulul SYSINIT apeleaz funcia EXEC a sistemului de operare, pentru a ncrca i a executa interpretorul standard de comenzi. O dat ce interpretorul a fost ncrcat, el afieaz la consol prompterul specific i ateapt introducerea de comenzi de la tastatur. Poriunea tranzitorie din

Programarenlimbajdeasamblare 40 COMMAND.COM este ncrcat peste SYSINIT, care nu mai este necesar. nfinal,imagineamemorieiesteceadinFigura8.4.

Figura 8.4 Imaginea final a memoriei

8.3StruturabloculuiPSP(ProgramSegmentPrefix)
Blocul PSP este caracteristic ambelor categorii de programe executabile (.EXE i .COM), fiind o zon de 256 de octei care precede imaginea din memorie a programului executabil. La lansarea n execuie a unui program, adresele DS:0000 i ES:0000 indic nceputul blocului PSP asociat programului. PSPul este construit de ctre funcia EXEC la ncrcarea programului de pe disc. StructuraPSPuluiesteilustratnFigura8.5.

41 Capitolul8

Figura 8.5 Structura blocului PSP SemnificaiacmpurilordinFigura8.5esteurmtoarea: octeii 01 conin codul unei instruciuni INT 20H (ieire n DOS), care permite unui program executabil s se ncheie cu o instruciune JMP sau RET la adresa PSP:0 aceast tehnic nu mai este actual, pentru terminareaunuiprogramutilizndusefunciaDOS4CH octeii 23 conin dimensiunea memoriei de baz continue (vrful memoriei), n paragrafe de cte 16 octei aceast informaie este folositnprocesuldencrcareaprogramuluiexecutabil

Programarenlimbajdeasamblare 42 octetul4rezervat octeii 59 conin codul unei instruciuni CALL de tip far la dispecerul defunciiDOS octeii 0AH0DH conin adresa far a rutinei de ncheiere (accesibil prin INT 22H) ntreruperea 22H este o alt modalitate perimat de a ncheia programele executabile actualmente se utilizeaz funcia DOS 4CH octeii 0EH10H conin adresa far a rutinei de tratare a apsrii tastelor CtrlBreak (accesibil prin INT 23H) CtrlBreak provoac terminareaforataprogramelorncursdeexecuie octeii 12H15H conin adresa far a rutinei de tratare a erorilor critice (accesibil prin INT 23H) (erorile critice sunt de genul: nu exist dischet nunitateadediscflexibilisedocomanddegenulDIRA:) octeii16H2BHrezervai octeii 2CH2DH conin adresa de segment a blocului de environment acesta este o zon de memorie n format text, care conine informaii de genul: ci (path) active, specificarea interpretorului de comenzi, specificarea prompterului de comenzi etc ntre altele, n blocul de environment se gsete calea complet a fiierului care conine programul executabil n felul acesta, se poate ti n program numele fiierului executabil din care a fost ncrcat programul acesta este suportul fizic al argumentului argv[0] al funciei main de la programele C octeii2EH5BHrezervai octeii 5CH6BH i 6CH7FH reprezint aa numiii parametri formatai sunt utilizai pentru dou blocuri de control fiiere (FCBuri), care reprezint o modalitate perimat de lucru cu fiiere disc actualmente se utilizeaz funcii de prelucrare a fiierelor orientate pe handlere(vezi8.7) octetul 80H reprezint lungimea (numrul de caractere) coninute n zonadeparametrineformatai octeii 81H0FFH reprezint zona de parametri neformatai aceast zon conine caracterele introduse n linia de comand dup numele fiierului executabil (aa numita coad a comenzii) prin aceast zon, un program executabil are acces la parametrii din linia de comand (acesta este suportul oferit de DOS pentru parametrii numii generic argc i argv de la funcia main a programelor C) parametrii din linia de comand nu cuprind parametrii de redirectare a dispozitivelor standard de intrare i de ieire primii 43 de octei de la offsetul 80H mai sunt utilizai implicit i ca Zon de Transfer Disc (DTA) aceast zon este folosit de unele funcii de acces la disc i se poate poziiona ntrun spaiu rezervat de ctre utilizator prin funcia DOS 1AH de

43 Capitolul8
asemenea, adresa curent a zonei DTA poate fi citit cu funcia DOS 2FH

8.4StructuraprogramelordetipCOM
Programele de tip COM corespund modelului de memorie tiny, n care exist un singur segment i toate salturile i apelurile de proceduri sunt de tip near. Fiierul disk conine exclusiv modulul care se ncarc, fr alte informaii suplimentare,cancazulfiierelordetipEXE. ImagineamemorieiunuiprogramCOMesteprezentatnFigura8.6.

Figura 8.6 Imaginea memoriei ocupate de un program COM Programele COM au ca punct de start adresa near 100H, adic imediat dup blocul PSP. Indicatorul SP este plasat la adresa 0FFFEH, deci pe ultimul cuvnt adresabil.Acestcuvnteiniializatcu0. UnprogramCOMsepoatencheianunuldinurmtoarelemoduri: prinapelalfuncieistandarddeterminare(funciaDOS4CH) prinapelalntreruperiisoftINT20H prin execuia unei instruciuni RETN, dac registrul SP conine valoarea iniial 0FFFEH. Cuvntul de la adresa 0FFFEH fiind 0, instruciunea RETN va da controlul la adresa near 0, adic la primul octet din PSP. Acolo ns se gsete codul unei instruciuni INT 20H, careprovoacrevenireanDOS.

Programarenlimbajdeasamblare 44 Programele COM nu necesit relocare, deoarece toate simbolurile relative sunt deplasamente n cadrul unui segment unic. Simpla ncrcare a registrului CS estesuficient. ablonuldedezvoltarepentruprogrameleCOMeste:
_TEXT ORG ASSUME start: jmp init ; ; Aici se pun eventuale definitii de date ; init: ; ; Aici se pune codul propriu-zis ; mov ax, 4C00H ; Apel functie DOS int 21H ; pentru terminare ; program _TEXT ENDS end start ; Eticheta de start segment para CODE 100H CS:_TEXT, DS:_TEXT, ES:_TEXT, SS:_TEXT

Programele de tip COM (ca de altfel i cele de tip EXE) i rezerv toat memoria disponibil. n unele situaii, e necesar reducerea la minim a memoriei rezervate, care se poate realiza printrun apel al funciei DOS 4AH. ablonuldedezvoltarealprogramelorCOMvafiurmtorul:
_TEXT ORG ASSUME start: jmp init ; ; Aici se pun definitii de date ; proc near ; ; Aici se pune codul propriu-zis ; mov ax, 4C00H int 21H main endp ; ; Aici se pun alte proceduri (daca e cazul) ; mov mov mov ah, 4AH bx, offset end_mem cl, 4 ; ; ; ; ; ; Functie redimensionare memorie Limita pana unde se pastreaza Dimensiunea memoriei se specifica in segment para CODE 100H CS:_TEXT, DS:_TEXT, ES:_TEXT, SS:_TEXT

main

init:

45 Capitolul8
shr inc int mov jmp bx, cl bx 21H sp, offset end_mem main ; ; ; ; ; ; paragrafe de 16 octeti Mai punem unul de siguranta Apel propriu-zis Initializare sp

; ; Rezervam o stiva de 512 octeti, care sa cuprinda ; si spatiul dintre etichetele init si init_mem, care se poate ; suprascrie dupa incarcarea programului init_mem: db (512 - (init_mem - init)) dup (?) ; ; Pana aici rezervam memoria ; end_mem: _TEXT ENDS end start

8.5StructuraincrcareafiierelorEXE
Programele de tip EXE pot fi ncrcate n orice locaie de memorie i se compun din mai multe segmente. Acest fapt impune ajustarea tuturor instruciunilorcareconinadresedesegment,cumarfi: JMP/CALLFARPTRnume MOVreg,SEGnume MOVreg_seg,valoare. Acest proces se numete relocare i se execut la ncrcarea programului n memorie.PunctuldestartpoatefioarecareiestestabilitprindirectivaEND. Este evident c un fiier de tip EXE trebuie s conin, pe lng programul propriuzis, i informaii despre simbolurile relocabile, adresa de start, adresa segmentului de stiv etc. Aceste informaii sunt grupate n prima parte a fiierului, numit header al fiierului EXE. Structura acestui header este ilustratnTabelul8.7.

Programarenlimbajdeasamblare 46

Offset 0 2 4 6 8 0AH

Dim. 2 2 2 2 2 2

Coninut 4DH5AH PartPag PageCnt ReloCnt HdrSize MinMem

Semnificaie Semnturfiier.EXE(MZ) Lungimefiiermodulo512 Lungime n pagini de 512 octei,inclusivheaderul Numr de elemente tabeladerelocare din

Dimensiune header n para grafede16octei Necesar minim de memorie peste sfritul programului (nparagrafe) Necesar maxim de memorie peste sfritul programului (nparagrafe) Deplasamentsegmentstiv ValoareSPlaexecuie Sumdecontrol ValoareIP(adresdestart) Deplasamentsegmentcod Poziia n fiier a tabelei de relocare(uzual1CH) Indicator overlay (0 pentru moduleledebaz) Tabela de relocare Caractere pn la limita de paragraf

0CH

MaxMem

0EH 10H 12H 14H 16H 18H 1AH ?

2 2 2 2 2 2 2 4*

ReloSS ExeSP ChkSum ExeIP ReloCS TablOff Overlay offs ... offs seg ... seg

Tabelul 8.7 Structura headerului fiierelor .EXE Primii doi octei identific tipul fiierului. Urmtorii 4 octei conin lungimea fiierului (inclusiv headerul), n pagini de 512 octei i, respectiv, modulo 512. Suma de control reprezint suma cu semn schimbat a tuturor cuvintelor din fiier,perminduncontrolalvaliditiifiierului.

47 Capitolul8
Valorile ReloSS i ReloCS reprezint deplasamentele segmentelor de stiv i cod fa de adresa de segment de ncrcare (segmentele pot fi n orice ordine). Valorile ExeSP i ExeIP reprezint coninutul registrelor SP i IP la intrare n execuie. Aceste valori sunt deduse din dimensionarea segmentului de stiv i din directiva END a modulului de program principal (care precizeaz etichetadestart). Tabela de relocare cuprinde adresele tuturor cuvintelor care trebuie ajustate, adrese precizate prin offset n cadrul segmentului curent i prin deplasamentul segmentului respectiv fa de adresa de segment iniial. Tabela de relocare are ReloCnt (vezi [6]) elemente, ncepe la poziia TablOff (vezi [18H]) n fiier iocupReloCnt4octei. Headerul este completat cu octei fr semnificaie, pn la o limit de paragraf. Relocarea programului este realizat de funcia EXEC a sistemului de operare (funcia4BH)iconstnurmtorulalgoritm: SecreeazunPSPcufunciaDOS26H Se citesc 1CH octei din fiierul .EXE (aanumita poriune formatat a headerului),ntrozonlocaldememorie Se determin lungimea modulului = ((PageCnt 512) (HdrSize 16)) PartPag Sedetermindeplasamentulnfiieralmodulului=(HdrSize16) SeselecteazoadresdesegmentSTART_SEG(uzualPSP+10H) SecitetemodululdeprogramnmemorielaadresaSTART_SEG:0000 Se seteaz poziia de citire din fiier la nceputul tabelei de relocare (TablOff) Pentrufiecareelementaltabeleiderelocare(ReloCnt): seciteteelementuldintabelcadoucuvinte(I_OFF,I_SEG) se determin adresa actual de memorie a elementului care trebuie relocatRELO_SEG=(START_SEG+I_SEG) se citete elementul care trebuie relocat, deci cuvntul de la adresa (RELO_SEG:I_OFF) se adun START_SEG la acest cuvnt (se ajusteaz adresa de segment) sedepunevaloareaajustatnapoilaadresa(RELO_SEG:I_OFF) Se aloc memorie suplimentar pentru program, conform MaxMem i MinMem Seiniializeazregistrelesemnificativeisedcontrolulprogramului: ES=DS=PSP SS=START_SEG+ReloSS SP=ExeSP

Programarenlimbajdeasamblare 48 CS=START_SEG+ReloCS IP=ExeIP. PoziionarearegistrelorCSiIPserealizeazprintrosecvendeforma:


PUSH PUSH RETF START_SEG + ReloCS ExeIP ; Intrare in executie

8.6ProgramedetipTSR(TerminateandStayResident)
Programele de tip EXE sau COM obinuite sunt ncrcate n memorie n zona de procese tranzitorii (TPA) i ocup memoria pn la ncheierea execuiei. Mai concret spus, la execuia funciei DOS 4CH, memoria ocupat de programesteeliberatioferitsistemuluiDOS. Programele de tip TSR (care sunt tot programe de tip EXE sau COM) rmn n memorie o durat nedeterminat de timp (sunt rezidente). Ele sunt activate de ctre evenimente externe, cum ar fi acionarea unei taste special destinate (hot-key) sau expirarea unui interval de timp. Pentru ca s rmn rezident, un program trebuie si ncheie execuia cu un apel al funciei DOS 31H, n care se precizeaz (n registrul DX) numrul de paragrafe de memorie care se pstreazrezidente. Sedeosebesc,deci,urmtoarelenoiuni: activarea unui program TSR reprezint ntreruperea programului care se ruleaz n mod curent (nu neaprat un program utilizator), cu salvarea corespunztoare a ntregului context i transferul controlului ctreprogramulTSR dezactivarea unui program TSR reprezint refacerea contextului programuluintreruptitransferulcontroluluictreacesta instalarea unui program TSR reprezint ncrcarea de pe disc i ncheiereaexecuieiprinapelulfunciei31H dezinstalarea unui program TSR reprezint eliberarea memoriei ocupatedeunprogramTSRinstalatanterior.

8.6.1ActivareaidezactivareaprogramelorTSR
Activarea se face, de obicei, ca urmare a acionrii unei taste special destinate. Se utilizeaz ntreruperea pe nivelul 9 (asociat tastaturii), care se producelafiecareapsareiridicareauneitaste. Interaciunea cu ntreruperea 9 se face prin modificarea (furtul) vectorului de ntrerupere cu o rutin proprie de tratare, care apeleaz rutina veche, testnd dac sa apsat tasta special de activare a TSRului. Rutina veche trebuie apelat, deoarece ea convertete codul de scanare produs de tastatur ntrun cod ASCII, actualizeaz bufferul tastaturii, gestioneaz starea tastelor Ctrl, Shift, Alt etc. De asemenea, este posibil s fie instalate mai multe TSRuri

49 Capitolul8
unul peste altul, activate prin taste speciale diferite, care au modificat la rndul lor vectorul 9 de ntrerupere. Prin apelul rutinei vechi, se iau n considerare i acesteTSRuriinstalateanterior. ApelulrutineivechisefacesimulndoinstruciuneINT,prinsecvena:
pushf call dword ptr cs:oldint

undeoldintesteolocaiencaresasalvatadresavechiirutinedetratare. Trebuie observat faptul esenial c, la activarea unui TSR, dintre registrele de segment nu se poate conta dect pe coninutul registrului CS. Acesta este poziionat n urma invocrii rutinei de tratare pe nivelul 9, n timp ce restul registrelor de segment sunt poziionate conform programului care a fost ntrerupt. De aceea, programele TSR se dezvolt de obicei sub forma unui unic segment, adresabil prin registrul CS. Aceasta explic prezena prefixului de segment din instruciunea CALL de mai sus. Dac este cazul, se pot ncrca i alte registre de segment cu valori adecvate, dar aceste valori trebuie memorate la etapa de instalare, obligatoriu n locaii din segmentul adresabil prinregistrulCS. Secvena de parcurgere a mai multor programe TSR instalate este ilustrat n Figura8.8. NonreentranafunciilorDOS Problemele speciale legate de activarea TSRurilor sunt n principal datorate faptului c sistemul DOS nu este reentrant. Aceasta nseamn c, dac se ntrerupe execuia unei funcii DOS i din rutina de ntrerupere se apeleaz o alt funcie DOS, este posibil ca funcionarea sistemului de operare s fie compromis. Soluia const n activarea TSRurilor numai n situaii sigure, adic, teoretic, atunci cnd nu se execut funcii DOS. Se utilizeaz o combinaie dedoutehnici: Prima tehnic se bazeaz pe un flag de sistem, numit uzual flag INDOS, care menine un contor al nivelurilor de adncime ale apelurilor de funcii DOS. Adresa flagului INDOS poate fi obinut prin funcia DOS 34H. Teoretic, ar trebui s activm TSRul doar atunci cnd acest contor este nul. Din pcate, flagul INDOS este diferit de zero mai tot timpul, datorit interpretorului de comenzi care ateapt introducerea comenzilor de la tastatur prin execuia funciei DOS 0AH (citire ir de caractere). A doua tehnic se bazeaz pe ntreruperea soft 28H, care este apelat periodic de ctre sistem atunci cnd interpretorul ateapt comenzi de la consol. Se consider c, n momentul apelului acestei ntreruperi, este relativsigursseactivezeprogramulTSR.

Programarenlimbajdeasamblare 50

Figura 8.8 Parcurgerea succesiv a mai multor rutine de tratare pe nivelul 9 n loc de a activa programul TSR imediat dup ce a aprut cererea de activare, se va memora aceast cerere ntro variabil, urmnd ca ulterior, cnd sunt ndeplinite condiiile de activare, s se fac activarea propriuzis. Concret, se va modifica rutina de tratare pe nivelul 28H, astfel nct s se testeze variabila care memoreaz cererea de activare, i, dac exist cerere, s se activeze TSRul. Aciunicriticentimp O alt categorie de probleme o reprezint aciunile critice n timp. Acestea sunt activiti ale sistemului de operare sau ale BIOSului, a cror

51 Capitolul8
ntrerupere ar putea duce la funcionri defectuoase. Concret, este vorba despre rutinele de nivel sczut pentru operaiile cu discurile, realizate prin ntreruperea de BIOS 13H i de operaiile de nivel sczut asupra displayului, realizateprinntrerupereaBIOS10H. Problema se rezolv prin modificarea ntreruperilor 13H i 10H, adugnduse poziionarea la 1 a unui flag propriu, pe durata ct aceste rutine de tratare sunt active. Programul TSR trebuie activat doar dac flagul respectiv este nul. Structuranoilorrutinedetratarevafi:
new13 proc mov ; ; pushf ; call dword ptr cs:old13; mov flag_bios, 0 ; ; retf 2 ; ; ; new13 endp far flag_bios, 1 Marcheaza operatii critice in curs Simulare executie apel INT 13H Marcheaza sfarsit operatii critice Revenire cu flagurile intoarse de apelul lui old13

n care old13 este o variabil DWORD care memoreaz adresa vechii rutine de tratare, iar flag_bios este o variabil rezervat n segmentul adresabil prin CS. Se observ ncheierea procedurii prin RETF 2, i nu prin IRET (dei este procedur de tratare a unei ntreruperi), ceea ce menine flagurile aa cum au fostntoarsedeapelulvechiirutinedepenivelul13H. Evitareaactivriirecursive O problem de baz la implementarea programelor TSR o reprezint evitarea activrii recursive. Dac programul TSR a fost activat i se afl n execuie, este posibil s apar o nou cerere de activare (de exemplu, se apas din nou tasta special de activare). n aceast situaie, programul TSR nu trebuie reactivat. Problema se rezolv prin meninerea unui alt flag propriu, careeste1peduratactTSRulesteactiv. Comutareacontextuluilaactivareiladezactivare Programele TSR pot fi destul de complexe, n sensul c pot apela orice funcie DOS, pot lucra cu fiiere disc etc. Aceasta presupune ca activarea s fie nsoit de o salvare ct mai complet a contextului programului ntrerupt i de o comutare a contextului ctre programul TSR. Similar, la dezactivarea TSR ului,trebuierefcutcompletcontextulprogramuluintrerupt. Problemelecaretrebuieavutenvederesunturmtoarele: salvareairestaurarearegistrelorprogramuluintrerupt salvarea i restaurarea unor structuri de date specifice programului ntrerupticomutareapestructurilespecificeprogramuluiTSR:

Programarenlimbajdeasamblare 52 salvarea adresei PSPului programului ntrerupt i marcarea ca fiind activaPSPuluiprogramuluiTSR salvareazoneiDTAicomutareapezonaDTAaTSRului comutareapestivaproprieaprogramuluiTSR salvarea unei poriuni (uzual 64 de octei) din stiva programului ntrerupt ntrozonproprie salvareaconinutuluiecranului. Toate operaiile de mai sus trebuie realizate n sens invers la cedarea controluluictreprogramulntrerupt. Pentru citirea i marcarea PSPului i a zonei DTA sunt disponibile funcii DOS specifice. Salvarea unei poriuni din stiva programului ntrerupt este necesar, deoarece sistemul DOS lucreaz cu stive proprii alocate la adrese fixe i este posibil ca ntreruperea s fi aprut atunci cnd registrele SS:SP erau poziionate pe o asemenea stiv. Un apel al unei alte funcii DOS va utiliza poate aceeai stiv DOS, ceea ce va distruge coninutul stivei apelului anterior. Salvarea i restaurarea ecranului apare ca necesar n situaia n care TSRul afieaz ceva la consol (ceea ce se ntmpl destul de frecvent). Salvarea presupune un transfer ntre memoria video i o zon proprie. De obicei, programele TSR lucreaz n mod text, deci se va utiliza memoria video de la adresa 0B0000H (la ecrane monocrom) i 0B8000H la ecrane color. Funcie de modul video curent, se salveaz 25 sau 43 de linii de ecran, fiecare a 80 de cuvinte (un simbol pe ecran este codificat prin caracterul ASCII extins i printr un octet de atribut, care precizeaz culoarea sau efecte speciale de afiare). Este indicat s se salveze i modul video curent, precum i poziia cursorului pe ecran. Dac este instalat un driver de mouse, trebuie salvat poziia cursorului mouseului i inhibat afiarea mouseului pe durata ct TSRul este activ. Dac este cazul, se poate comuta pe o rutin (handler) proprie de tratare aevenimentelordelamouse. Pentru citirea i setarea cursoarelor, a modurilor video etc., se utilizeaz funciiBIOSspecifice.

8.6.2InstalareaidezinstalareaprogramelorTSR
Instalarea unui program TSR nseamn ncrcarea lui n memorie i pregtirea condiiilor pentru activare. Dezinstalarea unui TSR nseamn eliberarea memoriei ocupate la instalare. Trebuie remarcat c dezinstalarea trebuie fcut de ctre un alt program dect cel rezident (eventual o alt instan a aceluiai program). Evitareainstalriirepetate Programul TSR este memorat ntrun fiier executabil. Nimic nu ne mpiedic s lansm n execuie acest program de mai multe ori. Totui, nu se poate accepta ca un TSR s fie instalat de mai multe ori, deoarece sar consuma n

53 Capitolul8
mod inutil memorie. Pe de alt parte, secvena de activare din Figura 8.8 ar fi compromis(careinstansevaactiva?) Un program TSR trebuie, deci, s testeze dac nu este instalat deja n memorie isrefuzeinstalareanacestcaz. Testarea se face definind o secven particular de caractere (o semntur) la un offset fix n cadrul unicului segment care compune programul TSR. Identificarea locului n care programul TSR este eventual rezident se poate face numai prin examinarea vectorului de ntrerupere care declaneaz activarea (uzual, INT 9). Citind acest vector, identificm adresa de segment a rutinei de tratare, adic adresa de segment a programului TSR care este eventual instalat. Comparnd semntura programului curent cu semntura din segmentul indicat de vectorul INT 9, se determin dac TSRul este deja instalat(veziFigura8.9). Aceast tehnic este posibil numai dac TSRul deja instalat este ultimul din lanuldeTSRuricareaumodificatvectoruldentreruperepenivelul9. O alt soluie, mai general, dar mai lent, este parcurgerea tuturor blocurilor de memorie alocate de ctre sistem. Aceste blocuri sunt structuri de date specifice DOS care conin informaii depre deintorul blocului, deci crui modul de program ia fost alocat blocul respectiv. Astfel, se caut de fapt n memorie numele fiierului executabil care conine programul TSR. n acest capitol,vomutilizaprimatehnicdeidentificare. Instalarea trebuie s salveze o serie de date necesare procesului de activare, cum ar fi adresa de PSP i a zonei DTA a programului TSR, adresa stivei programului TSR etc. De asemenea, trebuie rezervat spaiu pentru stiva TSR, pentru salvarea ecranului, pentru copiile vectorilor de ntrerupere modificai etc. Instalarea TSRului mai presupune i modificarea vectorilor de ntrerupere 9, 10H, 13H etc. cu adresele propriilor rutine de tratare. n final, se calculeaz dimensiunea spaiului de memorie care trebuie s rmn rezident i se ncheieexecuiacuapelulfuncieiDOS31H.

Programarenlimbajdeasamblare 54

Figura 8.9 Tehnica de testare a instalrii DezinstalareaTSRurilor La identificarea situaiei de TSR deja instalat, multe programe se mulumesc safiezelaconsolunmesajdegenul:
Program XXXXX already installed !

iapoisincheieexecuianmodnormal. O variant mai evoluat este ca, la a doua invocare a programului TSR, s se realizeze dezinstalarea primei instane, dup care a doua instan s se ncheiecuieirenormalnDOS. Dezinstalarea trebuie s elibereze spaiul de memorie alocat primei instane. Trebuie mai nti eliberat blocul de environment (mediu) al TSRului instalat. Adresa blocului de environment se gsete la un offset fix n cadrul PSPului (vezi 8.3). La instalare, este necesar memorarea adresei blocului PSP ntro variabil aflat la un offset fix. Dup ce sa eliberat blocul de environment, se

55 Capitolul8
elibereaz memoria propriuzis cu funcia 49H i se ncheie execuia cu funciaDOS4CH.Figura8.10ilustreazacestproces. De observat c, funcie de testul asupra instalrii TSRului, se va face instalarea instanei curente sau dezinstalarea instanei anterior instalate. Tot la dezinstalare se refac vectorii 9, 10H, 13H i 28H, care au fost modificai la instalare.

8.6.3ablondedezvoltarepentruprogrameTSR
Urmtorul program reprezint un ablon de dezvoltare pentru aplicaiile TSR uzuale, fiecare aciune fiind comentat intensiv. Trebuie observat accesul la bufferul tastaturii, realizat prin pointerii de la adresele absolute 400:1AH i 400:1CH, care indic cele dou capete ale bufferului. Bufferul tastaturii se afl n spaiul de adrese 400:1EH400:3CH, fiind organizat circular. Bufferul este vid cnd cei doi pointeri sunt egali i este plin cnd pointerul de introducere este cu o poziie (2 octei) n urma pointerului de extragere. Capacitatea logic estede30deoctei(15taste),iarceafizicde32deoctei(16taste). Acest model de program realizeaz doar tergerea ecranului, afiarea unui mesaj i ateptarea apsrii unei taste oarecare. Pentru afiri la consol se folosesc direct funcii DOS, ceea ce explic terminatorul '$' pentru iruri de caractere. Tasta de activare este F1. La o a doua execuie, programul se dezinstaleaz. Se observ i funciile DOS sau BIOS pentru citirea sau poziionarea diverselordatedesistem.
bios segment at 40h org 1AH b_out dw ? b_in bios ends cseg segment assume cs:cseg MONO equ F1 equ HOTKEY equ ident lng mes_act db equ db db db mes_inst db mes_dezinst db ; ; ; dw ? ; Segment date BIOS ; ; ; ; Indicator extragere buffer BIOS Indicator introducere buffer BIOS

0 3B00H F1

; 59 in zecimal = cod F1 ; Tasta activare

'_IDENTIF_' $ - ident 'TSR activ: Apasati orice tasta ' 'pentru a reveni' 7, '$' ' TSR instalat: Activare cu F1', '$' ' TSR dezinstalat', '$'

Spatiu pentru memorat vectorii vechi de intrerupere

Programarenlimbajdeasamblare 56
old9 label dword old9_off old9_seg old10 label dword old10_off old10_seg old13 label dword old13_off old13_seg old28 label dword old28_off old28_seg ; ; ;

dw dw dw dw dw dw dw dw

? ? ? ? ? ? ? ?

Spatiu pentru adresa flagului INDOS flag_dos label dword indos_off dw indos_seg dw ? ? 0 0 0 ? ? ; ; ; ; ; ; ; ; ; Flag TSR activ Flag BIOS activ Memoreaza cerere viitoare Cod tasta activare Salvare registre stiva program intrerupt Stiva locala TSR Buffer salvare ecran Salvare cursor DTA local TSR Adresa PSP TSR Adresa DTA TSR

; flag_tsr flag_bios cerere cod_scan ss_int sp_int ss_tsr sp_tsr buff_video salv_cursor dta psp_tsr dta_tsr ; psp_int dta_int dw dd ? ? ; Salvare PSP si ; DTA program intrerupt ; ; Noile rutine de tratare intreruperi 9, 10H, 13H, 28H ; new10 proc far mov flag_bios, 1 pushf call dword ptr cs:old10 mov flag_bios, 0 retf 2 new10 endp new13 proc far mov flag_bios, 1 pushf call dword ptr cs:old13 mov flag_bios, 0 retf 2 new13 endp dw dw db dw dw dw dw dw dw db dw db dw dd

? cseg 256 dup (?) sp_tsr 4000 dup (?); ? ; 43 dup (?) ; ? ; dta ;

57 Capitolul8
new9 proc far assume ds:bios pushf call cs:old9 cli cmp jne push push push mov mov mov new9_0: cmp je mov mov cmp jnz add cmp jne mov new9_11: mov jmp new9_1: pop pop pop iret assume new9_2: pop pop pop cmp je mov new9_end: iret cs:flag_tsr, 0 new9_end ds bx ax ax, bios ds, ax bx, b_out bx, b_in new9_1 ax, [bx] cs:cod_scan, ax ax, HOTKEY new9_1 bx, 2 bx, 3EH new9_11 bx,1eh b_out, bx new9_2 ax bx ds ds: NOTHING ax bx ds cs:flag_bios, 0 cont1 cs:cerere, 1 ; Test operatii critice ; Marcheaza cerere ; Revenire in programul ; intrerupt

; ; ; ;

Apel rutina veche Dezactivare intreruperi Test deja activ

; Salvari ; registre ; Acces BIOS prin ds ; Indicator extr. ; buffer BIOS ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Este buffer-ul BIOS vid ? Da, return Nu e vid, iau codul si il memorez Este tasta de activare ? Nu, return Incrementez (extrag din buffer) Compar cu val. maxima + 2 Nu este = 3EH Este 3EH si se aduce la val. initiala

; Memorare indicator ; buffer BIOS

Programarenlimbajdeasamblare 58
cont1: push push lds cmp je mov pop pop iret cont2: pop pop call iret endp bx ds activ_tsr ; Apel functie TSR ds bx bx, cs:flag_dos byte ptr [bx], 0 cont2 cs:cerere, 1 bx ds ; Test INDOS ; Marcheaza cerere ; Revenire in programul ; intrerupt

new9 ; new28 proc far pushf ; Apel rutina call dword ptr cs:old28 ; veche cli cmp flag_tsr, 0 ; Test TSR activ jz cont3 iret cont3: cmp flag_bios, 0 ; Test operatii critice jz cont4 cont5: ret 2 cont4: cmp cerere, 0 ; Este cerere ? jz cont5 mov cerere,0 call near ptr activ_tsr ; Satisface cererea ret 2 new28 endp ; ; Rutina de baza care realizeaza activarea TSR-ului ; activ_tsr proc near cli mov flag_tsr, 1 ; Marcheaza TSR activ ; ; Comutarea contextului ; mov sp_int, sp ; Salveaza stiva mov sp, ss ; program intrerupt mov ss_int, sp mov sp, ss_tsr ; Comut pe stiva ; TSR-ului mov ss, sp mov sp, sp_tsr ; push ax ; Salvari

59 Capitolul8
push push push push push push push push ; mov mov mov mov cld iar1: push inc inc loop ; mov int mov ; push mov int mov mov pop ; mov mov int ; push mov lds int pop ; sti cmp jz jmp e1: mov mov int mov ; IF MONO mov ELSE mov ah, 3 bh, 0 10H salv_cursor, dx ax, 0B000H ax, 0B800H ; Citire ; pozitie ; cursor si salvare ; Adresa ecran monocrom ; Adresa ecran color cod_scan, HOTKEY e1 end_tsr ; Test tasta activare ; sau nu ds ah,1ah dx,dta_tsr 21h ds ; Comuta ; pe zona DTA ; a TSR-ului ah,50H bx,psp_tsr 21h ; Marcheaza PSP-ul ; TSR-ului ; ca fiind cel activ es ah, 2FH 21h word ptr dta_int, bx word ptr dta_int+2, es es ; ; ; ; Citeste DTA programului intrerupt si salveaza ah, 62H 21h psp_int, bx ; Citeste PSP-ul ; programului intrerupt ; si salveaza [si] si si iar1 ; in stiva ; proprie cx, ax, ds, si, 64 ss_int ax sp_int ; ; ; ; ; Salvare 64 de octeti din stiva programului intrerupt bx cx dx si di bp ds es ; registre

Programarenlimbajdeasamblare 60
ENDIF ; push push mov mov mov cld xor mov mov rep pop pop ; mov mov mov mov int ; ; ; ; ; bh, 7 ax, 600H cx, 0 dx, 24*256 + 79 10H ; ; ; ; ; ; Stergere ecran De la linia 0, coloana 0 pana la linia 24, coloana 79 ds es ds, ax ax, cs es, ax si, si di, offset buff_video cx, 4000 movsb es ds ; Sursa = B000:0 ; (B800:0) ; Destinatie = ; cs:buff_video

; Copiere 80*25*2 ; octeti

Aici se pune codul propriu-zis pentru functia TSR-ului in cazul de fata, se tipareste un mesaj si se asteapta apasarea unei taste mov mov mov int bh, 0 dx, 010CH ah, 2 10H ax, ds, ah, dx, 21H ah, 16H cs ax 9 offset mes_act 0 ; Pozitionare cursor in ; linia 1, coloana 0CH

; mov mov mov mov int mov int ; ; ; ; DS = segment curent ; Mesaj TSR activ ; Citire caracter de la ; tastatura

Refacerea contextului mov mov mov int dx, salv_cursor bh, 0 ah, 2 10H ax, cs ds, ax si, offset buff_video ; Pozitionare cursor

; mov mov mov ; IF MONO ; Refacere ; ecran

61 Capitolul8
mov ELSE mov ENDIF ; mov xor cld mov rep ; end_tsr: cli mov mov int ; push mov lds int pop ; mov mov mov mov add iar2: dec dec pop loop ; pop pop pop pop pop pop pop pop pop ; mov mov mov ; mov flag_tsr, 0 sti ret activ_tsr endp ; ; Marcare TSR inactiv sp, ss_int ss, sp sp, sp_int ; ; ; ; Refacere registre stiva ale programului intrerupt es ds bp di si dx cx bx ax ; ; ; ; Refacere registre din stiva curenta (TSR) si si [si] iar2 es, ax di, di cx, 4000 movsb ax, 0B800H ax, 0B000H

ah, 50H bx, psp_int 21H ds ah, 1aH dx, dta_int 21H ds cx, 64 ax, ds, si, si, ss_int ax sp_int 128

; Comutare pe PSP-ul ; programului intrerupt

; Comutare pe DTA a ; programului intrerupt

; ; ; ; ; ;

Refacere continut stiva program intrerupt din stiva curenta

Programarenlimbajdeasamblare 62
; Rutina urmatoare reface vectorii de intrerupere ; si elibereaza memoria alocata pentru programul TSR ; dezinst proc near ; ; in ES : segmentul programului rezident ; push ds push es cli ; ; Refacere vectori de intrerupere 9, 10H, 13H, 28H ; mov ax, 2509H ; Vector 9 mov ds, es:old9_seg mov dx, es:old9_off int 21H ; mov ax, 2510H ; Vector 10H mov ds, es:old10_seg mov dx, es:old10_off int 21H ; mov ax, 2513H ; Vector 13H mov ds, es:old13_seg mov dx, es:old13_off int 21H ; mov ax, 2528H ; Vector 28H mov ds, es:old28_seg mov dx, es:old28_off int 21H sti ; ; Prima data eliberam blocul de environment, a carui adresa ; de segment se gaseste la offset-ul 2CH in PSP ; mov bx, es:psp_tsr mov es, bx ; Adresa PSP mov es, es:[2ch] ; ES = adresa bloc ; environment mov ah, 49H ; Eliberare memorie ; alocata int 21H ; la instalare ; ; Acum eliberam memoria detinuta de programul ; TSR, incepand de la PSP ; mov es, bx ; ES = PSP-ul TSR-ului mov ah, 49H ; Eliberare int 21H ; pop es pop ds ret ; Revenire

63 Capitolul8
dezinst ; sfirsit endp label byte ; Eticheta pentru ; a pastra rezident ; numai pana aici

; ; Aici e punctul de start al programului ; start: mov ax, cseg ; Initializari registre mov ds, ax ; de mov ss, ax ; segment mov sp, sp_tsr ; si stiva ; ; Testam daca TSR-ul este deja instalat ; mov ax, 3509H ; Citire vector de int 21H ; intrerupere 9 ; ES = segment program ; instalat ; deja (eventual) mov ax, cs mov ds, ax ; DS = segment program ; curent xor si, si ; Offset-uri 0 mov di, si mov cx, lng ; Lungime mesaj repz cmpsb ; Comparam ds:[si] ; cu es:[di] jnz not_inst ; Nu e instalat, salt ; call dezinst ; Dezinstalare, apoi mov dx, offset mes_dezinst ; mesaj dezinstalare mov ah, 9 int 21H ; mov ax, 4c00H ; Iesire normala int 21H not_inst: ; ; Instalare TSR ; mov ah, 62H int 21H mov ; mov lds int ; ; ; ; ah, 1aH dx, dta_tsr 21H ; Similar pentru DTA psp_tsr, bx

; ; ; ;

Citire PSP si salvare pentru comutare context la activari viitoare

Citiri si salvari vectori vechi (nivelele 9, 10H, 13H, 28H)

Programarenlimbajdeasamblare 64
mov int mov mov mov int mov mov mov int mov mov mov int mov mov mov mov ; push push ; ; ; ds es ax, 3509H 21H cs:old9_off, bx cs:old9_seg, es ax, 3510H 21H cs:old10_off, bx cs:old10_seg, es ax,3513H 21H cs:old13_off, bx cs:old13_seg, es ax, 3528H 21H cs:old28_off, bx cs:old28_seg, es ax, cs ds, ax

; Vector 9

; Vector 10H

; Vector 13H

; Vector 28H ; DS = segmentul de cod

Pozitionare vectori noi mov mov int ax, 2509H dx, offset new9 21H ax, 2510H dx, offset new10 21H ax, 2513H dx, offset new13 21H ax, 2528H dx, offset new28 21H

; Vector 9 nou

; mov mov int ; mov mov int ; mov mov int ; ; ; ; Vector 28H nou ; Vector 13H nou ; Vector 10H nou

Citire si salvare adresa flag INDOS mov int mov mov ax, 3400H 21H cs:indos_off, bx cs:indos_seg, es es ds ah, 9 dx, offset mes_inst 21H ; Mesaj instalare

; pop pop ; mov mov int ; ;

Calcul al necesarului de memorie (inclusiv PSP-ul)

65 Capitolul8
; mov mov shr inc mov int cseg end ends start dx, offset sfirsit + 100h cl, 4 dx, cl dx ax, 3100H 21H ; Spatiul se specifica ; in paragrafe de ; cate 16 octeti ; Terminare cu ramanere ; in memorie

8.7Funciideintrare/ieireorientatepehandlere
Handlerele sunt variabile ntregi mai mari sau egale cu zero, ntoarse de sistemul DOS sau predefinite, care identific n mod univoc fiiere disc sau dispozitive. Funciile orientate pe handlere au generalitate maxim i permit schimbarea dispozitivelor de intrare i/sau ieire asociate unui program ntro manierfoartecomod. Suntpredefiniteurmtoarelehandlere: 0 numit i stdin (Standard Input - Intrare standard), uzual asignat ladispozitivulconsol 1 numit i stdout (Standard Output - Ieire standard), uzual asignatladispozitivulconsol 2 numit i stderr (Standard Error - Ieire standard pentru mesaje de eroare),totdeaunaasignatlaconsol 3 numit i stdaux (Standard Auxilliary - Dispozitiv auxiliar), uzualasignatladispozitivulCOM1 4 numit i stdprn (Standard Printer - Imprimant standard), uzualasignatladispozitivulLPT1. Funciile orientate pe handlere pot accesa orice subdirector al discurilor, porninddelardcinsaudeladirectorulcurent. Intrarea i ieirea standard asociate unui program executabil pot fi redirectate din linia de comand, cu ajutorul caracterelor < (redirectare sttdin) i > (redirectare stdout). Dac un program executabil nume.exe utilizeaz funcii deintrare/ieireorientatepehandlere,atunciolansarenexecuiedeforma:
C:\> nume < file1

va face ca toate citirile care au loc de la consol s fie nlocuite cu citiri din fiierulfile1. Similar,olansarenexecuiedeforma:

Programarenlimbajdeasamblare 66
C:\> nume > file2

va face ca toate afirile care au loc la consol s fie nlocuite cu scrieri n fiierulfile2. nfine,oliniedecomanddeforma:
C:\> nume < file1 > file2

varedirectaattstdin,ctistdout. Interpretorul de comenzi permite i un simulacru de mecanism pipe, prin care ieirea standard a unui program nume1 este redirectat ctre intrarea standardaaltuiprogramnume2:
C:\> nume1 | nume2

Cum sistemul DOS nu poate executa programe n mod concurent, linia de mai susesteechivalentcusecvena:
C:\> nume1 > temp C:\> nume2 < temp C:\> del temp

n continuare, sunt descrise principalele funcii de intrare/ieire orientate pe handlereiparametriilordeintrareideieire. Create File (Creeaz sau recreeaz fiier) Parametrideintrare: AH=3CH(codfuncie) CX=atribute(ReadOnly,Hidden,Systemetc.) DS:DX = adres ir de caractere terminat cu 0 (calea fiierului) Parametrideieire: CF=0,AX=handler(operaiencheiatcusucces) CF=1,AX=coddeeroare(eec) Descriere: Se creeaz fiierul cu numele specificat dac fiierul exist, coninutulvechisepierde. Open File (Deschide fiier) Parametrideintrare: AH=3DH(codfuncie) AL = mod acces (0 = pentru citire, 1 = pentru scriere, 2 = punerelazietc.

67 Capitolul8
DS:DX = adres ir de caractere terminat cu 0 (calea fiierului) Parametrideieire: CF=0,AX=handler(operaiencheiatcusucces) CF=1,AX=coddeeroare(eec) Descriere: Se deschide fiierul cu numele specificat, pentru operaia specificat fiierul trebuie s existe la deschidere pentru scriere,coninutulvechisepierde. Read File (Citete din fiier) Parametrideintrare: AH=3FH(codfuncie) BX=handler(obinutladeschideresaupredefinit) DS:DX=adresbufferdecitire(dimensionatcorespunztor) CX=numrdeocteicerutpentrucitire Parametrideieire: CF = 0, AX = numr de octei citii efectiv (operaie ncheiatcusucces) CF=1,AX=coddeeroare(eec) Descriere: Se ncearc citirea a CX octei din fiier, din poziia curent poziia este avansat automat dac de la poziia curent pn la sfritul fiierului sunt mai puin de CX octei, se citesc ci octei exist (posibil 0) dac AX = 0, sa ajuns la EOF nainte de apelul funciei, iar dac AX < CX, sa ajuns la EOF n decursul execuiei funciei ambele situaiisuntcorecte. Write File (Scrie n fiier) Parametrideintrare: AH=40H(codfuncie) BX=handler(obinutladeschideresaupredefinit) DS:DX=adresbufferdescriere CX=numrdeocteicerutpentruscriere Parametrideieire: CF = 0, AX = numr de octei scrii efectiv (AX difer de CX numainsituaiideeroare) CF=1,AX=coddeeroare(eec)

Programarenlimbajdeasamblare 68 Descriere: Se ncearc scrierea a CX octei n fiier, din poziia curent poziia este avansat automat dac CX < AX, este vorbadeosituaiedeeroare. Close File (nchide fiier) Parametrideintrare: AH=3EH(codfuncie) BX=handler(obinutladeschidere) Parametrideieire: CF=0(operaiencheiatcusucces) CF=1,AX=coddeeroare(eec) Descriere: Se nchide fiierul, adic se taie legtura logic dintre handler i fiier, stabilit la deschidere operaia este obligatorie, n special la fiierele deschise pentru scriere, deoarece acum se scriubuffereleinternealesistemuluiDOSnfiier. Delete File (terge fiier) Parametrideintrare: AH=41H(codfuncie) DS:DX = adres ir de caractere terminat cu 0 (calea fiierului) Parametrideieire: CF=0(operaiencheiatcusucces) CF=1,AX=coddeeroare(eec) Descriere: Setergefiierulcunumelespecificat. Duplicate Handle (Duplic handler) Parametrideintrare: AH=45H(codfuncie) BX=handler(obinutladeschideresaupredefinit) Parametrideieire: CF = 0., AX = handler duplicat (operaie ncheiat cu succes) CF=1,AX=coddeeroare(eec) Descriere: Se obine o copie a handlerului asociat fiierului operaia este necesar nainte de redirectarea unor fiiere sau

69 Capitolul8
dispozitive, n situaia n care dorim i revenirea la asocierea iniial. Redirect Handle (Redirecteaz handler) Parametrideintrare: AH=46H(codfuncie) CX=handlercaretrebuieredirectat BX=handler(obinutladeschideresaupredefinit) Parametrideieire: CF = 0., AX = handler duplicat (operaie ncheiat cu succes) CF=1,AX=coddeeroare(eec) Descriere: Se obine o copie a handlerului asociat fiierului operaia este necesar nainte de redirectarea unor fiiere sau dispozitive, n situaia n care dorim revenirea la asocierea iniial. Seek File (Poziioneaz indicatorul fiierului) Parametrideintrare: AH=42H(codfuncie) BX=handler(obinutladeschidere) CX:DX = poziia cerut n fiier (ntreg pe 32 de bii, CX = parteahigh,DX=partealow) AL = punctul de referin (0 = fa de nceputul fiierului, 1 fadepoziiacurent,2=fadesfritulfiierului) Parametrideieire: CF = 0, DX:AX = noua poziie n fiier (operaie ncheiat cusucces) CF=1,AX=coddeeroare(eec) Descriere: Se ncearc citirea a CX octei din fiier, din poziia curent poziia este avansat automat dac de la poziia curent pn la sfritul fiierului sunt mai puin de CX octei, se citesc ci octei exist (posibil 0) dac AX = 0, sa ajuns la EOF nainte de apelul funciei, iar dac AX < CX, sa ajuns la EOF n decursul execuiei funciei ambele situaiisuntcorecte. Find First (Identific primul fiier dintr-un nume generic cu * i/sau ?)

Programarenlimbajdeasamblare 70 Parametrideintrare: AH=4EH(codfuncie) DS:DX = adres ir de caractere terminat cu 0 (poate conine*i?) CX=atribute(0=normal) Parametrideieire: CF = 0, zona DTA conine informaii despre fiierul identificat(operaiencheiatcusucces) CF=1,AX=coderoare(nusaidentificatfiier) Descriere: Se caut primul fiier care verific numele generic specificat. La offsetul 1EH n zona DTA se gsete numele acestui fiier este necesar obinerea adresei zonei DTA n prealabil(necesarlafunciaurmtoare). Find Next (Identific urmtorul fiier dintr-un nume generic) Parametrideintrare: AH=4FH(codfuncie) DS:DX=adresazoneiDTAsauauneicopiiaacesteizone Parametrideieire: CF = 0, zona DTA conine informaii despre urmtorul fiieridentificat(operaiencheiatcusucces) CF=1,AX=coderoare(nusaidentificatfiier) Descriere: Se caut urmtorul fiier care verific numele generic specificat la un apel anterior al funciei Find First. La offsetul 1EH n zona DTA se gsete numele acestui fiier este necesar obinerea adresei zonei DTA n prealabil (necesar la funcia urmtoare). n general, aceast funcie se apeleaz ciclic, pn cnd se obine CF = 1 (nu mai sunt fiierecaresverificenumelegenerice). Funciile de duplicare i de redirectare sunt utilizate de interpretorul de comenzi, pentru redirectarea din linia de comand a intrrii i a ieirii standard. Redirectri asemntoare pot fi fcute i din programele utilizator. S considermurmtorulprogram,careexecuturmtoareleaciuni: scrieunmesajlaieireastandard creeazunfiierdisc duplichandlerul1(ieireastandard) redirecteazieireastandardctrefiierulanteriorcreat scrieunmesajlaieireastandard(scriereasevaface,defapt,nfiier)

71 Capitolul8
redirecteaz ieirea standard la handlerul duplicat (revenire la situaia iniial) scrieunmesajlaieireastandard. Programulestelistatncontinuare:
.model large include io.h .data nume db 'fis.dat', 0 h1 dw ? h2 dw ? mes_1 db 'Acest mesaj se va tipari la consola', cr, lf lng_1 dw $ - mes_1 mes_2 db 'Acest mesaj se va tipari in fis.dat', cr, lf lng_2 dw $ - mes_2 mes_3 db 'Acest mesaj se va tipari din nou la consola', cr, lf lng_3 dw $ - mes_3 .stack 1024 .code start: init_ds_es ; mov ah, 40H ; Scriere la mov bx, 1 ; standard output lea dx, mes_1 mov cx, lng_1 int 21H ; mov ah, 45H ; Duplicare mov bx, 1 ; standard output int 21H mov h2, ax ; Handler duplicat in h2 ; mov ah, 3CH ; Deschidere 'fis.dat' mov cx, 0 ; pentru scriere lea dx, nume int 21H mov h1, ax ; Handler in h1 ; mov ah, 46H ; Redirecteaza mov cx, 1 ; standard output mov bx, h1 ; la h1, adica ; la 'fis.dat' int 21H ; mov ah, 40H ; Scriere la mov bx, 1 ; standard output ; redirectat lea dx, mes_2 mov cx, lng_2 int 21H ; mov ah, 46H ; Redirecteaza

Programarenlimbajdeasamblare 72
mov mov int ; mov mov lea mov int ; end exit_dos start ah, 40H bx, 1 dx, mes_3 cx, lng_3 21H ; Scriere la ; standard output ; original cx, 1 bx, h2 21H ; standard output ; la h2, adica la ; cel original

Mesajele mes_1 i mes_3 vor fi afiate pe ecran, iar mesajul mes_2 va fi scris n fiierul fis.dat. Programul de mai sus (s presupunem c se numete redi.exe)sepoateacumrulaicuredirectaredinliniadecomand:
C:\> redi > fis_nou.dat

ceea ce va duce la scrierea mesajelor mes_1 i mes_2 n fiierul fis_nou.dat. Se observ c redirectrile efectuate prin program se refer la asignarea curentadispozitivuluirespectiv,nulaasignareaimplicit. O problem important la scrierea fiierelor executabile este accesul la parametrii din linia de comand. La descrierea blocului PSP, am vzut c n PSP exist un contor al caracterelor din linia de comand, iar coada propriu zisacomenziisegsetencepnddelaoffsetul81H. S considerm un program care accept n linia de comand un nume generic de fiier (cu '' sau '?') i afieaz la consol toate fiierele care corespund numelui generic. Accesul la fiiere se va face prin funciile Find First i Find Next,iarparametriidinliniadecomandsecitescdinPSP. Se pune problema corectitudinii numrului de parametri (cuvinte). Vom utiliza procedura count, dezvoltat n subcapitolul 8.9, care primete un ir de caractere i ntoarce numrul de cuvinte din acel ir. Este necesar o uoar modificare, n sensul de a accepta ca delimitatori de cuvinte numai spaiul i caracterul Tab. Pentru apelul funciilor DOS, se utilizeaz macroinstruciunile definitenfiierulio.h(descrisnAnexaA). Implementareaprogramuluiesteurmtoarea:
.model large include io.h extrn count : far .stack 512 ; ; Zona proprie DTA ; dta struc

73 Capitolul8
f_name dta ; ; .data file_struc dta buf_name db gen_name db f_hand nr_bytes dw buf db dim_buf help_err db mess_no_file open_err db read_err db .code start: cld push ds ; Avem nevoie de ; adresa PSP ; Offset contor ; caractere <> 128 dup (0) 80 dup (0) dw ? ? 4096 dup (?) equ $ - buf cr, lf , 'Sintaxa este: dump <file>',0 db cr, lf, 'dump: Nu exista fisier: ',0 cr, lf, 'dump: Eroare deschidere fisier ',0 cr, lf, 'dump: Eroare citire fisier ',0 ends stdout equ 1 db db 30 13 dup () dup (); Nume fisier ; identificat

pop ax init_ds_es mov si, 80H lea push mov mov xor inc jcxz ; push rep mov pop pop lea ch_nxt: cmp jz cmp jz jmp skip: inc dec jmp ; cx movsb byte ptr es:[di], 0 cx ds si, buf_name byte ptr [si], ' ' skip byte ptr [si], tab skip first_ch si cx ch_nxt di, buf_name ds ds, ax cl, [si] ch,ch si help_ds

; ; ; ;

CX = numar caractere, fara CR, LF Primul caracter Daca CX = 0, mesaj de help

; Transfer din PSP ; in buf_name ; Terminator sir

; Sarim peste spatiile albe ; si peste Tab-uri

; De la cap la coada ; si contorizam

Programarenlimbajdeasamblare 74
first_ch: lea jcxz rep ch_last: dec cmp jz cmp jz jmp skip1: dec dec jmp last_char: inc mov lea call cmp je jmp di cx ch_last di byte ptr [di], 0 si, gen_name far ptr count ax, 1 ok help ; De la coada la cap ; si contorizam ; ; ; ; ; ; ; ; ; ; Am decrementat o data in plus Punem terminator Adresa sir curatat de spatii albe initiale si finale Numaram cuvintele AX = numarul de cuvinte Daca e unul singur, e bine Altfel, mesaj help

di, gen_name help movsb di byte ptr [di], ' ' skip1 byte ptr [di], tab skip1 last_char

; ; ; ;

Transfer in gen_name Daca acum CX = 0, nu exista parametri Abia acum transfer

; Pe ultimul caracter ; Eliminam spatiile albe ; si de la sfarsit ; La fel cu Tab-urile

; help_ds: pop ds ; Help cu POP DS help: puts help_err ; Mesaj de asistenta exit_dos ; si iesire in DOS ; ok: set_dta file_struc ; Setam DTA pe zona noastra find_first gen_name ; Apel Find First jnc rel ; S-a gasit ceva jmp gata_1 ; Nu s-a gasit nimic rel: o_read file_struc.f_name, f_hand ; Deschide fisierul cu numele ; raportat de Find First in DTA jnc no_err ; Test eroare puts open_err ; Mesaj de eroare puts file_struc.f_name ; Afisare nume fisier putsi <cr, lf> ; CR, LF jmp next ; Si trecem la urmatorul ; fisier no_err: putsi <cr, lf, 'Fisier: '> ; Nume puts file_struc.f_name ; fisier identificat putsi <cr, lf, cr ,lf> iar:

75 Capitolul8
f_read f_hand, buf, dim_buf ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Citire dim_buf octeti din fisier in bufferul buf Test eroare Test sfarsit de fisier (s-au citit 0 octeti) Salt la urmatorul fisier Memoram cat s-a citit de fapt Afisam ce s-a citit Daca s-au citit mai putini octeti decat am cerut, salt la inchidere Altfel, reluam bucla de citire

jc test jz mov

error ax, ax next nr_bytes, ax

f_write stdout, buf, nr_bytes cmp jb jmp close: f_close f_hand next: find_next file_struc jc gata jmp rel error: puts puts putsi jmp gata_1: puts read_err file_struc.f_name <cr, lf> next mess_no_file ; Mesaj de eroare ; Nume fisier ; Urmatorul ; Nu exista nici un ; fisier cu numele dat ; Urmatorul fisier ; CF = 1 : nu mai sunt ; inchidere fisier nr_bytes, dim_buf close iar

puts gen_name putsi <cr, lf> gata: end exit_dos _main ; Iesire in DOS

Programul acceseaz PSPul, copiind coada comenzii ntrun buffer propriu. Se sare apoi peste spaiile albe de la nceputul irului i se elimin i spaiile albedelasfritulirului(prinmutareaterminatoruluimailastnga). Apoi se copiaz irul curat n bufferul gen_name i se apeleaz procedura count, care ntoarce numrul de cuvinte din ir. Dac numrul de parametri este diferit de 1, se afieaz un mesaj help. Altfel, se seteaz zona DTA pe o zon proprie i se apeleaz Find First. La un offset specificat n zona DTA, se va gsi numeleprimuluifiier(dacCF=0). Se deschide fiierul pentru citire i se intr ntro bucl de citireafiare, care se ncheie dac numrul de octei citii este strict mai mic dect cel cerut sau estezero.

Programarenlimbajdeasamblare 76 Se apeleaz Find Next, cu parametrul zona proprie DTA, care ntoarce numele urmtorului fiier identificat. Toat procedura se reia n bucl, pn cnd Find Next raporteaz (prin CF = 0) c nu mai sunt fiiere care s corespund numeluigenericspecificat.