Sunteți pe pagina 1din 432

Programare in limbaj de asamblare, Prof. Dr. Ing.

Lungu Vasile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 Introducere (structura unui calculator). Scurt istoric al calculatoarelor si procesoarelor (evolutie). Performante, generatii de calculatoare si procesoare Etapele realizarii unui program in limbaj de asamblare (LA). Structura microprocesoarelor INTEL 80x86/ PENTIUM. Arhitectura de baza, resursele procesoarelor, moduri de lucru (real, protejat). Arhitectura calculatoarelor si a memoriei. Segmentare si paginare. Spatiul de I/O. Descriptori de segment. Procesoare superscalare. Sistemul de intreruperi. Intreruperi BIOS si DOS. Intreruperi interne si externe. Tabela vectorilor de intrerupere. Proceduri de tratare a intreruperilor. Formatul instructiunilor (codificare, moduri de adresare). Limbajul de asamblare (definire constante, propozitii si instructiuni). Operatori si directive. Declararea datelor in LA. Declarare etichete in limbajul de asamblare. Definirea si utilizarea segmentelor (directive simplificate si complete). Initializarea registrelor segment, asocierea segmentelor cu registrele. Grupuri de segmente. Setul de instructiuni. Instructiuni de transfer, aritmetice, de prelucrare la nivel de bit Operare pe siruri, instruciuni de transfer al controlului programului, de control procesor si de sistem. Exemple de programe pentru fiecare tip de instructiuni. Definirea si utilizarea procedurilor. Transferul parametrilor pentru proceduri in limbaj de asamblare. Transferul parametrilor pentru proceduri in limbajele de nivel inalt. Proceduri recursive. Programe compuse din mai multe module. Comunicarea intre module. Macroinstructiuni. Macroinstructiuni de repetare. Directive de asamblare conditionata. Structuri de date in LA. Definirea de structuri si inregistrari (directivele struc si record). Programe rezidente (TSR). Componentele unui program TSR (partea tranzitorie, de instalare si cea rezidenta). Instalarea, activarea si dezinstalarea acestor programe. Etapele realizarii unui program in limbaj de asamblare (LA). Utilizare Debug si TurboDebugger pentru realizare de programe simple si depanarea lor. Elaboraea de programe simple si depanarea lor, utilizand instructiuni de transfer, sub Debug/ TD.

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

Functii DOS si BIOS. Setul de instructiuni: instructiuni de transfer, aritmetice, de prelucrare la nivel de bit Operare pe siruri, de transfer al controlului programului, de control procesor si de sistem. Exemple de programe pentru fiecare tip de instructiuni. Definirea si utilizarea procedurilor. Transferul parametrilor pentru proceduri in limbaj de asamblare (memorie, registre, stiva). Transferul parametrilor pentru proceduri in limbajele de nivel inalt. Definirea si utilizarea de proceduri recursive. Programe compuse din mai multe module. Comunicarea intre module. Definirea si utilizarea de macroinstructiuni. Macroinstructiuni de repetare. Directive de asamblare conditionata. Elaborarea de programe utilizand structuri de date (directivele struc si record). Programe rezidente (TSR). Instalarea, activarea si dezinstalarea acestor programe.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

2. Scurt istoric al calculatoarelor i procesoarelor (evoluie).

Calculatoare
Momentul iniial al istoriei calculatoarelor este, de obicei, legat de numele matematicianului englez Charles Babbage. El a propus n anul 1839 o Main analitic , o fascinant anticipaie a structurii calculatoarelor actuale. Ideile sale au devansat cu peste 100 de ani posibilitile tehnologice ale vremii sale. naintea sa, n acest domeniu, au mai fost ncercrile lui Leibnitz i Pascal (sec. XVII). Astfel, n 1642, Blaise Pascal inventeaz o main de calcul destinat gestiunii (adunri, scderi, conversii ntre monedele europene), denumit Pascalina, ale crei tehnologii erau asemntoare cu acelea ale ceasurilor mecanice din acel timp. n 1694, Wilhelm Leibnitz a realizat o main de calcul, care realiza cele patru operaii aritmetice n mod automat. La nceputul secolului XIX (1801) Joseph Jaquard a proiectat o main de esut (gherghef) care putea ese automat un anumit tipar. Informaia care controla ghergheful era stocat sub forma unor guri date n cartele, astfel nct prezena sau absena gurii ntr-un anumit loc controla comportarea gherghefului. ntr-un fel, acea cartel perforat coninea unul din primele programe scrise vreodat. Urmtorul moment de referin este anul 1937, cnd Howard Aiken, de la Universitatea Harvard, a propus Calculatorul cu secven de comand automat , bazat pe o combinaie ntre ideile lui Babbage i calculatoarele electromecanice produse de firma IBM. Construcia acestuia a nceput n 1939 i s-a terminat n anul 1944, fiind denumit Mark I. El a fost n principal un calculator electromecanic, fiind alctuit din comutatoare i relee. Tot n acea perioad (1943) a fost construit i n Marea Britanie un calculator, Colossus, cu scopul de a sparge faimosul sistem de coduri german Enigma. Ambele calculatoare au fost proiectate la universitatea Harvard, cu sprijinul IBM. nlocuirea releelor cu tuburi electronice a constituit un important pas nainte. n anul 1942 a fost proiectat un calculator pentru calcule numerice generale. Rezultatul a fost calculatorul ENIAC (Electronic Numerical Integrator And Computer), primul calculator electronic digital, proiectat la universitatea statului Pennsylvania, i construit n anii 1945-1946. El coninea circa 18.000 de tuburi electronice i executa 5.000 de adunri/s, avnd o memorie de 20 de numere reprezentate n zecimal. Programarea sa se realiza prin poziionarea a circa 6.000 de comutatoare, cu mai multe poziii. Pentru a introduce date i a obine rezultatele se foloseau cititoare/inscriptoare de cartele perforate. La nceput, primele aplicaii au fost cele de calcul balistic, apoi cele de criptologie, studiul razelor cosmice, meteorologie, ca n final s fie folosit i la proiectarea primei bombe cu hidrogen. O semnificaie aparte o are faptul c n arhitectura calculatoarelor Mark I i ENIAC intrau mai multe elemente de calcul, ce lucrau n paralel la o problem comun, fiind dirijate de o singur unitate de comand. Aceast soluie a fost aleas datorit vitezei reduse a fiecrei uniti de calcul n parte. La versiunea urmtoare s-a renunat la aceast structur paralel de calcul, deoarece s-a considerat c viteza unei uniti de calcul realizat cu ajutorul circuitelor electronice este suficient. Soluia prelucrrii paralele a fost reluat ulterior, dup anii 80, pentru mrirea performanelor unui sistem de calcul; astfel, n 1996 a fost realizat, de ctre firma INTEL, un supercomputer ce utilizeaz peste 7000 de procesoare PENTIUM, utiliznd tehnica de calcul paralel masiv (utilizat pentru simularea de teste nucleare, n cercetri genetice, spaiale, meteorologice). Primul calculator comercializat a fost UNIVAC (UNIVersal Automatic Computer), realizat pe structura calculatorului ENIAC, n anul 1951. Acesta se baza tot pe tuburi catodice, iar
2

informaiile se introduceau pe band magnetic, la o vitez de 40.000 bii/s. n anii urmtori, dezvoltarea calculatoarelor a cptat un ritm exploziv, la mai puin de zece ani intervenind cte o schimbare, care a fost interpretat drept apariia unei noi generaii de calculatoare.

Procesoare
Istoria microprocesoarelor ncepe n anul 1970, prin producerea primului microprocesor INTEL 4004, un procesor de 4 bii, care realiza calcule n BCD, cu o vitez de lucru de 60.000 operaii/s. Firma INTEL (INTegrated Ellectronics) a fost fondat spre sfritul anilor 60 de Robert Noyce i Gordon Moore, care au plecat de la Fairchild Semiconductor; firma i -a nceput activitatea cu fabricarea de circuite de memorie (RAM stati c de 64 bii 3101, primul produs). Primul microprocesor pe 4 bii 4004, cu o putere de calcul echivalent cu aceea a calculatorului ENIAC, avea 2.300 tranzistori, avea acces la o memorie de 4 Ko, efectua 60.000 operaii/s., la o frecven de baz de 108 KHz. n anul 1972, firma INTEL produce primul procesor pe 8 bii, 8008, cu un set de 48 de instruciuni, un spaiu de adrese de 16 Koctei i o vitez de operare de 30.000 instr./s. n anul 1974, INTEL produce microprocesorul 8080, cu un set de 72 instruciuni, un spaiu de adrese de 64 Koctei i o vitez de lucru de 300.000 operaii/s. (de zece ori mai mare dect 8008); o parte din circuitele auxiliare utilizate la procesorul 8008 sunt acum incluse n structura intern a versiunii 8080. ncepnd din 1975 se produc i primele calculatoare avnd la baz astfel de procesoare. Odat cu apariia primelor uniti de discuri flexibile (floppy disk), produse de firma Digital Microsystems, este inventat i sistemul de operare pe disc CP/M (Control Program for Microcomputer). Tot n aceast perioad ncep i alte firme s produc diferite microprocesoare, cum ar fi: Motorola, familia 6800; MOS Technology, procesoarele 6501, 6502, utilizate n calculatoarele Apple II; Zilog, Z80, realizat de aceeai echip care a realizat i 8080 (care a plecat de la INTEL i a constituit noua companie).

Procesorul Z80 este o variant mbuntit a procesorului 8080, mai rapid i care, spre deosebire de acesta, utiliza o singur tensiune de alimentare (8080 era un procesor bipolar). De asemenea, el genera singur semnalele pentru remprosptarea memoriei dinamice. Ulterior i firma INTEL a realizat o variant mbuntit a procesorului 8080, i anume 8085, n anul 1976. De remarcat c, n acea perioad, o a doua surs de procesoare Intel era . . . AMD (Advanced Micro Devices, fondat n 1969). Proiectanii de la INTEL au urmrit dou mari obiective n proiectarea oricrui procesor:
meninerea compatibilitii totale cu procesoarele precedente; folosirea unor noi tehnologii de fabricaie, pentru a produce procesoarele cele mai rapide i cele mai puternice.

n anul 1979 este realizat, de ctre firma INTEL, primul microprocesor de 16 bii (8086). Acesta a pstrat resursele procesorului 8080, pentru a pstra compatibilitatea cu softul deja scris pentru el, dar arhitectura sa intern conine dou uniti, ce lucreaz n paralel: unitatea de execuie EU (Execution Unit), care realizeaz prelucrarea efectiv a datelor, i unitatea de interfa cu magistrala BIU (Bus Interface Unit), care realizeaz comunicaia cu lumea extern. Odat cu acest procesor este produs i procesorul 8088, cu aceeai structur cu 8086, dar care comunic n exterior printr-o magistral de 8 bii, i nu de 16 bii ca la 8086. Aparent 8088, ar
3

trebui s lucreze cu o vitez de dou ori mai mic dect 8086, deoarece magistrala sa fiind de 8 i nu de 16 bii, trebuie s execute dou accese la memorie, fa de 8086, care va executa un singur acces. Lucrurile nu se ntmpl astfel deoarece unitatea BIU gestioneaz o memorie de tip coad n care se gsesc, aproape n permanen, urmtorii 6 octei ai instruciunilor ce urmeaz s se execute. Singurele momente n care coada trebuie reiniializat, i deci EU trebuie s atepte efectiv citirea unei instruciuni, sunt cel e care urmeaz dup execuia unei instruciuni de salt. n acest mod diferena de vitez ntre 8086 i 8088 este doar de circa 20%. Aceste procesoare au introdus noiunea de segmentare a memoriei (doar n modul real): registrele de 16 bii sunt folosite ca indici de adres ntr-un segment fizic de memorie de 64 Ko; registrele segment conin adresa de baz efectiv pentru segmentele active. Procesorul care avea 29.000 tranzistori realiza 330.000 operaii/s., la o frecven de 4,77 MHz, i putea avea acces la o memorie fizic de 1 Mo, mprit n 640 Ko disponibili sistemului de operare i programelor (memoria convenional) i 384 Ko pentru ROM-BIOS (memoria superioar). Arhitectura respectiv a fost pstrat mult timp, sistemul MS-DOS fiind special conceput pentru aceasta. Pn la sistemul de operare Windows Millenium (2000), inclusiv, pentru a putea avea acces la ntreaga memorie a fost necesar ncrcarea driver-ului HIMEM.SYS, datorit necesitii de compatibilitate a softului cu programele mai vechi. O dat cu aceste procesoare apare i conceptul de coprocesor, care este un procesor dedicat, legat direct pe magistrala microprocesorului i care extinde domeniul funciilor realizate de microprocesor. Cel mai important coprocesor realizat de firma INTEL pentru 8086/8088 este 8087, care este un coprocesor matematic ce realizeaz calcule n virgul mobil. Primul coprocesor matematic a fost realizat, n 1979, de firma AMD (AMD 9511). Tot n anul 1979, firma MOTOROLA ncepe s produc microprocesorul 68000, primul ce lucreaz intern pe 32 bii, iar n exterior pe 16 bii, i care va echipa calculatoarele Macintosh ncepnd din 1984 (ce vor da natere unui segment aparte de pia). Arhitectura sa difer mult de cea a procesoarelor produse anterior, deoarece a fost proiectat fr nici un fel de restricii referitoare la compatibilitatea cu alte procesoare din aceeai familie; obiectivul principal a fost obinerea unui procesor puternic, care s permit executarea tuturor instruciunilor cu oricare dintre registre, asupra oricror tipuri de date i utiliznd orice mod de adresare. Deoarece efortul de programare a acestui procesor, n limbaj de asamblare, a fost mai mare dect la familia INTEL, cel puin la nceput procesorul 68000 nu a fost prea rspndit. De asemenea, unitatea de comand a procesorului, spre deosebire de cea convenional a lui 8086, este microprogramat, fiind astfel mai uor de testat, dar are dezavantajul c este ceva mai lent. Spre deosebire de firma Motorola, firma Intel a pstrat compatibilitatea cu versiunile anterioare a fiecrui nou procesor realizat, tocmai pentru a utiliza softul deja existent n vederea exploatrii imediate a noului procesor. Din acest motiv, ns, unele neajunsuri de proiectare, iniial au continuat s fie prezente i la modelele urmtoare. n anul 1980, firma Sinclair a realizat calculatorul Zx80, bazat pe microprocesorul Z80, care coninea i un interpretor de BASIC. Acesta a cunoscut o foarte larg rspndire, datorit preului sczut fa de cel al celorlalte microcalculatoare. n anul 1981, firma IBM produce primul calculator IBM PC (Personal Computer), bazat pe procesorul 8088/8086, dotat i cu un disc flexibil de 5 1/4". Impactul mare al acestui calculator s-a datorat i faptului c firma a publicat schemele acestui calculator i un listing al BIOS-ului (singurul protejat de firm). n acest mod, multe firme au realizat echipamente compatibile IBM, fcnd n acest fel reclam, indirect, firmei IBM. Deoarece IBM a devenit un standard n domeniu, i sistemul de operare
4

MS-DOS (MicroSoft Disk Operating System) a devenit un standard pentru microprocesoarele de 16/32 bii, cum era sistemul de operare CP/M, strmoul su, pentru microprocesoarele de 8 bii. n anul urmtor, 1982, sunt realizate microprocesoarele 80186 i 80286. Primul este de fapt un 8086 mai rapid, prevzut cu o serie de circuite auxiliare, care a fost utilizat pentru a realiza calculatoare compatibile cu IBM PC/XT (eXtended Technology). Al doilea a deschis epoca calculatoarelor AT (Advanced Technology). ncepnd din anii 80, termenul de microprocesor a fost substituit (prescurtat) cu cel de procesor, i datorit complexitii din ce n ce mai mari a acestor chip-uri. n schimb, procesorul 80286 reprezint o etap nou n arhitectura microprocesoarelor, ntruct o serie de concepte clasice din domeniul calculatoarelor mari au fost transferate la acesta: multiprelucrare i multiacces, care utilizeaz mecanisme pentru gestiunea memoriei virtuale i pentru protecia memoriei atribuite unui proces. Spaiul de memorie fizic este i el mrit de la 1 Moctet, la 8086, la 16 Moctei, la 286. Pe baza acestui procesor s-a realizat calculatorul IBM PC AT. Odat cu acest procesor, 80286, a aprut termenul de mod protejat. Acest nou mod de lucru utilizeaz coninutul registrului segment (nu ca adres de baz a segmentului, ca n modul real) ci ca un selector (index) ntr-o tabel a descriptorilor de segmente. Un descriptor de segment conine adresa fizic de baz a segmentului (pe 24 de bii, oferind deci un spaiu de memorie de 16 Mo). Mecanismele de protecie a memoriei cuprind: verificarea depirii limitei adresabile a unui segment; segmente ce pot fi doar citite; segmente ce pot fi doar executate; opiuni (drepturi) de acces ntr-un segment; patru niveluri de protecie a codului sistemului de operare de programele de aplicaie i cele utilizator; mecanismele de comutare de task-uri i tabelele descriptorilor locali, care permit sistemului de operare s protejeze aplicaiile sau programele utilizator unele de altele.

n anul 1983 este realizat i primul mediu de programare, constituit dintr-un editor i compilator aflate n interaciune, adic Turbo Pascal, de ctre firma BORLAND. Primul procesor de 32 bii al firmei INTEL apare n anul 1986, i este numit 80386, pe scurt 386, avnd 275.000 tranzistori i 132 pini. Acesta poate adresa un spaiu de adrese de 4 Goctei, pentru un singur segment, ajungnd pn la 64 Toctei de memorie virtual. Procesorul posed aceleai faciliti ca i 286, dar dispune, suplimentar, de memorii interne rapide, fiind compatibil, la nivel de cod main, cu predecesorii si. Toi urmaii si, de la 486 pn la Pentium 4, se bazeaz pe aceeai arhitectur, numit IA-32. Procesorul a avut dou variante: 386DX i 386SX, diferena fiind c al doilea comunica cu memoria doar pe 16 bii, n rest fiind identic cu primul. Ca i 286, el adreseaz memoria pe 24 bii, spre deosebire de cei 32 ai lui 386DX, deci poate adresa doar 16 Mo, fa de cei 4 Go ai lui 386DX. Procesorul 80386 a introdus registre de 32 de bii pentru folosirea lor att la operanzi, ct i pentru adrese. De fapt ultimii 16 bii din registrele de 32 de bii reprezint registrele de 16 bii, corespunztoare procesoarelor precedente, pentru a asigura o compatibilitate total cu acestea. Setul de instruciuni de baz a fost mbogit cu noile moduri de adresare pe 32 de bii i cu un numr de noi instruciuni. La acest procesor apare implementat conceptul de paginare, pentru adresarea memoriei, cu pagini de dimensiune fix de 4 Ko, care ofer o metod de implementare a memoriei virtuale, mai bun dect segmentarea. n plus, posibilitatea de a defini segmente de lungime egal cu spaiul de adresare, mpreun cu
5

mecanismul de paginare, permit crearea unui sistem de adresare liniar protejat, mod folosit de sistemul de operare UNIX. Pe lng acestea s-au dezvoltat, n arhitectura procesoarelor, tehnici de procesare (prelucrare) paralel. Astfel dac la 8086 erau doar dou uniti funcionale care lucrau n paralel, structura procesorului 286 conine 4 uniti funcionale ce lucreaz n paralel, n timp ce procesorul 386 conine 6 uniti funcionale ce lucreaz n paralel. Cele 6 uniti funcionale sunt: Unitatea de interfa cu magistrala (BIU-Bus Interface Unit), care realizeaz accesul la memorie i la porturile de intrare/ieire, pentru celelalte uniti; Unitatea de citire n avans a instruciunilor (Code Prefetch Unit), care ia codul obiect (codul instruciunii) din memorie, i l depune ntr-o coad de 16 octei; Unitatea de decodificare a instruciunii (Instruction Decode Unit), care decodific codul obiect din coada de instruciuni n microcod; Unitatea de execuie (Execution Unit), care execut microcodul furnizat de unitatea de decodificare; Unitatea de translatare a adreselor (Segment Unit), care translateaz adresele logice n adrese liniare i realizeaz verificrile de protecie; Unitatea de paginare (Paging Unit), care translateaz adresele liniare n adrese fizice i realizeaz verificrile de protecie legate de pagini. Aceast unitate mai conine un cache cu informaii de lucru pentru cel mult 32 de pagini, cele mai recent accesate.

Coprocesorul lui 386 (387) este i el mbuntit, adugndu-i noi operaii, cum ar fi funciile trigonometrice. O variant mbuntit a acestui procesor este 80486, produs n anul 1989, care este la fel cu 386 dar include n aceeai capsul (chip) i coprocesorul matematic, fiind de cel puin dou ori mai rapid dect un 386, la aceeai frecven. La acest procesor s-a dezvoltat paralelismul execuiei prin expandarea unitilor de decodificare a instruciunii i de execuie ntr -o band de asamblare (pipeline) cu cinci nivele, n care unitatea fiecrui nivel opereaz n paralel fa de celelalte, putnduse executa, n acest mod, cinci operaii n paralel. Fiecare nivel din banda de asamblare i realizeaz sarcina corespunztoare pentru execuia unei instruciuni pe durata unui impuls de tact (ceas). n plus, fa de 386, procesorul Intel 486 are un cache intern de date i de instruciuni, de nivel L1 (L1 cache) de 8 Ko, pentru a mri procentul instruciunilor care se pot executa la viteza maxim (de o instruciune pe impuls de ceas, incluznd i instruciunile cu acces la memorie, care au operanzii n cache-ul de date). Procesorul 486 a cunoscut i el dou variante: 486DX i 486SX, cea de-a doua mai ieftin, dar fr coprocesor inclus (de fapt, coprocesorul era doar dezactivat sau defect; acest procesor a fost mai degrab un produs de pia dect o nou tehnologie). Procesorul 486DX avea 1.2 milioane tranzistori, cu frecvene ntre 25 i 50 MHz, funcionnd la 5V, 168 de pini. Unele procesoare ncorporeaz caracteristici pentru reducerea consumului sau pentru controlul sistemului, cum ar fi procesoarele Intel 386SL sau 486SL, care sunt specializate pentru sistemele portabile, alimentate de la baterii. Dac la primele procesoare din familia Intel x86 s-a utilizat o arhitectur complex, denumit arhitectur CISC (Complex Instruction Set Computer), ulterior, ncepnd cu procesorul 486, prin utilizarea conceptului de band de asamblare (pipeline), arhitectura acestor procesoare se apropie de o structur RISC. Cercetrile au artat c o suit de instruciuni simple se poate executa mai rapid dect o singur instruciune complex, iar diminuarea numrului de comenzi i a complexitii lor permite reducerea spaiului utilizat de acestea n procesor, avnd ca i consecin creterea vitezei de lucru.
6

Arhitectura RISC (Reduced Instruction Set Computer) a fost dezvoltat ncepnd din anii 70. Setul de instruciuni ntr-o main RISC, dup cum o spune i numele, const doar din instruciuni simple, cu moduri de adresare limitate. Ideea de baz a fost ca, n locul unei sumedenii de operaii, procesorul s ofere un set restrns de operaiuni, pe care le poate executa foarte rapid. Cele mai multe instruciuni se execut ntr-un singur ciclu. Arhitectura unui procesor Pentium este de tip RISC. Compilatoarele genereaz secvene de instruciuni complexe corespunztoare. Pe lng setul redus de instruciuni, procesoarele RISC mai ofer urmtoarele avantaje:
operaii cu registre, minimiznd astfel necesarul de operaii de acces la memorie; memorie cache integrat pe chip, evitndu-se lucrul lent cu memoria; un model pipeline, pentru a permite procesarea mai multor instruciuni ntr-un ciclu.

Dezavantajul procesoarelor RISC este c, posednd un set mai mare de registre, operaiile de multitasking (multiprelucrare) necesit comutri de multe registre. Ulterior firma INTEL a produs, n anul 1994, i un procesor pe 64 bii, denumit PENTIUM, tocmai pentru a-l deosebi de procesoare cu aceeai structur produse de alte firme, i denumite 586, Intel realiznd c nu va putea niciodat transforma un numr (586) n marc de comer. Acest procesor, care marcheaz nceputurile generaiei P6, a adugat o a doua band de asamblare de execuie pentru a se obine performane superioare (cele dou benzi de asamblare, denumite U i V, pot lucra n paralel, executnd dou instruciuni pe un impuls de tact). De asemenea, a fost dublat i memoria cache intern, avnd acum cte un cache pentru date i unul pentru cod, fiecare de cte 8 Ko. 1994, Pentium, 2 benzi (u,v), cache L1 separat 8Ko date + 8Ko instr., BTB(Branch Target Buffer), mag int 128 bii, APIC (Advanced Programmable Interrupt Controller); P6. 1996, Pentium Pro, superscalar pe 3 ci, execuie dinamic (analiz flux, execuie n orice ordine, predicie salt, execuie speculativ), 5 unit exec, L1 + L2 (256 Ko) 1997, Pentium MMX (8 reg 64 bii, 3 tipuri de date noi mpachetate de 8-16-32 bii), 57 instr. noi, SIMD (Single Instruction Multiple Data), L1 dublat, alg. predicie mb. 1998, Pentium II = Pro + MMX, SECC (Single Edge Contact Cartridge); 1999, Pentium III = II + arh. SSE (Streaming SIMD Extension), 70 instr., 4*32 bii (virgul mobil, simpl precizie)= 128 bii. 2001, Pentium 4, extinde SIMD, SSE 2, pt. real dubl precizie, NetBurst (MP, HyperThreading, superband-20 nivele/ fa de 12 la PII/ PIII), L1: 8Ko date + 12 K micro-operaii trace cache. 2001, arhitectura Itanium, extindere a execuiei paralele, predictive i speculative; L3 (2 sau 4 Mo), L2 (96 Ko, linie 64 oct., 6 ci). 2002, Itanium 2 mrete performana de 1.5-2 ori. Procesoare INTEL: familia P6 (1995-1999): Pro, II, III band de asamblare superscalar (2-3 instr/ciclu); extensia SSE, set 8 registre, XMM, pe 128 biti (real-sp) + reg. control/stare de 32 bii; familia Pentium 4 (2000-2006)

micro-arh NetBurst (viteza dubla UAL/intregi, executie dinamica avansata, imb alg predictie, expandare reg cu redenumire, dim cache 64 octeti; SSE2, set registre pe 128 biti (real-dp, intregi), instruciunile utiliz. reg. XMM, MMX i reg. gen; procesoarele Xeon i Pentium Extr Ed (2001-2007) micro-arh NetBurst, tehnologia Hyper-Threading, 64 bii; instruciuni SSE3 (virg. mobil, sincronizare multi-thread), SSSE3-Supplemental Streaming SIMD Extensions (instr. accelereaz prel. semnal i MM), SSE4 cu 2 componente: SSE4.1-media, imagine, 3D i SSE4.2-prel text/string, 128 bii. Microarhitectura Intel Core : Execuie dinamic larg fiecare nucleu (core) fetch, decod, execut 4 instr/ciclu; Band asamblare 14 niveluri, 3 UAL, 4 decod, predict av; Cache inteligent avansat rat mare pentru nivel 2 cache: < 4M i asociativitate pe 16 ci; mag intern 256 bii pentru transferul L1-L2; Acces la memorie inteligent reduce cache-miss pentru execuia n orice ordine; hard prefetch ce reduce latena pt cache-miss la L2; hard prefetch ce reduce latena pt cache-miss la L1; mb. prelucrrii de date media digitale execuie pe singur ciclu pt. maj. instr. SIMD pe 128 bii; execuia pn la 8 operaii n virgul mobil/ciclu

Procesoarele iniial dezvoltate ca uni-core Procesor multi- core (Intel Core Duo, cu 2 core-uri, Intel 2010 core, cu 4 core, Intel Core i7 Ultimate, cu 6 core): implementeaz multiprocesarea pot fi puternic sau slab cuplate: partajeaz memorie cache comunicaie prin mesaje sau memorie partajat inter-core Performana limitat de procentul de soft ce poate fi paralelizat s ruleze simultan pe coruri multiple

Unele metode de paralelism la nivel instruciune (ILP) precum asamblarea superscalara sunt adecvate Consum mai mic dect dou procesoare single-core cuplate, nemaifiind necesar transmitere semnale n afara procesorului Procesoarele multi- core partajeaz aceleai circuite: cache L2, interfaa cu FSB(Front Side Bus); Necesit ajustri att ale SO ct i ale softului aplicaiilor curente; Softul multi-thread mai greu de depanat, dar tehnicile de programare paralel pot beneficia direct de multiple core-uri. Administrarea concurenei: partiionare/ descompunere problem n taskuri, Comunicare ntre taskuri, Aglomerare versus combinare taskuri pentru a furniza un numr mai mic de taskuri, fiecare de o dimensiune mai mare (replicare date sau calcule, pentru eficien), Maparea specific unde se execut fiecare task

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

3. Performane, generaii de calculatoare i procesoare.

Calculatoare
Dezvoltarea calculatoarelor a cptat un ritm exploziv, la mai puin de zece ani intervenind cte o schimbare, care a fost interpretat drept apariia unei noi generaii de calculatoare. Aceste generaii pot fi clasificate astfel:
generaia I ( 1946-1956), caracterizat prin: hard: relee, tuburi electronice; soft: programe cablate, cod main, limbaj de asamblare; capacitate memorie: 2 Koctei; vitez de operare: 10.000 operaii/s. generaia a II-a (1957-1963) a fost marcat de apariia tranzistorului; hard: tranzistoare, memorii cu ferite, cablaj imprimat; soft: limbaje de nivel nalt (Algol, Fortran); memorie: 32 Koctei; vitez: 200.000 instruciuni/s. generaia a III-a (1964-1981), caracterizat prin: hard: circuite integrate (la nceput pe scar redus, apoi pe scar medie i larg; scara de integrare se refer la numrul de componente electronice pe unitatea de suprafa), cablaje imprimate multistrat, discuri magnetice, apariia primelor microprocesoare; soft: limbaje de nivel foarte nalt, programare structurat, baze de date, grafic pe calculator; memorie: 12 Moctei; vitez: 5.000.000 instruciuni/s. generaia a IV-a (1982-1989) hard: circuite integrate pe scar foarte mare (VLSI), sisteme distribuite de calcul, apar microprocesoarele de 16/32 bii; soft: pachete de programe de larg utilizare, sisteme expert, limbaje orientate obiect, baze de date relaionale; memorie: 810 Moctei; vitez: 30 mil. instr./s. generaia a V-a, n curs de dezvoltare, se dorete a atinge urmtoarele performane: hard: circuite integrate pe scar ultralarg ULSI (proiectare circuite integrate 3D), arhitecturi paralele, alte soluii arhitecturale noi (reele neurale etc.); soft: limbaje concurente, programare funcional, prelucrare simbolic, baze de cunotine, sisteme expert evoluate; memorie: zeci sute Moctei; viteza: 1 Ginstr./s. 1 Tinstr./s.

Procesoare
1970, INTEL 4004, 4 bii, calcule BCD, 60.000 op./sec. Firma INTEL (INTegrated Electronics) a fost fondat spre sfritul anilor 60 de Robert Noyce i Gordon Moore. 1972, INTEL 8008, 48 de instruciuni, 16 Koctei, 30.000 instr./sec 1974 INTEL 8080, 72 instruciuni, 64 Koctei, 300.000 op./sec. 1979, INTEL, primul microprocesor de 16 bii (8086); 2 uniti: EU + BIU. 8088, mag. ext. 8 bii. Motorola 68000. 1980, Sinclair, Spectrum Zx80 (Z80), Basic. 1982, 80186, 286 - multiprelucrare/ acces, mod protejat, 4 uniti, mecanisme gest. mem. virtual, protecie mem. 1983, primul mediu integrat de programare (TP, Borland). 1986, 386, 32 bii, 6 unit., paginare; coprocesor mbuntit 1989, 486 = 386+387+cache unificat 8 Ko., band de asamblare, RISC (Reduced Instruction Set Computer); 1994, Pentium, 2 benzi (u,v), cache L1 separat 8Ko date + 8Ko instr., BTB(Branch Target Buffer), mag int 128 bii, APIC (Advanced Programmable Interrupt Controller); P6. 1996, Pentium Pro, superscalar pe 3 ci, execuie dinamic (analiz flux, execuie n orice ordine, predicie salt, execuie speculativ), 5 unit exec, L1 + L2 (256 Ko) 1997, Pentium MMX (8 reg 64 bii, 3 tipuri de date noi mpachetate de 8-16-32 bii), 57 instr. noi, SIMD (Single Instruction Multiple Data), L1 dublat, alg. predicie mb. 1998, Pentium II = Pro + MMX, SECC (Single Edge Contact Cartridge); 1999, Pentium III = II + arh. SSE (Streaming SIMD Extension), 70 instr., 4*32 bii (virgul mobil, simpl precizie)= 128 bii. 2001, Pentium 4, extinde SIMD, SSE 2, pt. real dubl precizie, NetBurst (MP, HyperThreading, superband-20 nivele/ fa de 12 la PII/ PIII), L1: 8Ko date + 12 K microoperaii trace cache. 2001, arhitectura Itanium, extindere a execuiei paralele, predictive i speculative; L3 (2 sau 4 Mo), L2 (96 Ko, linie 64 oct., 6 ci). 2002, Itanium 2 mrete performana de 1.5-2 ori. Procesoare INTEL: familia P6 (1995-1999): Pro, II, III band de asamblare superscalar (2-3 instr/ciclu); extensia SSE, set 8 registre, XMM, pe 128 biti (real-sp) + reg. control/stare de 32 bii; familia Pentium 4 (2000-2006) micro-arh NetBurst (viteza dubla UAL/intregi, executie dinamica avansata, imb alg predictie, expandare reg cu redenumire, dim cache 64 octeti; SSE2, set registre pe 128 biti (real-dp, intregi), instruciunile utiliz. reg. XMM, MMX i reg. gen;

procesoarele Xeon i Pentium Extr Ed (2001-2007) micro-arh NetBurst, tehnologia Hyper-Threading, 64 bii; instruciuni SSE3 (virg. mobil, sincronizare multi-thread), SSSE3Supplemental Streaming SIMD Extensions (instr. accelereaz prel. semnal i MM), SSE4 cu 2 componente: SSE4.1-media, imagine, 3D i SSE4.2prel text/string, 128 bii. Microarhitectura Intel Core : Execuie dinamic larg fiecare nucleu (core) fetch, decod, execut 4 instr/ciclu; Band asamblare 14 niveluri, 3 UAL, 4 decod, predict av; Cache inteligent avansat rat mare pentru nivel 2 cache: < 4M i asociativitate pe 16 ci; mag intern 256 bii pentru transferul L1-L2; Acces la memorie inteligent reduce cache-miss pentru execuia n orice ordine; hard prefetch ce reduce latena pt cache-miss la L2; hard prefetch ce reduce latena pt cache-miss la L1; mb. prelucrrii de date media digitale execuie pe singur ciclu pt. maj. instr. SIMD pe 128 bii; execuia pn la 8 operaii n virgul mobil/ciclu

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic


Programare n limbaj de asamblare

4. Etapele realizarii unui program n limbaj de asamblare (LA).

Programarea procesoarelor
Fiecare procesor (sau calculator bazat pe un procesor) are propriul su limbaj, denumit limbaj main, care este exprimat n alfabetul binar {0,1}. Acest limbaj se definete n etapa de proiectare a unitii de comand a procesorului (calculatorului). Unitatea de comand este cea care citete instruciunile din memorie (fetch), le decodific i le execut. Aceste instruciuni reprezint operaii elementare: transferul datelor ntre memorie i unitatea de prelucrare, operaii aritmetice i logice, modificarea fluxului de comand etc. Un program n cod (limbaj) main mai este denumit i cod obiect. Limbajele de nivel nalt, precum C sau Pascal, au fost concepute pentru a nu ine cont de caracteristicile tehnice specifice oricrui calculator, n timp ce limbajul de asamblare este proiectat pentru o familie specific de procesoare. Limbajul de asamblare reprezint o codificare simbolic a codului main. Aceste coduri simbolice sunt denumite mnemonici. Limbajul, care este foarte aproape de structura mainii, are urmtoarele avantaje: ofer posibilitatea utilizrii tuturor resurselor i facilitilor calculatorului; permite implementarea mai eficient (cu mai puine resurse i mai rapid) a anumitor funcii, dar i de a realiza taskuri de mare tehnicitate, care ar fi dificile, dac nu imposibile, ntr-un limbaj de nivel nalt;
dar are i unele dezavantaje: programele nu sunt portabile; ntruct fiecare procesor are propriul su limbaj de asamblare, programele nu pot fi executate pe alt tip de procesor, din alt familie; solicit un efort mult mai mare din partea programatorului pentru elaborarea unor aplicaii complexe.

De exemplu, un fiier surs care conine un program surs, n limbaj de asamblare, este mult mai mare dect un fiier ce conine un program echivalent ntr-un limbaj de nivel nalt (Pascal sau C). n schimb, programul obiect obinut pentru varianta n limbaj de asamblare este mult mai mic i, n consecin, mai rapid. Programarea n limbaj de asamblare presupune cunoaterea structurii i arhitecturii calculatorului, cunoaterea sistemului de operare i a asamblorului. Programele rezidente i rutinele de tratare a ntreruperilor sunt aproape ntotdeauna dezvoltate n limbaj de asamblare. De asemenea, dei cei mai muli specialiti dezvolt noile aplicaii n limbaje de nivel nalt, care sunt mai uor de scris i de ntreinut, o practic obinuit este de a scrie n limbaj de asamblare acele rutine care sunt critice din punct de vedere al timpului de execuie (adic cele care produc gtuiri de prelucrare). Asambloarele sunt programe care translateaz programele surs, scrise n limbaj de asamblare, n cod main. Asemntor limbajelor de nivel nalt, i asambloarele au cunoscut o evoluie n timp. Astfel, primele asambloare utilizau pentru referirea datelor adrese fizice, dup care s-au introdus nume simbolice pentru date i adrese. Ulterior au aprut macroasambloare, care permit utilizarea de macroinstruciuni, care permit ca unor secvene de instruciuni s li se asocieze un nume; aceste macroinstruciuni pot fi parametrizate i pot fi utilizate pentru a defini un limbaj de tip limbaj de asamblare, dar mult mai puternic. De asemenea, se pot utiliza nu numai date simple, dar i date structurate, asemntoare celor din limbajele de nivel nalt.

Operaia de asamblare se realizeaz n dou etape:


1. La primul pas se genereaz o tabel de simboluri, ce va conine toate numele simbolice din program, exceptnd numele simbolice externe (definite n alte module), instruciuni i directive de asamblare. n aceast etap, asamblorul contorizeaz instruciunile i datele i asociaz numelor simbolice o poziie relativ (deplasament) fa de nceputul programului, ca i cum programul ar ncepe de la adresa zero. n realitate, programul nu se ncarc n memoria RAM de la adresa zero, care este o zon folosit de sistemul de operare, ci de la o adres furnizat de sistemul de operare, n funcie de spaiul de memorie disponibil; din acest motiv, programul furnizat de asamblor este relocabil. 2. La pasul al doilea se obine programul obiect, translatnd programul instruciune cu instruciune i nlocuind n instruciunile respective numele simbolice cu valorile numerice asociate n tabela de simboluri. Programul executabil se obine n urma etapei de editare de leg turi (linkeditare), care permite legarea mai multor module relocabile ntr-un fiier executabil, rezolvndu-se toate referinele ncruciate care au fost folosite n alte module.

n concluzie, etapele care trebuie parcurse pentru realizarea i execuia unui program n limbaj de asamblare sunt descrise schematic n figura urmtoare. Prima etap este cea de editare a programului surs, ce are extensia .ASM, i care poate fi realizat cu orice editor (WS- opiunea NonDocument, NC, editoarele din TPascal sau TC etc.). Dup aceasta urmeaz asamblarea, care furnizeaz programul obiect, cu extensia .OBJ; dac apar erori n faza de asamblare, se reia editarea programului, corectnd erorile respective. La editarea de legturi, pe lng programul curent, pot fi utilizate i alte programe obiect, eventual din bibliotec. Fiierul executabil astfel obinut, poate fi testat i depanat utiliznd una din utilitarele TurboDebugger (TD) sau Debug(ger). Pentru a nu relua de fiecare dat secvena de comenzi, se poate edita un fiier de comenzi (batch), ASM.BAT, pentru asamblarea, editarea de legturi, i eventual tergerea fiierului neutilizat (.OBJ), de forma:
@echo off tasm tlink del % 1.asm % 1.obj % 1.obj

Comanda va fi utilizat astfel:


>ASM nume_fisier.asm

Dac se dorete i obinerea fiierului listing, atunci comanda de asamblare trebuie utilizat cu opiunea /l.

Editare program

Editoare de text: Notepad, editoare NC, C/C++, etc.

fiier surs

nume_fiier.asm

Asamblare

TASM (Borland) MASM (MicroSoft) fiier listing nume_fiier.lst fiier referine nume_fiier.crf

fiier obiect alte programe obiect

nume_fiier.obj

module din bibliotec

Editare de legturi fiier executabil

TLINK LINK

nume_fiier.exe sau nume_fiier.com Debug TD (TurboDebugger)

Depanare

Testare

Erori nume_fii er.com

Editare

Execuie Etapele de realizare a unui program n limbaj de asamblare

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

6. Arhitectura de baz, resursele procesoarelor, moduri de lucru (real, protejat).

Arhitectura de baz. Setul de registre


Familia de procesoare 8086, 88, 186, 286 conine acelai set de registre de baz, instruciuni i moduri de adresare. Pentru procesoarele 386, 486 i respectiv Pentium se vor face specificrile necesare.

Setul de registre
Procesorul 286 are 15 registre, grupate n patru categorii, conform figurii de mai jos. Cele patru categorii de registre sunt: generale, de segment, index i de baz, de stare i control.

Registrele generale
Sunt opt registre cu scop general: AX, BX, CX, DX, BP, SP, SI i DI, utilizate pentru a stoca operanzi logici i aritmetici. Patru dintre acestea pot fi utilizate fie ca registre de 16 bii, sub numele de AX, BX, CX, DX, fie pot fi mprite n perechi de registre separate de cte opt bii, denumite astfel: AH, AL, BH, BL, CH, CL, DH, DL (H=high, L=low, respectiv primii 8 bii i ultimii 8 bii din registrele respective). Majoritatea instruciunilor utilizeaz n acelai mod toate registrele; exist ns instruciuni pentru care anumite registre generale au o anumit semnificaie:
AX (denumit i acumulator) i DX sunt utilizate n instruciunile de nmulire, mprire i cele de I/O cu o semnificaie prestabilit; de asemenea, registrul AL se folosete pentru operaii de translaie de cod sau n operaiile cu numere reprezentate n BCD (binary coded decimal); CX este utilizat drept numrtor pentru operaii de deplasare, rotire, bucle soft, repetri hard a uno r instruciuni; la 386/486, aceste registre sunt extinse la 32 bii: EAX, EBX, ECX, EDX, ESP, EBP, ESI i EDI.

Registre generale funcii speciale 31 EAX EDX ECX EBX EBP ESI EDI ESP 31 16 7 AX DX CX BX 0 7 (AH) (DH) (CH) (BH) BP SI DI SP 0 (AL) (DL) (CL) (BL)

Registre segment 15 0 Code Segment (CS) Data Segment (DS) Extra Segment (ES) Stack Segment (SS)

Instruciuni de I / O, *, / Registre de Numrtor baz (base) Registre index -Indicator stiv

16 15 31

Registre de stare i control EIP EFlags 16 15 0 IP-Instruction Pointer Flags MSW

Setul de registre al procesoarelor Intel 286 (386/ 486/ Pentium)

Registrele segment
Sunt patru registre speciale, ce permit selectarea n orice moment a segmentelor de memorie imediat adresabile pentru cod (instruciuni) CS, stiv SS i date (DS, ES). Pe lng registrele de segment, vizibile programatorului pentru fiecare registru segment mai exist i regist re cache de descriptori de segment, care nu sunt vizibile programatorului, dar este util s cunoatem coninutul lor. Aceste registre, asociate cu fiecare registru segment, conin: adresa de baz a segmentului (24 bii), limita segmentului (16 bii) i alte atribute de segment (8 bii), deci n total 48 bii. Cnd valoarea unui selector este ncrcat ntr-un registru segment, registrul cache de descriptor asociat este n mod automat actualizat. n modul real de adresare se actualizeaz direct numai adresa de baz (prin deplasarea valorii selectorului cu patru bii la stnga), deoarece limita maxim a segmentului i atributele sunt fixe n acest mod. n modul protejat, toate componentele (baz, limit i atribute) sunt actualizate de coninutul descriptorului de segment la care face referire selectorul. Structura unui selector va fi descris ulterior n acest capitol. Orice referire la memorie va implica n mod automat registrul cache de descriptor de segment, asociat cu registrul segment utilizat pentru referire. Adresa de baz a segmentului devine o component n calculul adresei fizice (sau a adresei liniare, la 486), limita este utilizat pentru operaii de verificare a limitei segmentului, iar atributele sunt folosite pentru verificarea tipului (drepturilor) de referire la memorie. La 386/486 mai exist nc dou registre segment pentru date: FS i GS. Bineneles c i pentru acestea exist registre cache de descriptori de segment asociate. Fa de 286 ns, dimensiunea lor este mai mare, deoarece adresa de baz a segmentului este extins la 32 de bii, limita segmentului la 20 de bii, iar atributele de segment ocup 12 bii (deci n total 64 bii).

Registre index i de baz


Patru dintre registrele generale (BX, BP registre de baz, SI, DI registre index) pot fi utilizate, de asemenea, pentru a determina adresele de offset (deplasament) ale operanzilor din memorie. Aceste registre pot conine adresele de baz sau indexul pentru anumite locaii de memorie dintr-un segment. Modul de adresare determin registrul specific utilizat pentru calcularea adresei efective a operandului. Registrele index sunt utilizate n mod implicit pentru a face referire la irurile surs, respectiv destinaie pentru operaiile pe iruri. Registrul BP se refer implicit (dac instruciunea nu este precedat de un prefix segment) la segmentul de stiv curent (SS). Tot la segmentul de stiv face referire, implicit pentru operaiile cu stiva, i registrul SP (Stack Pointer), dar operaiile cu stiva (PUSH, POP, CALL, RET, INT, IRET) actualizeaz n mod automat registrul SP, afectnd n mod corespunztor stiva (extragerea sau introducerea informaiei n stiv). n schimb, registrul BP poate fi folosit pentru acces la date din stiv (parametrii sau variabilele locale procedurii), fr ns a extrage datele din stiv (adic fr a modifica stiva).

Registre de stare i control


Sunt trei registre cu scop special, care memoreaz i controleaz anumite stri ale procesorului: IP, MSW i F.

Registrul IP (Instruction Pointer) conine adresa de offset pentru urmtoarea instruciune secvenial ce va fi executat. La 386/486, registrele au 32 bii: EIP, EFLAGS. Registrul MSW (Machine Status Word) memoreaz starea procesorului, adic dac a avut loc o comutare de task, i controleaz modu l de operare a procesorului. Dintre cei 16 bii sunt folosii doar ultimii patru unul trece procesorul n mod protejat, iar ceilali trei controleaz interfaa cu extensia procesor i care au urmtoarea semnificaie:
PE (Protected mode Enable) este poziionat pe 1 cnd se trece n modul protejat de lucru i nu poate fi pus pe 0 dect cu semnalul RESET; MP (Monitor Processor extension / Math Present) specific dac este (1) sau nu (0) prezent n sistem extensia procesor; pe durata instruciunii WAIT, dac MP=1, se testeaz TS i se genereaz excepia 7 ; EM (EMulate processor extension) specific dac funciile extensiei procesor sunt emulate prin soft (1) sau nu (0); permite emularea (dac este 1), la execuia instruciunii ESC, prin generarea unei excepii de extensie procesor inexistent (7); TS (Task Switched) memoreaz dac a avut loc o comutare de task, pentru a permite unei excepii de extensie procesor (7) s testeze n ce msur contextul curent al extensiei procesor aparine taskului curent. Exist instruciuni pentru ncrcarea/memorarea MSW, n modul real de adresare: LMSW, respectiv SMSW. La 386, n plus, mai sunt utilizai nc doi bii, cu urmtoarea semnificaie: ET (Extension Type) specific tipul coprocesorului (extensiei procesor) 287 sau 387; PG (Paging) specific dac procesorul utilizeaz tabele de pagin pentru a transfera adresa liniar n adres fizic; Registrul indicatori (F Flags register) conine trei categorii de indicatori: de stare, de control i speciali. Structura acestui registru este prezentat n figura urmtoare.

15 14 13 12 11 10 9

0 CF

x NT IO PL OF DF IF TF SF ZF x

AF x

PF x

Structura registrului de indicatori

Indicatorii de stare
OF (Overflow Flag) este poziionat pe 1 dac rezultatul unei operaii aritmetice depete domeniul de reprezentare (limita superioar/inferioar a acestuia) pentru numerele utilizate, adic rezultatul nu poate fi memorat n destinaia stabilit de instruciune (de exemplu, mprirea prin zero sau adunarea/nmulirea a dou numere mari la limita superioar a domeniului). SF (Sign Flag) este indicatorul de semn al rezultatului unei operaii i, de fapt, coincide cu primul bit al rezultatului, fiind 1 dac numrul este negativ, respectiv 0 pentru pozitiv. ZF (Zero Flag) este poziionat pe 1 dac rezultatul unei operaii aritmetice s au logice este zero, altfel bitul este poziionat pe 0. AF (Auxiliary carry Flag) este pus pe 1 dac n urma execuiei unei instruciuni a aprut un transport din rangul 3 n rangul 4, sau un mprumut dinspre rangul 4 spre rangul 3. Acest indicator este utilizat la implementarea aritmeticii pentru numere zecimale codificate binar (BCD Binary Coded Decimal). PF (Parity Flag) este poziionat pe 1 cnd numrul de uniti din rezultat este par (paritate par); a nu se confunda cu paritatea unui numr (de exemplu numrul 2, care este un numr par, are

reprezentarea binar 00000010, iar acest octet are paritatea impar o singur unitate). CF (Carry Flag) se poziioneaz pe 1 dac a aprut un transport sau un mprumut n/din rangul cel mai semnificativ al rezultatului, n urma execuiei unei instruciuni aritmetice.

Indicatorii de control
DF (Direction Flag) este utilizat de instruciunile pe iruri i specific direcia de parcurgere a acestora: 0 irurile se parcurg de la adrese mici spre adrese mari; 1 irurile sunt parcurse invers. IF (Interrupt Flag) acest indicator controleaz acceptarea semnalelor de ntrerupere extern. Dac IF = 1 este activat sistemul de ntreruperi, adic sunt acceptate semnale de ntrerupere extern (mascabile, pe linia INTR); altfel, acestea sunt ignorate. Indicatorul nu are influen asupra semnalului de ntrerupere nemascabil NMI. TF (Trace Flag) este utilizat pentru controlul execuiei instruciunilor n regim pas cu pas (instruciune cu instruciune), n scopul depanrii programelor. Dac indicatorul este 1, dup execuia fiecrei instruciuni se va genera un semnal de ntrerupere intern (pe nivelul 1). Evident, execuia secvenei de tratare a acestei ntreruperi se va face cu indicatorul TF = 0.

Indicatori speciali
IOPL (Input/Output Privilege Level) acest indicator ocup doi bii i definete dreptul de a utiliza instruciuni de intrare/ieire (I/O). Aceste instruciuni, precum i instruciunile ce opereaz asupra lui IF, sunt denumite instruciuni sensibile la IOPL, deoarece ele nu pot fi executate dect dac CPL <=IOPL procedura care execut aceste instruciuni trebuie s se execute la un privilegiu cel puin egal cu acela specificat de IOPL. NT (Nested Task) este automat poziionat pe 1 sau 0 de operaiile de comutare de task; execuia unei instruciuni IRET, cu NT=1, realizeaz o comutare de task.

La procesorul 386/486, acest registru (EF) are 32 bii, dintre care ultimii 16 sunt identici cu acetia, dar n plus mai sunt utilizai nc doi bii (16 i 17) care au urmtoarea semnificaie: RF (Resume Flag) acest indicator dezactiveaz, temporar, excepiile de depanare (debug), astfel nct s se poat relua o instruciune dup o excepie de depanare, fr a se genera imediat o alt excepie de depanare; adic nu se execut o instruciune de punct de suspendare dac este returnat controlul de ctre excepia de depanare direct la o astfel de instruciune. VM (Virtual 8086 Mode) acest bit arat c se execut un program 8086, dac este poziionat pe 1.

Organizarea memoriei
Memoria este organizat ca seturi de segmente de lungime variabil. Fiecare segment este o secven continu, liniar, de pn la 64 Ko (216). Adresa fizic, de nceput, a unui segment este multiplu de 16. Fiecare segment este alctuit din locaii succesive de memorie i reprezint o unitate independent i adresabil separat. Fiecrui segment i se asociaz n spaiul memoriei o adres de baz, care este adresa de start. Segmentele, n modul real, pot fi adiacente, disjuncte sau supra puse total sau parial. O locaie de memorie poate fi coninut n mai multe segmente. Unei locaii de memorie i se asociaz o adres fizic, de 20 sau 24 de bii, care identific n mod unic locaia, i o adres logic- pe care o utilizeaz efectiv programatorul care nu este unic. Adresa logic se compune dintr-un selector (adic adresa de baz a segmentului) i un deplasament fa de nceputul segmentului; practic, mai multe adrese logice pot face referire la aceeai adres fizic: modificnd n

mod corespunztor deplasamentul, pentru o alt adres de baz a segmentului se poate obine acces la aceeai locaie de memorie, ca n figura de mai jos. Din punct de vedere fizic, memoria este organizat sub forma a dou blocuri: blocul superior de adrese impare (high) este conectat la magistrala de date pe liniile D15-D8, iar blocul inferior de adrese pare (low) este conectat la liniile D7-D0. Ambele blocuri sunt selectate n paralel, pe liniile de adres A19(A23)-A1; pentru accesul selectiv la octetul inferior, la cel superior sau la ambii octei simultan, deci la un cuvnt, se activeaz n mod corespunztor liniile A0 i BHE\. Cnd se execut un acces la o adres impar octetul va fi transferat pe liniile high (D15-D8), cnd ar trebui s se gseasc pe liniile low (D7-D0). Din fericire, CPU recunoate aceast situaie i n mod automat transfer data de pe liniile high pe liniile low. Dac adresa furnizat este par, se poate citi un cuvnt de acolo, dar dac dorim s citim un cuvnt de la o adres impar, atunci se v or efectua dou cicluri de citire. Primul, de la adresa par imediat inferioar celei impare solicitate, care va furniza octetul low (de la adresa impar), iar al doilea cuprinde o citire de la adresa par imediat superioar, pentru a citi octetul high al cuvntului solicitat. Accesul la operanzi de 32 de bii, pentru un procesor de 16 bii, va necesita cel puin dou cicluri de acces sau cel mult trei, pentru cei plasai la adrese impare.

adresa 22B13 fizic H deplasament 0B13 H adresa de baz 2200 H a segmentului Adresa logic

adresa fizic deplasament 0013 H 22B0 H adresa de baz a segmentului 22B13 H

Pentru procesoarele 386/486 pot fi considerate nc dou blocuri de memorie, conectate la liniile de date D31-D24, respectiv D23-D16, pentru a se putea citi i cuvinte pe 32 de bii. Adresa plasat pe magistral este ntotdeauna multiplu de 4. Utiliznd diverse linii de activare octet CPU poate selecta oricare dintre cei patru octei de la adresa la care programul dorete s obin acces. n mod asemntor procesoarelor pe 16 bii, CPU va aranja automat n mod corespunztor octeii transferai. Procesorul poate accesa un dublu cuvnt ntr-un singur acces la memorie, dac adresa sa este divizibil cu 4, altfel vor fi necesare dou cicluri de acces la memorie. CPU va face toate aceste operaii n mod automat pentru a ncrca corect datele solicitate, dar pentru a beneficia de performana procesorului datele trebuie aliniate: valorile de tip cuvnt trebuie plasate la adrese pare, iar cele de tip dublu cuvnt trebuie aliniate la adrese divizibile cu 4. Instruciunile i datele, de 8, 16, 32, 64 sau 80 bii, pot fi memorate la orice adres, indiferent de aliniament. Prin aceasta se permite obinerea unei densiti superioare a programului n memorie. Dac pentru cod aliniamentul nu este important, ntruct instruciunile sunt citite la nivel de cuvnt n

momentul cnd se elibereaz doi octei din coada de instruciuni de ctre unitatea de citire anticipat din BU, nu acelai lucru se ntmpl i pentru date. Pentru citirea/scrierea datelor de 16 sau 32 bii, memorate la adrese ce nu sunt multiplu de 2 sau 4, vor fi necesare dou cicluri magistral, n loc de unul, dac datele sunt aliniate n memorie. Pentru cod, singurele momente n care pot s apar citiri de la adrese impare sunt cele n care se execut o instruciune de salt la o adres impar; n acest caz, se va citi n primul cicl u de magistral un octet de la adresa respectiv, dup care se continu citirea de octei de instruciune de la adrese pare. Convenia de memorare a datelor multiplu de octei, 16, 32, 64 sau 80 bii, este: se ncepe cu octetul mai puin semnificativ la prima adres (cea mai mic) i se depun n continuare octeii urmtori, n ordinea crescnd a semnificaiei, terminnd cu octetul cel mai semnificativ la adresele urmtoare. O clas special de date este cea pe dublu cuvnt (32 bii), denumite i pointeri sau referine, utilizate pentru a adresa date i cod. i acestea se memoreaz dup aceeai regul: la adresa mai mic se afl deplasamentul (offsetul), iar la adresele urmtoare se afl adresa de segment a pointerului. Memoria este adresat utiliznd dou componente de adres: un selector de segment (16 bii); un deplasament (offset), tot de 16 bii. Selectorul de segment al pointerului indic segmentul dorit din memorie, iar deplasamentul indic adresa octetului dorit n cadrul segmentului. Exist dou moduri de adresare: real i protejat, ultimul de adresare virtual. Structura segmentat a memoriei permite s se scrie programe independente de poziia n memorie, adic relocabile. Pentru ca un program s fie relocabil dinamic, el nu trebuie s ncarce sau s modifice registre segment sau s transfere controlul direct la o locaie n afara segmentului de cod curent. Relocarea dinamic permite un sistem multiprelucrare (multitasking) pentru a utiliza eficient spaiul de memorie disponibil. Programele inactive se salveaz pe disc, iar spaiul eliberat este alocat altor programe; dac programul este necesar ulterior, el poate fi adus napoi, la orice locaie de memorie disponibil, i relansat n execuie.

Modul real de adresare 8086


n acest mod, 80286 execut setul de instruciuni 8086; n acest mod, codul obiect este compatibil cu 8086. Memoria fizic este o reea continu de 1 Mo, adresabil prin pinii A0A19 i BHE (A20A23 pot fi ignorai). n acest mod, procesorul genereaz o adres de 20 bii direct dintr-o adres de segment de baz de 20 bii i un offset de 16 bii, ca n figura urmtoare. Poriunea selectorului unui pointer este interpretat ca primii 16 bii dintr-o adres de segment de 20 bii (ultimii patru sunt ntotdeauna zero). Adresele de segment sunt ntotdeauna multipli de 16. Toate segmentele, n modul real de adresare, au dimensiunea de 64 Ko. n modul real sunt rezervate dou zone de memorie, i anume:
zona de iniializare a sistemului (FFFF0FFFFFH); zona tabelei de ntreruperi (00000H003FFH).

19

16 15 adresa de deplasament 0 selector segment

0 0 0 0 15

0 0 0 0

SUMATOR

19
ADRESA FIZIC

Generarea adresei fizice n mod real

Modul protejat de adresare virtual


n acest mod, procesorul execut i setul de instruciuni 8086, dar furnizeaz mecanisme de protecie i administrare a memoriei virtuale i instruciunile asociate. Din punct de vedere al aplicaiilor n limbaj de asamblare, nu exist mari diferene ntre programarea n modul real i modul protejat. Programatorul nu lucreaz direct cu task-urile, avnd acces la ele doar prin intermediul sistemului. Sistemul de operare este cel care gestioneaz task-urile. El utilizeaz instruciuni specifice din setul de instruciuni al procesorului, care permit iniializarea modului protejat i controlul task-urilor simultane. Aceste instruciuni nu sunt folosite de programele de aplicaii. n continuare vom prezenta cteva caracteristici ale modului protejat, descrierea memoriei virtuale, controlul task-urilor multiple, mecanismul de protecie i instruciunile specifice. Se poate intra n acest mod din modul real prin setarea bitului PE din MSW, cu instruciunea LMSW (Load Machine Status Word). Acest mod ofer spaiu de adres fizic extins i spaiu de adres virtual. Spaiul de adres virtual este de 1 Go mapat (suprapus) peste spaiul de adres fizic de 16 Mo, definit de pinii de adres A23A0 i BHE\. Spaiul de adres virtual poate fi mai mare dect spaiul fizic, deoarece orice utilizare a unei adrese care nu se suprapune (mapeaz) cu o locaie fizic de memorie va determina o excepie de reiniializare. Ca i n modul real, modul protejat utilizeaz pointeri de 32 bii, constnd dintr-un selector de 16 bii i un offset de 16 bii. Selectorul specific un index ntr-o tabel rezident n memorie, n loc de primii 16 bii ai adresei reale de memorie.

Adresa de baz de 24 bii a segmentului dorit se obine de la tabelele din memorie. Offsetul se adun la adresa de baz a segmentului pentru a forma adresa fizic, ca n figura urmtoare. 31 CPU Selector 16 15 Offset Operanzi Memorie 0

Memoria fizic

Segment

Sumator de adres fizic

Descriptor Segment 23 Baz Segment 0

Tabela Descriptori de segment

Generarea adreselor fizice n modul protejat CPU face n mod automat referire la tabele ori de cte ori un registru segment este ncrcat cu un selector. Toate instruciunile care ncarc un registru segment vor face referire la tabelele din memorie, fr soft suplimentar. Aceste tabele conin valori de 8 octei, denumii descriptori. Exist descriptori de segment pentru segmentele de cod, stiv, date, descriptori de control ai sistemului pentru segmente de date speciale i operaii de transfer al controlului (comutare de task). Tabela descriptorilor segment face asocierea ntre un selector i un segment fizic din memorie, convertind astfel adresa virtual ntr-o adres fizic. Pe baza tabelei descriptorilor TD, procesorul determin poziia n memoria fizic a segmentului corespunztor unui anumit selector. Unele intrri din tabela DT sunt marcate ca segment nencrcat. Pentru aceste intrri din DT, procesorul genereaz o ntrerupere. Rutina de tratare a ntreruperii ncarc segmentul de pe disc n memorie, permind apoi accesul la informaia din acel segment. Un segment care nu mai este folosit este salvat pe disc de ctre sistemul de operare. Sistemul realizeaz operaia de interschimb de segmente ntre memorie i disc. Pentru a gestiona eficient memoria, sistemul de operare pstreaz n memorie segmentele cel mai recent utilizate. Pentru celelalte segmente, marcheaz intrrile n tabela DT ca segment nencrcat, utiliznd spaiul disponibil pentru alte segmente ce urmeaz a fi ncrcate.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic


Programare n limbaj de asamblare

7. Arhitectura calculatoarelor i a memoriei.

Arhitectura calculatoarelor Termenul arhitectura calculatoarelor este adesea utilizat cu semnificaia, simpl, de organizarea i proiectarea calculatoarelor. n practic ntr-un sistem de calcul exist mai multe arhitecturi distincte, fiecare fiind definit de o legtur ntre diferitele niveluri ale sistemului. Figura prezint o schem abstract a unui sistem de calcul, unde cele mai simple operaii i funcii sunt plasate n partea inferioar, iar cele mai complexe operaii, dependente de utilizator, ocup nivelurile superioare. Fiecare nivel folosete funciile furnizate de nivelul anterior (cel ierarhic inferior). Lumea exterioar Program aplicaie Limbaje de nivel nalt Control execuie Control I/O Arhitectura sistemului Arhitectura limbaj de programare Arhitectur sistem operare Arhitectur set instruciuni Arhitectura microcod Arhitectura nivel poart

Setul de instruciuni de baz Interpretare i execuie Microcod Registre ALU Procesor I/O Memorie Controllere

Arhitecturi ale unui sistem de calcul O arhitectur este, deci, legtura sau interfaa ntre dou astfel de module funcionale. Ea poate fi definit ca vederea funcional a sistemului sub o interfa (nivel) pentru un utilizator care se situeaz deasupra interfeei (nivelului). Proiectanii care utilizeaz interfaa (nivelul) arhitectural nu sunt, n general, preocupai de detaliile sistemului inferioare nivelului arhitecturii sistemului, sau de orice arhitecturi la niveluri inferioare. Ei sunt preocupai de funcionarea sistemului la nivelul interfeei imediat sub nivelul utilizator. Arhitectura global este interfaa ntre ntregul sistem de calcul i lumea exterioar; aceasta este denumit arhitectura sistemului. Undeva, mai jos, este interfaa ntre programul de aplicaie i limbajul de programare de nivel nalt (presupunnd c aplicaia este scris ntr-un limbaj de nivel nalt). Aceast limitare definete arhitectura limbajului de programare. Programatorul este plasat la acest nivel. n continuare, este interfaa ntre limbajul de programare i diferite funcii de administrare a resurselor, n timpul execuiei, care sunt furnizate de ctre sistemul de operare. Acest nivel este definit ca arhitectura sistemului de operare. Urmtoarea interfa este deosebit de important, deoarece n calculatoarele convenionale ea definete limita dintre hardware i software. Este nivelul elementar, la care instruciunile recunoscute de calculator sunt decodificate i executate. Acesta este nivelul

arhitecturii setului de instruciuni. Celelalte dou niveluri inferioare de arhitecturi (arhitectura microcod i arhitectura la nivel de pori) definesc mai n detaliu alte funcii primitive, dar care nu sunt interesante pentru cei mai muli dintre programatori. n general, ns, termenul de arhitectura calculatorului definete grania dintre hard i soft. Arhitectura calculatorului este nivelul sistemului de calcul ce este vzut de un programator n limbaj de asamblare sau de unul care scrie un compilator. O separare pe vertical a componentelor din figura urmtoare permite definirea de sisteme multiprocesor sau distribuite; aceast mprire se poate spune c definete arhitectura configuraiei. arhitectura Programe aplicaie Limbaje nivel nalt
Control execuie

Programe aplicaie Limbaje nivel nalt


Control execuie

Programe aplicaie Limbaje nivel nalt Control I/O Set instruciuni Microcod Pori Procesor I/O

sistem arhitectura limbaj arhitectura sistem operare arhitectura set instruciuni arhitectura microcod arhitectura nivel poart

Set instruciuni Microcod Pori CPU1

Set instruciuni Pori Microcod CPU2

SISTEM DISTRIBUIT Arhitectura configuraiei Arhitectura memoriei Una dintre cele mai importante caracteristici ale arhitecturii unui calculator este modul de organizare al memoriei i modul n care se obine acces la informaia din memorie. Memoria principal este organizat ca un set de locaii de memorare, numerotate consecutiv, ncepnd de la 0. Numerele asociate locaiilor fizice reprezint adresa fizic, iar mulimea total a adreselor fizice constituie spaiul de adrese fizice. O adres logic este o adres utilizat de ctre programator ntr-o instruciune. Adresele ce pot fi utilizate de un program constituie spaiul de adrese logice. Organizarea acestui spaiu definete arhitectura memoriei. Organizarea spaiului de adrese fizice este determinat de tehnologia utilizat pentru memorie i de costul ei, dar spaiul de adrese logice nu este condiionat de nici una dintre aceste consideraii. Din contr, organizarea memoriei logice este determinat de structura programelor ce vor rula n memorie. Iniial, spaiul de adrese logice era identic cu spaiul de adrese fizice. Memoria liniar Este cea mai obinuit organizare a spaiului de adrese logice, cea mai obinuit arhitectur

pentru memorie: un spaiu liniar, continuu de adrese. Adresele pornesc de la zero i se succed, ntrun mod liniar, fr goluri sau ntreruperi, pn la limita superioar, impus de numrul total de bii dintr-o adres logic. Un program, adesea constnd din mai multe proceduri, i datele sale sunt plasate n acest spaiu de adres unic. Spaiul de adrese logice al unei memorii liniare are, astfel, aceeai organizare ca memoria fizic. Astfel, pentru o memorie cu 16 linii de adres pot fi generate 65535 de adrese distincte. O astfel de adres generat de un program este utilizat direct de hardware-ul memoriei pentru a plasa data. Iat ce se ntmpl n cazul a dou programe, avnd codurile plasate la adrese dif erite de memorie i care nu se suprapun; s presupunem c unul dintre cele dou programe (B) face o operaie ntr-o locaie n afara codului. n figur se prezint ce se poate ntmpla n acest caz: vulnerabilitatea memoriei nemapate. 65535 program B 0 spaiul total de adres B spaiul total de adres A 65535 eroare de adresare program A 0 Vulnerabilitatea memoriei 'nemapate' Maparea memoriei liniare Maparea este, n esen, procesul de translatare a adreselor logice n adrese fizice. n exemplul anterior adresele logice sunt echivalate cu adresele fizice; dar prin exploatarea maprii, o adres logic poate fi atribuit la o adres fizic arbitrar. Deci maparea este un mecanism pentru realocarea spaiului de adrese logice peste spaiul de adrese fizice. n figura urmtoare se prezint o operaie de mapare foarte simpl. ntregul spaiu de adrese logice ale unui program (locaiile 0-65535, n acest caz) este mapat (suprapus) peste locaiile fizice 30000-95535. Astfel, o referin a unui program la locaia 50000, va prelua datele, efectiv de la locaia fizic 80000 (30000+50000). partiie program A 0 memoria fizic 65535 partiie program B suprascriere

1000000

spaiu de adrese logice 65535

logica de mapare

95535 spaiu 80000 de adrese fizice

50000

O schem simpl de mapare

30000

Aceast operaie este foarte util n sistemele multiprogram (sau multitask), pentru care a fost dezvoltat maparea. Astfel, fiecare program are propriul su spaiu logic de adrese, care este complet independent de spaiul oricrui alt program. Ca atare, mai multe programe pot 0 fizic fr posibilitatea de a interfera ntre ele. Procesul de mapare potrivete partaja memoria (suprapune) tot spaiul de adrese logice ntr -o zon de memorie0 fizic, dar procesul este transparent pentru program. Iat, de exemplu, cum se realizeaz maparea mai multor programe. Maparea bazat pe pagini n locul maprii ntregului spaiu logic de adrese ca o unitate, ca n figura de mai jos, mecanisme mai avansate de translaie a adresei mapeaz pagini de dimensiune fix, mai mici, ale spaiului de adrese logice, n pagini de memorie fizic. Astfel, un program mare nu trebuie s fie realocat ntr-o zon (poriune) continu de memorie, care poate fi greu gsit ntr-un cadru cu programe multiple, dect, mai degrab, n mai multe seciuni de memorie, mai mici, care sunt mult mai uor de gsit, disponibile. Sunt mai uor de gsit 20 de pagini de 1 Ko, dect un bloc de 20 Ko. funcia 65535 program 0 trei spaii de adrese logice mapare de
neutilizat

300000

program 215535

A B
neutilizat

65535 program 0

spaiu de adres fizic

131071 program 150000 program 65535

65535 program 0

B
0

Un cadru de mapare multiprogram Drepturi de acces, bazate pe pagini Mecanismul de paginare poate furniza baza pentru protecia memoriei ntr-un spaiu logic de adrese. Fiecare pagin poate avea asociate atribute (denumite i drepturi de acces) care indic modul n care se poate obine acces la pagin. Aceste atribute pot permite numai citire, citire / scriere sau pot mpiedica orice acces. spaiu de adrese logice 65535 unitate mapare

X R WR R
R = acces citire pagin WR = acces scriere / citire pagin X = acces interzis la pagin Protecia bazat pe pagini 0 Memoria virtual Spaiul de adrese logice este mult mai mare dect memoria fizic. Memoria virtual este un mecanism pentru a extinde limitele memoriei fizice. ntr-un sistem cu memorie virtual, aceasta apare utilizatorului ca i cum ntregul spaiu logic de adrese este disponibil pentru memorare. Dar, de fapt, doar cteva pagini din spaiul logic de adrese sunt mapate peste spaiul fizic la un moment dat. Alte pagini nu sunt prezente n memoria principal; n schimb, informaia din aceste pagini este memorat ntr-o memorie secundar, cum ar fi discul, al crei cost pe bit este mult mai economic. Ori de cte ori se obine acces la o pagin care lipsete, softul sistemului de operare ncarc pagina respectiv de pe disc i memoreaz pe disc o alt pagin, la care nu s -a fcut recent referire. Utilizatorul are impresia unei memorii fizice uriae, dar mai lente. Memoria segmentat O alt form de organizare a memoriei logice este memoria segmentat. Motivaia acesteia o reprezint faptul c programele nu sunt scrise ca o secven liniar de instruciuni i date, ci mai degrab ca buci (secvene) de cod i buci de date. De exemplu, poate exista o seciune principal spaiu de adrese fizice

de cod i mai multe proceduri separate. Aceste module de cod i date pot fi de diferite dimensiuni. Spaiul logic de adrese este desprit n mai multe spaii liniare de adrese, fiecare avnd o anumit dimensiune. Fiecare dintre aceste spaii de adrese liniare este denumit segment. Fiecare element dintrun segment este accesibil printr-o adres cu dou componente: selectorul segmentului, care specific adresa de nceput a segmentului; deplasamentul, care specific adresa relativ, fa de baza segmentului, a elementului selectat. Fiecare segment poate fi asociat unui modul de date sau de program. Astfel, programul poate avea procedura principal ntr-un segment, celelalte proceduri n segmente distincte, i fiecare structur important de date n segmentul su. Astfel, structura adreselor logice reflect organizarea logic a programului. Mecanismele de protecie pentru memoria liniar sunt bazate, de obicei, pe pagini de lungime fix, a cror dimensiune este determinat pe criterii hardware i nu au vreo relaie cu structura logic a programului. Problema descompunerii spaiului de adrese logice n pagini este c mecanismul de protecie nu poate proteja cu exactitate modulul de program. Dimensiunea paginii este determinat din raiuni hardware, deci nu are legtur cu structura logic a programelor. n schimb, ntruct fiecare segment are o anumit lungime, este uor s-l protejm de alte programe. Mecanismele de memorie virtual pot fi implementate i pentru arhitecturi segmentate. n acest caz, segmentul este unitatea de memorie ce se interschimb (swapping) la i de la memoria extern. Maparea memoriei segmentate Maparea, n acest caz, este implementat printr-o tabel de segment, care pstreaz un descriptor pentru fiecare segment. Descriptorul conine adresa de nceput a segmentului i lungimea acestuia. Componenta selectorului de segment a unei adrese logice este utilizat ca un index pentru a selecta descriptorul n tabela (descriptorilor) de segment. Apoi deplasamentul este adunat la adresa de start a segmentului, furnizat de descriptor, pentru a calcula adresa fizic a operandului referit. Deplasamentul este verificat hardware, pentru a exista sigurana c referina nu depete lungimea segmentului.

65535 54000 44000 34000 27000 20000 0

date B date A date progr. principal procedura B procedura A programul principal memoria liniar spaiu de adrese logice

memoria segmentat spaiu de adrese logice 2000 0 0 programul principal 7000 0 1000 0 0 procedura A date A 7000 0 1153 5 0 procedura B date B

1000 date 0 progr. principal 0

Compararea memoriei liniare cu cea segmentat

adresa logic segmentat selector segment deplasament locaia

descriptor segment segment tabela descriptori segment memoriei segmentate Maparea

Tipuri de segmente i drepturi de acces Descriptorul de segment mai conine, pe lng adresa de baz a segmentului i limita sa, i atribute referitoare la tipul segmentului. Drepturile de acces sunt, deci, asociate, n particular, fiecrui segment, n ciuda faptului c modulele programului refer acele segmente. Dac un segment este de tip read-only (numai pentru citire), de exemplu, i menine tipul pentru toate modulele care fac referire la acesta. Aceast asociere a drepturilor de acces cu segmentele este un dezavantaj, deoarece putem dori s dm diferitelor module acces la acelai segment, dar cu diferite drepturi de acces. Controlul accesului Un alt dezavantaj al mecanismului de mapare a segmentelor este dificultatea de a limita accesul unui program la segmentele altui program. Deoarece tabela de segmente conine toi descriptorii de segment, orice program poate accesa orice segment prin simpla indexare n tabela de segmente. Soluia este ca fiecare program s aib propriile sale tabele. Dar aceasta nseamn c, ori de cte ori un segment este realocat n memoria fizic, toate programele partajeaz segmentul vor trebui s actualizeze descriptorii lor de segment. Pentru a reduce numrul operaiilor de acest gen, fiecare task vede spaiul de memorie divizat n dou: un spaiu global, care conine serviciile de sistem, sistemul de operare i un spaiu local asociat fiecrui task. Memoria virtual i alocarea dinamic a memoriei Fiecare modul de program are propriul su cadru de acces, cadru n care (de exemplu, 32 de linii de adres) se pot genera 232 adrese diferite. Deci spaiul total de adrese, cel virtual, este egal cu dimensiunea maxim a unui segment nmulit cu numrul total de segmente. De exemplu la 386/486 i Pentium: cu o magistral de adrese de 32 de bii i un selector de 16 bii, dintre care 14 sunt utilizai pentru adresare, rezult un spaiu total de adresare virtual de 64 To. Fiecare descriptor de segment trebuie s conin un cmp de bii, actualizai hardware, utilizai de sistemul de operare pentru a implementa memoria virtual: valid (sau prezent), identific dac segmentul se gsete n acest moment n memorie; memorie alocata, indic dac s-a asociat memorie cu acest descriptor; accesat, indic dac segmentul a fost accesat de un program; modificat, indic dac informaia din segment a fost modificat sau nu de un task. Sistemul de operare poate utiliza aceti bii: valid / memorie alocat, pentru a detecta cnd un segment fizic nu este prezent n memorie; accesat / modificat, pentru a decide care dintre segmentele existente n acest moment ar trebui interschimbat (swapped) sau pur i simplu, dac n-au fost modificri, scrierea segmentului nou peste cel vechi (neutilizat curent). n plus, cteva cmpuri din descriptor pot fi utilizate de sistemul de operare, pentru a memora alte informaii folositoare despre segment (de exemplu: frecvena de utilizare), care pot fi utilizate n algoritmul de interschimb. Cantitatea de memorie alocat unui modul nu trebuie s fie fix la momentul compilrii; ea se poate modifica dinamic. Mecanismul de alocare dinamic a memoriei face memoria virtual mult mai eficient prin alocarea segmentelor numai atunci cnd este necesar, mpiedicnd astfel utilizarea memoriei de ctre segmentele la care nu se face referire.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic


Programare n limbaj de asamblare

8. Segmentare i paginare. Spaiul de I/O.

Segmentarea
S considerm un sistem multitasking, n care sunt rulate 4 task-uri (aplicaii), definite astfel: A necesit 400 Ko de memorie; B necesit 100 Ko de memorie; C necesit 400 Ko de memorie; D necesit 200 Ko de memorie; Sistemul are disponibil 1 Mo de memorie pentru execuia aplicaiilor. Presupunem c jumtate din spaiul unei aplicaii reprezint programul n sine, iar cealalt jumtate reprezint date. Deoarece necesitile de memorie ale celor 4 aplicaii depesc spaiul disponibil de 1 Mo, ele nu se pot gsi simultan n memorie. Dup ce se ncarc A, B i C, nu mai rmne spaiu disponibil pentru tot task-ul D (figura de mai jos). Sistemul de operare poate ncrca poriunea de cod a task-ului D (100 Ko), dar nu i segmentul de date. El creeaz descriptori att pentru cod, ct i pentru datele task-ului D, marcnd descriptorul de segment de date ca non-prezent (NP=0). Acesta este un sistem multitasking, astfel c adresa de start (CS:EIP) a fiecrui task este transmis ctre poriunea planificatorului din sistemul de operare, dup care ncepe execuia. Taskul A ncepe execuia i este executat timp de cteva milisecunde. Planificatorul i ia apoi controlul i permite execuia task-ului B, timp de cteva milisecunde. Totui, pe durata alocat, task-ul B citete o intrare, a operatorului, de la tastatur; deoarece nici o tast nu a fost apsat, sistemul de operare preia controlul i marcheaz task-ul B ca fiind suspendat. Apoi lanificatorul cedeaz controlul task-ului C, pe durata de timp alocat, dup care se va transfera controlul task-ului D. Acesta ncepe execuia, dar imediat ce ncearc referirea la segmentul de date, procesorul genereaz ntreruperea non-prezent (NP). Sistemul de operare determin task-ul care se executa la apariia ntreruperii, precum i motivul ntreruperii. El va stabili c task-ul D necesit acces la segmentul su de date, astfel c evalueaz strile celorlalte task-uri. ntruct task-ul B este suspendat, sistemul de operare decide s-l nlocuiasc temporar din memorie pentru a face loc segmentului de date al task-ului D. SO 200 Mo A 400 Mo 1 Go B 100 Mo C 400 Mo 100 Mo Task-urile iniiale, ncrcate n memorie D 200 Mo

Imaginea din memorie a lui B este scris pe disc, iar descriptorul pentru B este marcat ca non-prezent. Se spune c task-ul B a fost scos (swapped out), iar sistemele de operare care implementeaz memoria virtual ntr-o astfel de manier implementeaz interschimbarea (swapping). Segmentul de date pentru D este copiat n memorie la adresa fizic eliberat de B, iar descriptorul pentru D este actualizat pentru a reflecta noua adres de baz i pentru a arta c acest segment este acum prezent n memorie. Starea actual a sistemului este prezentat n figura urmtoare. Acum planificatorul comut timpul de execuie ntre task-urile A, C i D. La un moment dat operatorul, care vede promptul pentru intrarea de la task-ul B, va apsa o tast. Aceast aciune determin o ntrerupere hard i sistemul de operare observ c acum trebuie s planifice task-ul B. Totui, deoarece nici unul dintre celelalte task-uri nu este suspendat, sistemul poate alege s suspende temporar task-ul A. Deoarece task-ul B este mic, el nlocuiete doar o parte din A. Segmentul de cod al task-ului A este marcat ca non-prezent, task-ul B este interschimbat, iar descriptorii pentru task-urile A i B sunt actualizai corespunztor. tabela descriptori ... A - cod A - date B - cod B - date C - cod C - date D - cod D - date ... SO A cod
NP
NP

disc B

A - date D - cod

C - cod C - date D - date Interschimbarea task-urilor B i D

Task-ul B ruleaz acum la o adres fizic diferit de adresa de nceput. Aceasta este invizibil aplicaiei, totui, deoarece selectoarele ncrcate n registrele segment nu se modific i, deoarece offseturile de memorie utilizate de instruciuni n segmentul de cod sunt relative fa de punctul de start al segmentului, originea fizic a segmentului nu are importan. Sistemul va continua s opereze ca mai sus; dac nu exist condiii externe care s determine interschimbarea de segment, sistemul de operare poate interschimba segmente, bazndu-se fie pe durata de rulare a celui mai lung task, fie pe un alt sistem de prioriti.

tabela descriptori ... A - cod A - date B - cod B - date C - cod C - date D - cod D - date ...
NP

SO B cod B - date A - date D - cod

disc A-cod

C - date CDcod - date Interschimbarea task-urilor A i B.

Consideraii de performan Memoria virtual utilizeaz memoria secundar (de obicei discul) pentru a suplini memoria principal (RAM) i d senzaia unei cantiti de memorie principal superioar celei existente n sistem. Costul pentru aceasta este timpul necesar pentru a muta datele ntre memoria principal i cea secundar. Cu ct timpul de interschimbare este mai mare, cu att este mai mic timpul pentru execuia aplicaiilor. Performana sistemului de operare se poate mbunti. De exemplu, la mecanismul de protecie de la Intel, segmentele de cod sunt nemodificabile. Din acest motiv ele nu trebuie scrise pe disc cnd sunt extrase din memorie. Este posibil refacerea coninutului pornind de la imaginea executabil original a programului (de pe disc). Este necesar doar accesul la memoria secundar pentru interschimbarea lui n memorie. Rezult c sistemul de operare va interschimba de dou ori mai repede segmentele de cod dect cele de date. De asemenea, unele segmente de date pot fi marcate, n descriptorul lor, ca read-only. Deci, nu este necesar nici salvarea acestora pe disc la interschimbarea lor. O alt facilitate se refer la tehnica partajrii segmentului, care permite ca dou sau mai multe task-uri s partajeze acelai cod. Aceasta este eficient n sistemele multiutilizator. S presupunem, n exemplul anterior, c task-urile A, B, C i D reprezint utilizatori ce ruleaz aplicaii. S presupunem c utilizatorii A i C ruleaz aceeai aplicaie, de exemplu o foaie de calcul. Cei doi utilizatori opereaz pe date diferite i necesit segmente de date separate. Ei execut, totui, acelai cod. n figur se arat cum toate cele 4 aplicaii pot intra n memoria fizic, n acest caz. Utilizatorii pstreaz descriptori separai pentru codurile i datele lor, dar adresele de baz ale segmentelor de cod pentru A i C fac referire la aceeai locaie. tabela descriptori ... A - cod A - date B - cod B - date C - cod C - date D - cod D - date ... SO ...
...

A / C - cod A - date B - cod B - date C - date D - cod D - date

De asemenea, un sistem de memorie virtual, orientat pe segmente, poate furniza un mod pentru a compacta memoria. Compactarea memoriei permite rezolvarea unei probleme numite fragmentare. Fragmentarea memoriei apare cnd memoria discontinu este disponibil pentru a rula aplicaii suplimentare. Cu alte cuvinte, mici poriuni de memorie disponibil sunt disipate n memoria fizic, ca n figura de mai jos. Pentru a putea fi folosite este necesar ca aceste poriuni s fie contigue. Deoarece aplicaiile opereaz cu adrese virtuale, ele nu sunt afectate de o modificare a locaiei de start. Procesul acesta consum, totui, timpul procesorului. memoria su md su md
100 Mo 5 Mo

memoria dup compactare 100 Mo su su


20 Mo 80 Mo 20 Mo

su noul segment
100 Mo

300 Mo

su md
15 Mo

segment nou de adus 100 Mo in memorie

100 Mo - memorie disponibil

md memorie disponibil su segment utilizat Fragmentarea memoriei

Paginarea
Paginarea este utilizat pentru a implementa memoria virtual bazat pe blocuri de dimensiune fix, denumite pagini. Asemntor segmentrii, paginarea translateaz adresele virtuale n adrese fizice. Acestea sunt translatate prin maparea (suprapunerea) blocurilor de memorie de lungime fix n locaiile de memorie fizic, denumite cadru pagin. Segmentarea i paginarea sunt similare: un nume i un offset sunt translatate ntr-o adres. S considerm o memorie fizic compus din paginile 0, 1, 2, 3, fiecare avnd cte 10 octei; pentru convertirea unei adrese virtuale ntr-una fizic se utilizeaz o tabel de pagini. De exemplu, adresa virtual 27 este translatat n adresa fizic 17:

cadru virtual 0 1 27 adresa virtual 2 3

cadru de pagini din memoria fizic 0 1 2 3 17 adresa fizic

Translaia adresei virtuale n elemente de dimensiune fix Avantaje i dezavantaje Avantajul esenial al paginrii fa de segmentare este reprezentat de dimensiunea fix a paginrii. Deoarece pentru memoria virtual se utilizeaz discul se pot alege dimensiuni de pagin care corespund dimensiunii sectorului de pe disc. De asemenea, paginarea evit problema fragmentrii memoriei, specific segmentrii. Ori de cte ori o pagin este scoas din memorie, alt pagin se ncadreaz exact n spaiul eliberat. Un alt avantaj este c alocarea pentru un obiect mare nu trebuie realizat ntr-un spaiu continuu de memorie. Paginarea este invizibil programatorului. Spre deosebire de segmentare, care necesit cunoaterea numelui virtual (segment) i a unui offset pentru un obiect din memorie, paginarea necesit cunoaterea doar a unei adrese. Adresa virtual este descompus n componentele sale de mecanismul memoriei virtuale. Utilizarea paginrii nseamn pierderea inelelor de protecie, implementate cu segmentarea. De asemenea, ea este legat de un alt tip de fragmentare, denumit fragmentare intern, care apare la memorarea unor obiecte care nu se ncadreaz ntr-o pagin sau secven de pagini. De exemplu, dac pagina este de 10 octei, un obiect de 11 octei necesit dou pagini, care irosesc, deci, spaiu de memorie. Paginarea necesit mai mult memorie. La segmentare, tabela de translaie, pentru conversia unei adrese virtuale ntr-una fizic este necesar cnd se ncarc un nou segment. La paginare, ns, conversia (translaia) trebuie realizat pentru fiecare acces la memorie; acesta nu este un inconvenient dac ntreaga tabel de pagini poate fi memorat n procesor, dar necesit tabele de pagini foarte mari. Pentru a depi aceste probleme se poate implementa o schem de protecie simpl, care utilizeaz numai paginarea, sau se pot utiliza n paralel cele dou mecanisme: paginare i segmentare. Pentru a reduce spaiul necesar translaiei de pagini (de fapt, fragmentarea intern) se utilizeaz paralelismul intern al procesoarelor i o memorie cache special, denumit buffer de translaie adrese (TLB-Translation Lookahead Buffer), ce nu trebuie confundat cu memoria cache intern a procesoarelor 486 / Pentium. Translaia paginii Cea de-a doua etap, a translaiei de adres, (prima fiind cea de segmentare) transfer adresa liniar ntr-o adres fizic. Aceasta implementeaz caracteristicile de baz necesare pentru sistemele de memorie virtual, orientate pe pagin, i protecia la nivel de pagin. Un cadru pagin este o unitate de 4 Ko de adrese continue din memoria fizic.

O adres liniar face referire, indirect, la o adres fizic, prin specificarea unei tabele de pagini, o pagin n cadrul acestei tabele i un offset n acea pagin. Mecanismul complet, de segmentare i paginare, este prezentat n figur: adresa logic selector tabela descriptori adresa de baz director pagin translaia de segment intrare DIR CR 3 translaia de pagin Mecanismul translaiei adresei logice n adres fizic Din figur se poate observa cum procesorul convertete cmpurile DIR, PAGE i OFFSET ale unei adrese liniare n adres fizic, prin consultarea a dou tabele de pagini:
cmpul DIR este un index ntr-un director de pagini; cmpul PAGE este un index ntr-o tabel de pagini, determinat de directorul de pagin; cmpul OFFSET este utilizat pentru a realiza o adresare n pagina determinat de tabelele de pagin.

offset

descriptor segment

adresa liniar DIR PAGE OFFSET tabel pagin intrare PG TBL

cadru pagin adresa fizic

O tabel de pagini este un tablou de specificatori de pagin, de 32 de bii. O tabel de pagini este ea nsi o pagin, deci conine 4 Ko, adic 1K intrri de cte 32 de bii. ntruct acest mecanism utilizeaz dou niveluri de tabele, director de pagini i tabele de pagini, fiecare tabel putnd adresa 1K, rezult c toate tabelele adresate de un director de pagin pot adresa 1M pagini. ntruct fiecare pagin conine 4 Ko, rezult c tabelele unui director de pagin pot acoperi ntregul spaiu fizic de adrese de 4 Go. Adresa fizic a directorului de pagin curent este memorat n registrul CR3, denumit i registru de baz al directorului de pagin (PDBR Page Directory Base Register). Softul de administrare a memoriei poate opta ntre utilizarea unui director de pagin pentru toate task-urile, un director de pagin pentru fiecare task, sau o combinaie a acestor dou soluii.

Organizarea spaiului de I/O


Procesorul are dou spaii de adrese fizice distincte: memoria i I/O (intrri/ieiri). Dispozitivele periferice (consola, ecranul, tastatura, imprimanta etc.) sunt controlate i comandate de procesor, n general, prin operaii de citire/scriere la anumite locaii, diferite de spaiul de memorie. Acest spaiu este denumit spaiu de I/O, iar accesul la locaiile respective se face cu instruciuni specifice (In, Out). Locaiile din acest spaiu sunt denumite registre dispozitiv sau porturi de I/O. n general, perifericele sunt plasate n acest spaiu, dei procesorul poate permite maparea (suprapunerea) n memorie a perifericelor. Spaiul de I/O const din 64 Ko, i poate fi mprit n 64 Kporturi de 8 bii, 32 Kporturi de 16 bii sau, la 386/486, 16 Kporturi de 32 bii. Pentru a obine acces la acest spaiu nu se utilizeaz registre segment i implicit nici mecanismul de segmentare sau pagin. Pinul M/IO specific spaiul de memorie adresat (fizic sau I/O), deci dac se adreseaz o locaie de memorie sau un port de I/O. Instruciunile I/O, IN i respectiv OUT, pot furniza adresa direct n instruciune, ca o constant de 8 bii (deci pentru porturile din spaiul 0-255), sau indirect prin registrul DX (deci pentru tot spaiul de 64 K). Pe lng realizarea operaiilor de ieire utiliznd instruciunile specifice spaiului de I/O, se mai pot realiza transferuri de date prin acces direct la memorie (DMA-Direct Memory Access). DMA este mod special de organizare care const n maparea spaiului de I/O peste memorie. n acest mod, echipamentele periferice citesc i scriu direct n memorie, fr s se mai treac prin procesor. Pentru echipamentele foarte rapide, transferul prin intermediul procesorului (care se realizeaz element cu element) poate fi prea lent. Pentru aceste situaii a fost prevzut mecanismul de acces direct la memorie DMA. Acesta permite desfurarea n paralel de alte activiti ale procesorului, inclusiv de I/O, pentru a mri viteza de lucru a ntregului sistem. Totui, cele dou module, procesorul i DMA, nu pot utiliza simultan magistralele de date i adrese. Deci, prelucrarea paralel poate s apar doar dac procesorul are memorie cache i execut linii de program sau obine acces la date din aceasta, fr a utiliza magistrala. Chiar dac procesorul trebuie s atepte ca DMA s finalizeze un transfer, acesta este executat mai rapid de DMA dect sub controlul procesorului, fie n spaiul de I/O propriu, fie n cel mapat peste memorie.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic


Programare n limbaj de asamblare

9. Descriptori de segment.

Descriptori de segment
CPU face n mod automat referire la tabele ori de cte ori un registru segment este ncrcat cu un selector. Toate instruciunile care ncarc un registru segment vor face referire la tabelele din memorie, fr soft suplimentar. Aceste tabele conin valori de 8 octei, denumii descriptori. Exist descriptori de segment pentru segmentele de cod, stiv, date, descriptori de control ai sistemului pentru segmente de date speciale i operaii de transfer al controlului (comutare de task). Tabela descriptorilor segment face asocierea ntre un selector i un segment fizic din memorie, convertind astfel adresa virtual ntr-o adres fizic. Pe baza tabelei descriptorilor TD, procesorul determin poziia n memoria fizic a segmentului corespunztor unui anumit selector. Unele intrri din tabela DT sunt marcate ca segment nencrcat. Pentru aceste intrri din DT, procesorul genereaz o ntrerupere. Rutina de tratare a ntreruperii ncarc segmentul de pe disc n memorie, permind apoi accesul la informaia din acel segment. Un segment care nu mai este folosit este salvat pe disc de ctre sistemul de operare. Sistemul realizeaz operaia de interschimb de segmente ntre memorie i disc. Pentru a gestiona eficient memoria, sistemul de operare pstreaz n memorie segmentele cel mai recent utilizate. Pentru celelalte segmente, marcheaz intrrile n tabela DT ca segment nencrcat, utiliznd spaiul disponibil pentru alte segmente ce urmeaz a fi ncrcate. Descriptorii de segment de date i cod conin, pe lng adresa de baz a segmentului, i alte atribute de segment, incluznd: dimensiunea segmentului (1 64 Ko); drepturi de acces (read only, read/write, execute only, execute/read); prezena n memorie (pentru sistemele cu memorie virtual). Segmentele de memorie reprezint un tip de obiecte sistem. Alte obiecte sistem includ tabelele ce suport mecanismul de protecie, segmente speciale ce memoreaz starea procesorului i obiecte de control al accesului, denumite pori (gates). Descriptorii sunt grupai n tabele de descriptori. Examinnd selectorul, CPU determin descriptorul asociat selectorului i obiectul referit de descriptor. ntr-un cmp al descriptorului se memoreaz nivelul de privilegiu al obiectului (DPL). Cnd programul solicit accesul la un obiect sistem, cu un selector, pot s apar urmtoarele situaii:
accesul nu este permis; dac cererea violeaz o regul de protecie, controlul este transferat de la program la o rutin din sistemul de operare care, de obicei, sisteaz execuia procesului; accesul este permis, dar imposibil de recunoscut; de exemplu, dac obiectul nu este, curent, n memorie, atunci este apelat o rutin a sistemului de operare pentru a aduce obiectul n memorie (operaie denumit interschimb swapping), i returneaz controlul programului. Este permis, apoi, programului s rencerce accesul la obiect; accesul este recunoscut, la nivelul de privilegiu cerut (RPL);

Structura unui descriptor de segment este prezentat n figur.

31 adresa de baz 15 - 0 adresa baz


31 - 24

16

15 limita 15 - 0

adrese mici

G D 0

A V L

limita
19 - 16

P L

adresa baz S Type A


23 - 16

adrese mari

drepturi de acces Structura general a unui descriptor de segment (sistem, memorie sau poart) Cmpurile din structura unui descriptor de segment sunt descrise n continuare. Adresa de baz reprezint adresa de start a segmentului, fa de offsetul 0; ea este o adres de 32 de bii, reprezentat de octeii 2, 3, 4 i 7 din descriptor. Limita determin ultima unitate adresabil a segmentului; acest cmp are 20 de bii, alctuit din octeii 0 i 1 ai descriptorului, i ultimii 4 bii ai octetului 6 din descriptor. Limita poate fi definit n octei sau n entiti mai mari, denumite pagini, de 4 Ko. Aceasta poate conduce la o dimensiune maxim de 1 Mo, n primul caz, i 4 Go, n cel de-al doilea caz. Bitul G reprezint granularitatea sau rezoluia n care este definit limita unui segment. Limita unui segment cu rezoluie (granularitate) octet, este msurat n octei; un segment cu rezoluia pagin este msurat n entiti mai mari, denumite pagini. O pagin cuprinde 212 = 4 Koctei. Aceasta conduce la o limit a dimensiunii unui segment de 220 pagini de cte 4 Ko, deci n total 4 Go. Bitul P (present) este pus pe 1, cnd segmentul indicat de selector este prezent n memoria fizic. ntr-un sistem cu memorie virtual, sistemul de operare poate muta coninutul unor segmente pe disc, dac memoria fizic este plin. Atunci, sistemul de operare marcheaz descriptorul ca not-present, prin resetarea bitului P, pe 0. Dac o aplicaie ncarc un selector ntr-un registru segment i descriptorul asociat cu selectorul are P=0, se genereaz o ntrerupere not-present (11-nivelul/tipul ntreruperii). Sistemul de operare caut apoi o zon de memorie fizic liber, copiaz coninutul segmentului de pe disc napoi n memorie, actualizeaz descriptorul cu noua adres de baz, seteaz P=1, i rencepe instruciunea ntrerupt. DPL privilegiul unui descriptor: 0 cel mai privilegiat, 3 cel mai puin privilegiat. Un task poate obine acces la segmente cu acelai privilegiu sau mai mic. El poate citi/scrie date n segmente cu privilegiu egal sau mai mic. Un task poate apela segmente de cod de acelai privilegiu. Totui, accesele la segmente cu privilegiu mai mare pot fi recunoscute, indirect, prin pori (o caracteristic a mecanismului de protecie). Un task nu poate obine niciodat un acces la un segment de cod cu privilegiu mai mic. Nivelul de privilegiu al unui task, numit CPL (Current Privilege Level) este nivelul de privilegiu al segmentului de cod ce se execut. De obicei, cele mai importante poriuni ale sistemului de operare ruleaz la nivelul 0. Alte componente de sistem pot rula la un nivel mai puin privilegiat, iar aplicaiile ruleaz, tipic, pe nivelul 3. Bitul A (accessed) este setat cnd selectorul pentru descriptor este ncrcat ntr-un registru segment. Sistemul de operare poate utiliza acest bit pentru a determina care segmente nu sunt frecvent utilizate i pot fi transferate pe disc, dac este necesar. Bitul 6, din cmpurile adiionale, este denumit bitul D sau B: D (default), dac descriptorul este pentru un segment executabil; D=1 indic modul

nativ, adic setul implicit de instruciuni, iar D=0, un segment de cod 286, care ruleaz cu offseturi de 16 bii i setul de instruciuni de la 286. B (big), dac descriptorul este pentru un segment de date; B=1, pentru orice segment de date a crui dimensiune este mai mare de 64 Ko. AVL poate fi utilizat pentru: marcarea de segmente inutile (garbage collection); indicarea segmentelor ale cror adrese de baz nu trebuie modificate. Semnificaia biilor din octetul de acces este urmtoarea:
P (Present); dac este 1, segmentul este mapat n memoria fizic; n caz contrar, nu este mapat n memoria fizic, iar baza i limita nu sunt utilizate; DPL (Descriptor Privilege Level) este atributul de privilegiu, utilizat n teste de privilegiu; S (Segment Descriptor) specific tipul de segment definit de descriptor: = 1, este descriptor de segment de cod sau date; = 0, nu este descriptor de segment de cod sau date, ci descriptor de sistem; Type specific tipul segmentului: de cod sau de date; cei trei bii au urmtoarea semnificaie: (3) Executable; dac este 0 este un descriptor de segment de date, i n acest caz semnificaia biilor urmtori este: (2) Expansion Direction (ED); dac este 0, segmentul se extinde n sus, adic spre adrese mari (deci pentru date), astfel nct offset<=limita; dac este 1, segmentul se extinde n jos, adic spre adrese mici (stiv), i deci offset > limita; (1) Writeable; dac este 0, nu se poate scrie n acel segment, n caz contrar se poate scrie; (3) Executable; dac este 1, este un descriptor de cod, i atunci semnificaia biilor urmtori este: (2) Conforming; dac este 1, acest segment poate fi executat numai cnd CPL >= DPL, adic n conformitate cu criteriile de protecie (privilegiu); (1) Readable; dac este 0, segmentul nu poate fi citit, adic este numai executabil, alt fel el poate fi citit; A (Accessed); dac este 0, segmentul nu a fost adresat, iar dac este 1, selectorul de segment a fost ncrcat n registrul segment sau utilizat de instruciuni de test selector.

Formatele descriptorilor Sunt definite formate pentru cele trei tipuri de descriptori: program, sistem i pori. Descriptorii de segment de program au fost descrii anterior. Descriptorii de segment sistem descriu LDT i TSS. Nu se pot ncrca descriptorii pentru un LDT i un TSS ntr-un registru segment i nici citi sau scrie coninutul sub form de date. Pentru ca sistemul de operare s actualizeze un LDT sau TSS, el trebuie s creeze un descriptor de segment de memorie cu aceeai adres de baz i limit, denumit alias. Programele de depanare care permit modificarea segmentelor de cod al programului trebuie s creeze alias-uri, deoarece segmentele de cod nu pot fi scrise n condiiile regulilor de protecie ale familiei de procesoare Intel. Descriptorul de memorie (S=1) este descris n manual. Un descriptor de poart nu definete o zon de memorie, i deci nu are cmpurile: adres de baz i limit. n schimb, o poart face referire la un alt descriptor printr-un selector. Porile de

apel, ntrerupere i capcan, trebuie s conin selectorul pentru un segment de cod i un offset n segment. Porile task pstreaz un selector pentru un TSS, iar poriunea de offset a descriptorului este neutilizat. Descriptorii de poart, la fel ca i cei de sistem, au S = 0, i pot conine, de exemplu, una din valorile (n cmpul type): 5 poart TSS, 12 (4) poart apel 486/386 (286), 14 (6) poart ntrerupere 486/386 (286), 15 (7) poart capcan 486/386 (286). Tipurile de descriptori 1, 3, 4, 6 i 7 sunt utilizai la 286. Se pot utiliza descriptori de cod i date pentru sisteme de 16 bii, ntr-un sistem de 32 de bii, dar utilizarea descriptorilor de sistem de 16 bii poate crea probleme. Exist, totui, o diferen important ntre modul real de adresare i modul protejat, n ceea ce privete formatul actual i informaia coninut de selectoarele de segment. n modul real, selectorul de 16 bii constituie biii cei mai semnificativi ai adresei de baz a segmentului fizic. n schimb, selectorul de segment n modul protejat are urmtorul format: Semnificaia ultimilor doi bii este urmtoarea: 15 INDEX Formatul unui Selector
RPL (Requested Privilege Level) nivelul de privilegiu dorit; TI (Table Indicator) acest bit face selecia ntre tabela de descriptor global / local.

3 2 1 0 TI RPL

Ceilali bii (153) selecteaz intrarea respectiv din tabel. Deci biii RPL, din cmpul 10, nu sunt implicai n selectarea i specificarea segmentelor. Ceilali 14 bii din componena selectorului desemneaz n mod unic un segment particular. Spaiul de adres virtual al unui program va fi format din cel mult 214 segmente distincte. ntruct dimensiunea maxim a unui segment este de 64 Ko (216), rezult c spaiul virtual de adres al unui program poate ajunge la 1 Go (214216 = 230) de locaii adresabile individual. La 386/486, ntruct dimensiunea unui segment este de 32 de bii, se ajunge la un spaiu total de adres virtual de 64 To (214 232 = 246). Spaiul total de adresare virtual este ulterior subdivizat n dou jumti separate, deosebite prin bitul TI. Aceste dou jumti sunt spaiul global de adrese i spaiul local de adrese. Spaiul global este utilizat pentru date i procese de sistem, incluznd softul sistemului de operare, rutine de bibliotec i alte servicii de sistem, de obicei partajate. Pentru progr amele de aplicaie sistemul de operare apare ca un set de rutine, de servicii, ce sunt accesibile tuturor task urilor. Spaiul global este partajat de toate task-urile, pentru a evita duplicate inutile ale rutinelor de servicii de sistem i pentru a facilita partajarea datelor i a rutinelor de ntrerupere. Cealalt jumtate a spaiului virtual este mapat separat pentru fiecare task din sistem i este cunoscut sub numele de spaiu local de adres. n general, segmentele de cod i date dintrun spaiu local de adrese a unui task sunt specifice task-ului sau utilizatorului respectiv, ca n figura urmtoare.

Task 1 Spaiu Adres Local Spaiul de adres virtual al taskului 2

Spaiul de adres virtual al taskului 1

Spaiu Adres Global

Spaiul de adres virtual al taskului 3

Task 2 Spaiu Adres Local

Task 3 Spaiu Adres Local

Spaiile virtuale de adrese pentru trei taskuri Tabela GDT (Global Descriptor Table) conine o descriere complet a spaiului global de adrese i este unic. Tabelele LDT (Local Descriptor Table) conin descriptori ai spaiului de adrese local fiecrui task. Un task se caracterizeaz prin perechea de tabele GDT (comun tuturor task-urilor) i LDT (specific fiecrui task). Tabela GDT, fiind unic pentru toate taskurile, nu are nevoie de descriptor. Adresa de baz i dimensiunea ei sunt pstrate ntr -un registru special, GDTR (Global Descriptor Table Register). Analog exist un registru LDTR, care memoreaz adresa de baz i mrimea tabelei LDT curente asociat cu task-ul n execuie. Registrele GDTR i LDTR sunt accesibile numai sistemului de operare, prin intermediul unor instruciuni specifice. Fiecare task i are propria tabel LDT, care conine descriptorii segmentelor de cod i date utilizate. De asemenea, task-ul poate avea propria tabel a vectorilor de ntrerupere (IDT Interrupt Descriptor Table), care conine descriptorii vectorilor de ntrerupere specifici task-ului. Tabela IDT are aceeai structur ca tabela DT. Accesul la aceste tabele pentru citire i scriere se face prin instruciuni specifice: LGDT, SGDT, LLDT, SLDT, LIDT, SIDT ( Load /Store Global / Local / Interrupt Descriptor Table Register). Termenul de multitasking se refer la capacitatea de a executa simultan mai multe programe separate (task-uri). Deoarece calculatorul dispune de un singur procesor, task-urile nu se execut n paralel, ci procesorul comut de la un task la altul, crend astfel impresia de execuie simultan. Procesoarele familiei IA, ncepnd de la 286, implementeaz acest concept prin mijloace hard. Ele asigur protecia task-urilor astfel nct memoria utilizat de un task s nu fie accesibil unui alt task. Instruciunea ARPL (Adjust Requested Privilege Level) folosit de sistemul de operare modific nivelul de privilegiu al selectorului destinaie astfel nct s coincid cu acela al sursei. Descriptorul de segment conine un octet ce specific drepturile de acces la acel segment. Sistemul de operare poate modifica acest octet folosind instruciunea LAR (Load Access Rights), iar task-urile pot determina dreptul de acces prin instruciunile VERR, VERW ( Verify Segment for Reading / Writing). Instruciunile specifice modului protejat permit gestionarea corect a task-urilor. La comutarea de la un task la altul, procesorul trebuie s salveze starea task-ului curent. Starea task-ului curent se

refer la coninutul registrelor generale, registrul indicatorilor de condiii, descriptorii segmentelor pentru cod i date, selectorul pentru tabela LDT i legtura ctre task-ul executat anterior. Starea task-ului se memoreaz ntr-un segment n memorie, numit segment de stare task, TSS (Task State Segment). Descriptorul pentru segmentul de stare task este un descriptor special ce se afl n tabela GDT. Procesorul are un registru task, TR (Task Register), care conine un selector pentru acel descriptor special, selector care identific n mod unic task-ul. Accesul la registrul de stare task se realizeaz prin instruciunile STR i LTR (Store/ Load Task Register). Aceste instruciuni specifice modului protejat nu se folosesc, de regul, cnd se lucreaz sub sistemul de operare MS-DOS. Codul BIOS conine ns, instruciuni care testeaz procesorul n modul protejat. Secvena respectiv de instruciuni comut procesorul din modul real n modul protejat i apoi invers.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

10. Procesoare superscalare.

Procesoare superscalare
Procesoarele superscalare, exploatnd paralelismul arhitecturii, pot executa mai multe instruciuni ntr-un ciclu main. Metodele superscalare, rezultat al extinderii principiilor ce stau la baza procesoarelor RISC, au fost aplicate ncepnd din anii 1990 unei game largi de arhitecturi, de la cele specifice RISC (DEC Alpha), pn la unele evident non-RISC (Intel x86).

Arhitectura intern
Elementele (unitile) principale ale arhitecturii, prezentate n figura de mai jos, realizeaz, n ordinea n care sunt parcurse de fluxul de instruciuni, urmtoarele operaii: citirea instruciunilor (fetch) i predicia salturilor, decodificarea instruciunilor i analiza dependenelor de date, alocarea unitilor de execuie, analiza i execuia operaiilor cu memoria, reordonarea instruciunilor i nscrierea rezultatelor. La baza acestei arhitecturi st o implementare a unei benzi de asamblare (pipeline), ale crei etape se suprapun, ntr-o oarecare msur, peste fazele de procesare.

Fiier registre n virgul mobil


Buffere de instruciuni n virgul mobil Predecodare Cache instruc. Buffere instruc.

Uniti funcionale

Decodare, redenumire, despachetare


Buffere de instruciuni ntregi / de adres Uniti func i cache de date

Interfa de memorie

Fiier registre ntregi

Reordonare

Organizarea hardware a unui procesor superscalar

Un procesor superscalar aduce din memorie i decodific, n mod obinuit, mai multe instruciuni simultan. Ca parte a acestui proces, efectele salturilor condiionate sunt anticip ate pentru a asigura un flux nentrerupt de instruciuni. Fluxul de instruciuni, adus anticipat n bufferul de prefetch (citire anticipat a instruciunilor), este analizat pentru determinarea dependenelor de date, iar instruciunile independente sunt distribuite unitilor funcionale, n conformitate cu tipul lor. Aici ncepe, n paralel, execuia instruciunilor, n funcie, mai ales, de disponibilitatea operanzilor i mai puin de ordinea n care se afl acetia n programul secvenial. Terminarea execuiei instruciunilor i nscrierea rezultatelor are loc n aa fel nct starea logic a procesului este actualizat n ordinea secvenial a programului, pentru a da posibilitatea tratrii precise a unei eventuale ntreruperi. Dependenele de date apar ntre instruciuni care obin acces la acelai registru sau locaie de memorie. n acest moment se spune c exist un hazard datorat posibilitii ca instruciunile s se execute ntr-o ordine incorect. Aceste hazarduri pot fi de tipurile WAR, WAW i RAW. Hazardul WAR (Write After Read), adic scriere dup citire, apare cnd instruciunile trebuie s modifice o locaie de memorie, dar trebuie s atepte ca toate instruciunile anterioare ce necesit vechea valoare s o citeasc. Hazardul WAW (Write After Write), adic scriere dup scriere, apare cnd mai multe instruciuni modific aceeai locaie; modificrile trebuie realizate n ordinea precizat de programul secvenial, pentru ca la locaia respectiv s rmn, n final, valoarea corect. Aceste dou tipuri de hazarduri sunt artificiale, fiind cauzate de un cod neoptimizat, de numrul limitat de registre, de necesitatea de a economisi memorie sau de ciclurile programului (n care o instruciune poate fi dependent de ea nsi). n general, aceste dependene pot fi eliminate prin redenumirea resurselor respective. Hazardurile RAW (Read After Write), adic citire dup scriere sunt cele mai frecvente, deoarece o instruciune poate citi o valoare numai dup ce valoarea a fost furnizat de instruciunea care o scrie. Mai toate procesoarele superscalare utilizeaz o memorie rapid, de mici dimensiuni, de tip cache, care conine instruciunile cel mai recent executate, pentru a reduce ntrzierile, datorate accesului la memoria principal, care este mai lent, i pentru a mri numrul de instruciuni aflate, la un moment dat, la dispoziia procesorului. Cache-ul de instruciuni este organizat n blocuri coninnd instruciuni consecutive. Dac instruciunea ce urmeaz a fi executat nu este n cache, atunci blocul care o conine este adus, n ntregime, din memoria principal, i scris n cache. Pentru a executa mai multe instruciuni n paralel, faza fetch trebuie s aduc, din memoria cache, mai multe instruciuni ntr-un ciclu. Din acest motiv, exist dou cache-uri: unul pentru date i unul pentru instruciuni. Numrul maxim de instruciuni adus ntr-un ciclu ar trebui s fie egal cu rata de decodificare i execuie; el este, ns, ceva mai mare, pentru a compensa miss urile n cache (adic lipsa acelei instruciuni din cache) i situaiile n care se pot aduce doar un numr limitat de instruciuni (de exemplu, dac o instruciune transfer controlul unei alte instruciuni, aflate n interiorul unui bloc din cache, instruciunile ce o preced n bloc sunt inutile). Citirea normal a instruciunilor (fetch) incrementeaz contorul de program cu numrul de instruciuni aduse, pentru a obine adresa urmtorului bloc. La ntlnirea unei instruciuni de ramificaie, acest mecanism (fetch) trebuie reorientat pentru a folosi noua adres indicat de instruciunea de salt. Modul de tratare a instruciunilor de salt este vital pentru performana sistemului. Instruciunile de ramificaie sunt tratate n 4 pai:

1. 2. 3. 4.

recunoaterea instruciunii de ramificaie; determinarea comportrii instruciunii de ramificaie; calculul adresei de ramificaie; transferul controlului.

1. Recunoaterea instruciunii de ramificaie poate fi realizat mai rapid dac n cache-ul de instruciuni se memoreaz i informaii de decodificare, adic nite bii suplimentari generai de logica de predecodificare i memorai pe msur ce instruciunile sunt aduse n cache. 2. Determinarea comportrii instruciunii de ramificaie este dependent de instruciunile precedente incomplet executate. Pentru a evita ateptarea terminrii execuiei acestora se folosesc metode de predicie a comportrii instruciunilor de salt. Unele predictoare folosesc informaia static, prezent n codul binar: unele instruciuni de salt determin transferul controlului mai des dect altele, cum este cazul instruciunilor de ciclare (compilatoarele pot introduce informaii despre probabilitatea de efectuare a salturilor, pe baza analizei programului n limbaj de nivel nalt). Majoritatea predictoarelor folosesc informaia dinamic, disponibil n momentul execuiei programului; aceasta se refer la comportarea anterioar a instruciunii de salt (curent, i eventual a celor precedente) i este pstrat n tabele de predicie sau chiar n blocurile din cache care conin instruciunea de salt. Aceste tabele de predicie sunt organizate ntr -o manier asemntoare memoriilor cache, fiind accesibile cu adresa instruciunii de salt care trebuie executat anticipat. Istoria comportrii saltului este nregistrat folosind contoare, ce sunt incrementate la execuia saltului, respectiv decrementate la nendeplinirea condiiei de salt. Valoarea acestui contor reflect comportarea dominant a instruciunii de salt. Se utilizeaz, mai nou, scheme de predicie corelate, pe baza a dou informaii: istoria saltului curent i, respectiv, situarea acestuia n context, pe baza salturilor anterioare. Procesul de citire a instruciunilor (fetch) continu pe baza prediciei, pn n momentul n care condiia de salt poate fi evaluat pe baza datelor concrete. Acum informaia de predicie poate fi actualizat. Dac predicia nu a fost corect, mecanismul de citire (fetch) trebuie reorientat de la o nou adres, acum cunoscut cu precizie. n plus, trebuie nlturate i efectele produse de execuia speculativ a instruciunilor aduse pe baza prediciei (n acest caz, eronate). 3. Calculul adresei de salt se realizeaz de obicei, relativ la contorul programului i poate fi precizat printr-o valoare coninut n codul instruciunii, eliminndu -se necesitatea accesului la registre. Necesitatea accesului la registre, pentru calculul adresei de salt a condus la introducerea n tabela de predicie a adresei folosit ultima oar de instruciunea de salt. 4. Transferul controlului. ntrzierile datorate complexitii etapelor anterioare trebuie compensate, de obicei, prin folosirea bufferului de instruciuni deja amintit. Anterior, procesoarele RISC foloseau aa-numitele salturi ntrziate, prin care execuia instruciunii urmtoare celei de salt era suprapus peste faza de fetch a instruciunii care urma conform ramificaiei. Structura pipeline a procesoarelor superscalare complic mult aplicarea acestei metode.

Decodificarea instruciunilor i analiza dependenelor de date


n aceast faz, instruciunile sunt scoase din bufferul de instruciuni i examinate pentru stabilirea dependenelor de control i de date necesare etapelor urmtoare din banda de asamblare. Acum se detecteaz dependenele reale (hazardurile RAW) i se elimin celelalte tipuri de hazarduri la registre (WAW, WAR). Tot n aceast faz, instruciunile sunt distribuite n bufferele asociate unitilor de execuie, de unde vor fi preluate i executate ntr-o faz ulterioar. n urma decodificrii, fiecrei instruciuni i este asociat o structur de date (staie de rezervare) sub forma unei liste coninnd operaia care trebuie executat, identificatori pentru elementele care constituie operanzii, respectiv pentru elementele care vor conine rezultatele (tag-

uri), unitate ocupat sau nu etc. n imaginea static a programului, aceste elemente sunt precizate de locaii de memorie i de registre logice, indicate de arhitectura procesorului. Pentru a preveni hazardurile WAR i WAW i a mbunti gradul de paralelism al execuiei, registrelor logice le sunt asociate elemente de memorare fizice. Resursele logice ale procesorului pot fi vzute, deci ca nume simbolice, folosite pentru a descrie operaia dorit. n cursul execuiei paralele, unei resurse logice i pot fi asociate mai multe valori, memorate n resurse fizice distincte, corespunztoare diferitelor momente de execuie ale procesului secvenial. Cnd o instruciune creeaz o nou valoare pentru un registru logic, acestuia i este asociat o locaie fizic i este redenumit n structura de date asociat, n faza de decodificare, cu identificatorul locaiei ce va conine valoarea nou creat. n orice instruciune ulterioar n care registrul logic apare ca operand surs, el va fi redenumit cu identificatorul respectivei locaii. O prim metod de redenumire folosete un set de registre fizice, mai mare dect cel logic. Asocierea dintre un registru logic i valoarea coninut ntr -un registru fizic se face pe baza unei tabele de mapare. Redenumirea are loc la decodificarea instruciunilor, n ordinea secvenial a programului. Registrele fizice neocupate sunt pstrate ntr -o list de resurse libere, de unde sunt luate, n momentul n care sunt atribuite unui registru logic prin intermediul tabelei de mapare. Dac lista de resurse este goal, decodificarea instruciunilor urmtoare este temporar oprit. Asocierea dintre un registru logic i unul fizic are loc atunci cnd registrul logic este redenumit din nou i ultima instruciune, n care apare ca operand surs, i -a ncheiat execuia. n acest moment, registrul fizic este trecut n lista de resurse libere. O alt metod de redenumire are numrul de registre logice egal cu acela al de registrelor fizice. Se utilizeaz un buffer de reordonare (reorder buffer), care conine cte o intrare pentru fiecare instruciune n curs de execuie. Bufferul de reordonare este implementat ca o memorie (de tip FIFO), instruciunile fiind introduse aici n ordinea secvenial din program. n momentul n care instruciunile i termin execuia, n intrarea corespunztoare din buffer se nscriu rezultatele produse. Aceste rezultate vor fi nscrise n setul de registre doar atunci cnd intrarea respectiv ajunge ultima n buffer. Setul de registre va conine, deci, ntotdeauna valori corespunztoare execuiei secveniale a instruciunilor, un lucru deosebit de util din perspectiva tratrii precise a excepiilor. Valoarea logic a unui registru poate fi coninut fie n setul fizic de registre, fie n bufferul de reordonare. Cnd o instruciune este decodificat, rezultatul ei este asociat cu o intrare din bufferul de reordonare i tabela de mapare este actualizat. Tabela de mapare este accesibil folosind registrele surs ale instruciunilor i indic dac valorile corespunztoare acestora se afl n setul de registre sau n bufferul de reordonare. n concluzie, indiferent de metoda utilizat, redenumirea registrelor elimin dependenele artificiale, datoare hazardurilor WAW i WAR.

Alocarea unitilor de execuie paralel a instruciunilor


n fazele anterioare, ale benzii de asamblare, se formeaz structuri de date asociate instruciunilor coninnd informaii referitoare la operaia care urmeaz s se execute i la modul de localizare a operanzilor fizici. Urmtoarea etap este aceea de a determina, pe baza acestor informaii i innd seama de disponibilitatea resurselor, instruciunile care pot fi executate. Pentru un model ideal de procesor superscalar, avnd resurse infinite, o instruciune este gata de execuie n momentul n care operanzii surs sunt disponibili. Restriciile care se impun acestui model provin din limitarea numrului de uniti de execuie de un anumit tip, interconectarea acestora cu setul de registre sau bufferul de reordonare, precum i metoda de organizare a bufferelor care conin structurile de date, asociate instruciunilor (fereastra de execuie), ce pot fi de tip: coad simpl, coad multipl sau staii de rezervare.

n primul caz, coada simpl, execuia instruciunilor are loc n ordinea secvenial din program (in-order), iar redenumirea registrelor nu este necesar. Disponibilitatea operanzilor poate fi controlat prin bii de rezervare asociai fiecrui registru, un registru fiind rezervat pe ntreaga durat a execuiei unei instruciuni care l modific. Din punct de vedere al disponibilitii operanzilor, o instruciune i poate ncepe execuia n momentul n care operanzii si nu sunt rezervai de instruciunile anterioare. Pentru cea de-a doua metod instruciunile se execut in -order, din fiecare coad, dar nu neaprat n ordinea n care apar n programul secvenial, adic out-of-order ntre cozi. Fiecare coad conine instruciuni de un anumit tip, de exemplu fie instruciuni aritmetice ntregi, fie n virgul mobil, fie instruciuni de transfer (load/store). Redenumirea registrelor poate fi folosit ntro form restrns, lund n considerare doar pe aceia care pot fi operanzi comuni instruciunilor aflate n mai multe cozi (de exemplu registrele care pot fi operanzi pentru instruciunile de transfer de tip load/store). O a treia metod, staiile de rezervare, propuse n algoritmul lui Tomasulo, permite execuia complet out-of-order a instruciunilor, evident innd seama de hazardurile RAW. Staiile de rezervare sunt structuri de date asociate fiecrei instruciuni, avnd urmtoarele intrri: operaia ce trebuie executat, identificatori pentru fiecare operand surs i destinaie, valorile propriu-zise ale operanzilor surs, biii de validare, care indic c valorile operanzilor surs, coninute n staia de rezervare, sunt corecte. Cnd o instruciune i termin execuia i produce un rezultat, identificatorul destinaie este comparat cu identificatorii surs ai staiilor de rezervare asociate instruciunilor care ateapt date, iar n caz de potrivire, rezultatul este nscris n cmpul valoare i validat. n momentul n care toi operanzii sunt disponibili, instruciunea din staia de rezervare se poate executa. Algoritmul reduce mult din presiunea, la citire, asupra seturilor de registre, prin transferul (bypassing) rezultatelor direct ntre staiile de rezervare.

Operaiile cu memoria
n cazul procesoarelor superscalare, operaiile cu memoria necesit o tratare special. Cele mai multe seturi de instruciuni RISC permit accesul la memorie doar prin instruciuni specifice load i store. Pentru a reduce latena operaiilor cu memoria sunt folosite ierarhii de memorie, n ideea c accesele cele mai frecvente la memorie vor fi rezolvate de memoriile cache, aflate la nivelurile inferioare ale acestor ierarhii. Practic, toate procesoarele actuale conin cel puin un cache de date, tendina general fiind de utilizare a mai multor niveluri de cache. Spre deosebire de instruciunile aritmetice/logice, ai cror operanzi pot fi identificai nc din faza de decodificare, locaiile de memorie la care obin acces instruciunile de transfer (load/store) nu pot fi determinate dect n faza de execuie. Determinarea locaiei de memorie necesar unei astfel de instruciuni necesit un calcul de adres, adic o adunare de ntregi. Dup calculul adresei logice este necesar o translatare a acesteia, pentru obinerea adresei fizice (datorit folosirii mecanismului de paginare). Dup obinerea adresei valide, se poate executa operaia respectiv cu memoria. Ca i n cazul operaiilor cu registre, este de dorit ca un numr ct mai mare de operaii cu memoria s se execute ct mai rapid. Acest lucru poate implica: reducerea latenei acceselor la memorie, executarea simultan a mai multor operaii cu memoria, suprapunerea execuiei opera iilor cu memoria cu execuia unor instruciuni de alte tipuri, executarea out -of-order a operaiilor cu memoria. Totui, datorit numrului de locaii de memorie, mult mai mare dect cel al registrelor, precum i datorit faptului c memoria poate fi adresat i indirect, prin registre, soluiile anterioare nu sunt aplicabile. n loc de a folosi tabele de redenumire cu intrri pentru toate locaiile de memorie, ca n cazul registrelor se pstreaz informaii numai pentru subsetul de locaii asupra crora se

execut operaii, la un moment dat. Pentru a permite accese multiple la memorie, ierarhia de memorii trebuie s fie de tip multiport, permind mai multe accese ntr -un ciclu. Uzual, este suficient ca numai memoria cache primar s fie de tip multiport, d eoarece este probabil ca majoritatea acceselor s fie rezolvate aici. Mai mult, transferurile n cache din memoria de la nivelurile superioare, au loc sub form de blocuri ce includ mai multe cuvinte de date consecutive. Pentru a permite suprapunerea operaiilor cu memoria cu alte instruciuni (fie cu memoria, fie de alte tipuri), ierarhia de memorie trebuie s fie fr blocare; cu alte cuvinte, dac data solicitat nu se afl n cache, urmtoarele instruciuni trebuie s se poat executa, fr a atepta terminarea instruciunii blocate, i la fel i n cazul datelor. Suprapunerea execuiei operaiilor cu memoria i executarea lor out-of-order presupune rezolvarea hazardurilor i conservarea semanticii programului secvenial. Dificultatea principal const n determinarea n timp util a adreselor fizice de acces pentru instruciunile de transfer, pentru a le procesa out-of-order. Se utilizeaz buffere de adrese, de tip FIFO, n ordinea n care apar n program, n care sunt nscrise adresele la care obin accesul instruciunile store n curs de execuie. Adresele sunt meninute aici pn cnd datele necesare execuiei instruciunii sunt disponibile, iar instruciunea se poate ncheia, prin scrierea efectiv n memorie, n momentul n care ajunge ultima n buffer-ul FIFO. Adresele la care obin accesul instruciunile load sunt comparate cu adresele din buffer, iar n caz de potrivire trebuie s atepte terminarea instruciunii store corespunztoare.

nscrierea rezultatelor
n aceast ultim faz a execuiei unei instruciuni, efectele ei modific starea logic a procesului din care face parte. Scopul acestei faze este de a implementa un mecanism de modificare secvenial a acestei stri logice, dei instruciunile programului au fost executate speculativ, out -of-order. ntr-o prim tehnic, starea mainii este dublat de un buffer history, actualizat conform ordinii secveniale a programului. Instruciunile actualizeaz starea mainii pe msur ce sunt executate; cnd este necesar o stare precis (de exemplu, n cazul unei excepii), starea este regsit din acest buffer istorie. Alt metod folosete separarea strii logice (arhitecturale) a mainii de starea sa fizic. Starea fizic este modificat imediat dup terminarea execuiei instruciunilor, n timp ce starea logic se actualizeaz n ordinea secvenial a programului, fcnd astfel transparent execuia speculativ a instruciunilor. Starea fizic a mainii este reprezentat de bufferul de reordonare, de unde rezultatele produse de instruciuni sunt mutate, n aceast faz, n setul de registre logice sau n memorie (pentru instruciunile store). Pe lng identificatorii logici i valorile operanzilor fiecrei instruciuni, n bufferul de reordonare se nscrie i valoarea registrului contor de instruciuni (PC), necesar restaurrii strii precise a mainii, n cazul apariiei unei excepii. Dei tehnica bufferului history a fost implementat n unele procesoare superscalare, tehnica preferat rmne cea cu buffer de reordonare, deoarece, pe lng implementarea unui mecanism de excepii precis, ndeplinete i funcia de redenumire dinamic a registrelor.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

12. ntreruperi BIOS i DOS.

Utilizarea ntreruperilor BIOS i DOS


Elemente privind sistemul de operare MS-DOS Un sistem de operare (SO) permite utilizatorului controlul asupra sistemului de calcul; el poate fi definit ca o colecie de proceduri i programe. Aceste proceduri pot fi apelate din programele utilizatorului i permit acestuia accesul la resursele calculatorului, la memorie i la periferice, precum i la o serie de informaii care descriu contextul curent n care funcioneaz calculatorul. Sistemul de operare furnizeaz acces general, independent de dispozitiv, la resursele unui calculator (tastatur, monitor, uniti de disc). Aceasta nseamn c resursele respective nu trebuie specificate cu precizie, deoarece sistemul controleaz operaiile de I/O la nivel de dispozitiv, independent de programul ce a solicitat operaia. Funciile SO Gestiunea fiierelor. Sistemul de operare administreaz directoarele i fiierele de pe discurile sistemului. Programele creeaz i actualizeaz fiiere, dar sistemul este responsabil pentru administrarea spaiului i a locaiilor de pe disc. Intrri/Ieiri. Programele solicit date de intrare de la sistem sau furnizeaz date ctre sistem prin intermediul ntreruperilor. Programul nu trebuie s se ocupe de programarea I/O la nivel jos. ncrcarea programelor. Cnd un utilizator sau un program solicit execuia unui program, ncrctorul de program realizeaz operaiile de acces la programul de pe disc, plasndu-l n memorie i iniializndu-l pentru execuie. Administrarea memoriei. Cnd ncrctorul de programe ncarc un program de pe disc n memorie pentru execuie, el i aloc un spaiu de memorie suficient pentru programul propriu-zis i pentru datele sale. Programele pot prelucra datele n zona de memorie alocat, pot elibera memoria care nu este necesar sau pot solicita alocarea de memorie suplimentar (alocare dinamic). Manipularea ntreruperilor. Sistemul permite utilizatorilor s instaleze programe rezidente, care se ataeaz la sistemul de ntreruperi pentru a executa funcii speciale. Organizarea SO Sistemul de operare are trei componente majore: IO.SYS, MSDOS.SYS, COMMAND.COM. IO.SYS realizeaz funciile de iniializare la pornirea sistemului (boot) i conine funciile importante de I/O (citire de la dispozitive externe n memorie, respectiv scriere din memorie la dispozitivele externe) i driverele dispozitivelor care suplimenteaz sau nlocuiesc suportul de I/O primar din ROM (BIOS). IO.SYS este o interfa de nivel jos cu rutinele BIOS din ROM. Pe lng determinarea strii dispozitivelor conectate la calculator, aceast component iniializeaz i adresele din tabela vectorilor de ntrerupere, pn la ntreruperea 20H. Acest fiier conine extensii ale BIOS-ului, permind extinderea configuraiei standard, fr modificarea PROM-ului ce conine BIOS-ul; de asemenea, el realizeaz actualizri ale BIOS-ului, corespunztoare noilor versiuni de sisteme de operare. Aceast component este memorat pe disc ca un fiier de sistem ascuns, i este cunoscut pe PC-uri sub numele de IBMBIO.COM. Coreciile sau extensiile BIOSului se realizeaz prin actualizarea (resetarea) vectorilor de ntrerupere de ctre IO.SYS, astfel ca operaiile BIOS s treac mai nti prin IO.SYS i apoi, dac este cazul, la BIOS. Motivul utilizrii ntreruperilor pentru apeluri BIOS, n locul apelului unor locaii fixe din ROM, const n a permite nlocuirea programelor BIOS cu programe IO.SYS. MSDOS.SYS acioneaz ca nucleu al sistemului i se ocup de managementul fiierelor, memoriei i al sistemului de I/O (procedurile de tratare a operaiilor de intrare/ieire la nivel

logic). Aceast component este memorat pe disc ca fiier sistem ascuns (era denumit IBMDOS.COM) i este o interfa de nivel ridicat pentru programele ale cror adrese sunt depuse n tabela vectorilor de ntrerupere, pentru ntreruperile de la 20H la 3FH. Apelul procedurilor DOS se face utiliznd ntreruperi soft. Exist dou tipuri de servicii DOS: ntreruperi i funcii. Funciile DOS se apeleaz cu ntreruperea 21h (INT 21H) i numrul funciei n registrul AH, iar celelalte ntreruperi DOS se apeleaz prin ntreruperi soft: INT n. Funciile DOS furnizeaz majoritatea serviciilor de I/O cu tastatura, display-ul, imprimanta, operaii cu fiiere de pe disc (deschidere/nchidere, creare/tergere, manipulare date din fiiere, creare directoare etc.). Cnd un program utilizator solicit un serviciu DOS, INT 21H, operaia furnizeaz informaia ctre MSDOS.SYS prin intermediul registrelor. Pentru a executa serviciul solicitat, MSDOS.SYS poate translata informaia ntr-unul sau mai multe apeluri ctre IO.SYS, care la rndul su apeleaz BIOS, astfel: Serviciu I/O solicitat de utilizator
MSDOS.SYS IO.SYS BIOS Dispozitiv

MSDOS.SYS ncarc, de asemenea, COMMAND.COM. COMMAND.COM este procesorul de comenzi, care acioneaz ca interfa ntre utilizator i sistemul de operare. Acest program afieaz promptul, urmrete tastatura, (citete de la tastatur comenzile utilizator) i proceseaz aceste comenzi. Sistemul de operare MS-DOS conine urmtoarele elemente: BIOS (Basic Input/Output System), rezident n memorie; rutina pentru ncrcarea SO de pe disc (nregistrarea de pornire); programele enumerate anterior: IO.SYS, MSDOS.SYS, COMMAND.COM (sau IBMBIO.COM, respectiv IBMDOS.COM); programe utilitare (FORMAT, DISKCOPY etc.). BIOS-ul (Basic Input Output System, adic sistemul de baz de intrare/ieire, memorat n ROM) ncepe la adresa 768K i controleaz dispozitivele de I/O (cum ar fi consola, controlerul de disc etc.). BIOS-ul conine un set extins de rutine de intrare/ieire i tabele care indic starea dispozitivelor sistemului. Att DOS-ul ct i programele utilizator pot solicita rutinele BIOS pentru comunicaia cu dispozitivele ataate sistemului. Metoda de interfaare cu BIOS -ul este prin intermediul ntreruperilor soft. n continuare, ncepnd de la adresa 960K a memoriei ROM se afl programe care controleaz funciile de baz ale calculatorului, cum ar fi: testele de la pornirea calculatorului (power-on self-test), configuraia de puncte pentru modul grafic i programul de ncrcare de pe disc (disk self-loader). La pornirea calculatorului, BIOS-ul realizeaz diferite verificri i ncarc date speciale de sistem de pe disc n memoria RAM. Prin procedura de ncrcare (boot-up) se ncarc o poriune a sistemului de operare n RAM. n faza de testare se realizeaz i identificarea legturilor cu PROM-urile externe plcii de baz. Aceste PROM-uri includ interfeele pentru diverse echipamente periferice. Cutarea acestor PROM-uri se face n spaiul 0C800H-0E00H. Un astfel de PROM conine o secven de iniializare, care va fi executat n aceast faz de identificare. Efectul acestor secvene const din stabilirea adreselor de tratare a ntreruperilor corespunztoare, iniializarea echipamentelor i a variabilelor asociate. Memoriile ROM sau EPROM constau din chip-uri speciale, care permit pstrarea informaiei i dup decuplarea tensiunii de alimentare.

Memoria RAM & ROM are urmtoarea structur: 64K sistemul de intrare /ieire, de baz (ROM) F0000H 192K memoria extins (ROM) C0000H 128K memoria video (RAM) A0000H 640K RAM Memoria superioar

Memoria convenional

00000H BIOS-ul conine urmtoarele programe: testare pentru toate resursele calculatorului (procesor, memorie, sistemul de ntreruperi i iniializarea tabelei, tastatur, display, disc, ceas de timp real etc.); program pentru ncrcarea nregistrrii destinat ncrcrii sistemului de operare de pe disc; rutine pentru comanda i controlul operaiilor de intrare/ieire la nivel fizic, pentru toate echipamentele; rutine pentru tratarea ntreruperilor externe, provenite de la: ceasul de timp real (ntreruperea 8); tastatura (nivelul 9); unitatea de disc (nivelul 14); Dac programele de test nu semnaleaz nici o eroare, atunci se va lansa n execuie programul de ncrcare a sistemului de operare de pe disc, dup care se va ceda controlul acestuia, altfel procesorul intr n starea halt. Procesul de iniializare (boot) La pornire, prima instruciune executat este cea de la adresa FFFF0H (CS=FFFFH, IP=0000H), care este punctul de intrare n BIOS (din ROM). Pornirea calculatorului determin o iniializare la rece (cold boot). n acest caz, procesorul este iniializat (resetat), pune toate locaiile de memorie pe zero, realizeaz o verificare a bitului de paritate al memoriei i pune CS=FFFF[0]H, iar IP=0000H. Prima instruciune de executat este la adresa FFFF:0H, punctul de intrare n BIOS. BIOS memoreaz, de asemenea, valoarea 1234H la adresa 40[0]:72H pentru a semnala o iniializare la cald CTRL + ALT + DEL (warm boot), nu pentru a realiza autotestul POST (power-on self-test). Rutina BIOS verific diferite porturi pentru a identifica i iniializa dispozitivele ce sunt ataate la calculator, utiliznd INT 11H (determinare echipamente) i INT 12H (determinare dimensiune memorie). BIOS-ul iniializeaz apoi dou zone de date: Tabela vectorilor de ntrerupere (ce ncepe de la adresa 0). Zona de date BIOS, ce ncepe de la adresa 40h:0000h, rezervat pentru dispozitivele ataate. BIOS-ul determin dac este prezent un disc de sistem; n caz afirmativ, ncarc nregistrarea de iniializare, prin execuia ntreruperii INT 19H. Programul de ncrcare se afl pe pista 0, sectorul 1, faa 0 a oricrui disc sistem (formatat cu ajutorul comenzii FORMAT/S) i este ncrcat la adresa

7C00:0000H, dup care i cedeaz controlul. Acest program (ncrctorul) este un sistem de operare temporar, cruia rutinele BIOS i transfer controlul, dup ncrcarea lui n memorie; acest program ncarc fiierele de sistem, IO.SYS i MSDOS.SYS, de pe disc n memorie i transfer controlul la punctul de intrare al IO.SYS, care conine driverele dispozitive i alte programe specifice hard-ului. IO.SYS i schimb poziia n memorie i transfer controlul la MSDOS.SYS. Acest modul iniializeaz tabelele interne DOS i zona DOS a tabelei de ntreruperi. El citete fiierul CONFIG.SYS, execut comenzile din acest fiier i transfer controlul la COMMAND.COM, care proceseaz fiierul AUTOEXEC.BAT, afieaz promptul i monitorizeaz tastatura pentru intrare. n acest, moment memoria convenional, pn la 640K (A0000H), este alocat ca n figura urmtoare. Zona de memorie de la A0000H pn la FFFF0H (1 Mo) este memoria superioar (upper), iar ultimii 64K de memorie (de la FFFF0H la FFFFFH) poart numele HM A (High Memory Area). Memoria situat dincolo de HMA poart numele de memorie extins. nregistrarea de iniializare are dimensiunea standard a unui sector (512 octei). Pentru a simplifica programul de iniializare, cele dou fiiere (de sistem) sunt plasate la locaii predefinite pe disc (pentru a evita cutarea locaiilor acestuia). Acesta este motivul pentru care o dischet sistem este diferit de o dischet obinuit. Operaia de ncrcare a sistemului de operare se ncheie cu lansarea n execuie a programului COMMAND.COM, care este format din patru componente: F0000H C0000H B0000H A0000H ROM - zon sistem ROM BIOS Buffere video Buffere video

COMMAND.COM poriunea tranzient 640K (0FFFFH) (programele executate o pot terge). Zon disponibil pentru utilizare.

COMMAND.COM poriunea rezident Fiierele de sistem: IO.SYS, MSDOS.SYS 00500H Zon comunicaie DOS 00400H Zona de date BIOS 00000H Tabela vectorilor de ntrerupere

o component rezident, care trateaz ntreruperile 22H (terminare program), 23H (tratare

CTRL/BREAK), 24H (tratare erori critice scriere/citire pe disc), 27H (TSR programe rezidente) i partea necesar pentru ncrcarea componentei de tranziie; la terminarea unui program se calculeaz o sum de control, pe baza creia se verific dac zona de tranziie a fost modificat. Erorile DOS sunt tratate de aceast component. o component de iniializare a sistemului de operare, care verific existena unui fiier AUTOEXEC.BAT, care conine comenzi i care va fi executat; zona de memorie utilizat de aceast component este acoperit de primul program ncrcat de COMMAND.COM. Fiierele batch (cu extensia .bat) conin comenzi, ca i cum acestea ar fi introduse de la tastatur. Aceste fiiere pot fi incluse, dar dac un fiier apeleaz un altul, la terminarea execuiei celui de-al doilea nu se revine la primul, deci ele nu pot fi imbricate, ci doar nlnuite. Pentru aceasta, COMMAND.COM memoreaz locul de revenire ntr-un fiier de procesare batch, astfel nct atunci cnd o comand se termin, fiierul s poat fi citit pentru execuia comenzii ulterioare. Deoarece nici una dintre rutinele de iniializare nu este necesar ulterior, primul program ncrcat de pe disc se suprapune peste aceast poriune. o component tranzitorie, ncrcat la sfritul memoriei, care conine comenzile interne (DIR, COPY, DATA etc.) i interpretorul de comenzi. Acest program ar trebui, pe de o parte, s fie permanent n memorie pentru a interpreta comenzile, iar pe de alt parte s nu fie tot timpul n memorie, ntruct ar ocupa un spaiu de memorie pe care am dori s-l alocm altor programe. Soluia aleas a fost de a permite scrierea n aceast zon a altor programe. n momentul utilizrii interpretorului de comenzi, poriunea rezident din COMMAND.COM verific, mai nti, dac interpretorul de comenzi se afl n memorie, nealterat. Dac nu, el este rencrcat. Verificarea prezenei nealterate a acestei componente se face prin calcularea unei sume de control a locaiilor unde se presupune a se afla partea rezident, iar dac suma de control nu coincide cu valoarea scontat, se rencarc fiierul COMMAND.COM. o component care afieaz promptul, citete comenzile de la tastatur sau din fiierul de comenzi i conine ncrctorul pentru programele utilizator (.COM, .EXE). La sfritul execuiei oricrui program, se verific dac partea tranzitorie din COMMAND.COM, cea care interpreteaz liniile de comand, mai este rezident n memorie; n caz contrar, se rencarc. Accesul utilizatorului la programele coninute n BIOS se va realiza prin ntreruperi soft. ncrctorul de programe La ncrcarea unui program .EXE n memorie pentru execuie, ncrctorul realizeaz urmtorii pai: 1. acceseaz programul .EXE de pe disc; 2. construiete un prefix segment program (PSP) de 256 octei (100H) n memoria disponibil, aliniat la un paragraf, dup ce a iniializat blocurile de memorie pentru contextul programului i pentru segmentul programului; PSP-ul va fi creat de la adresa relativ 00H n segmentul programului i va ncrca programul de la adresa 100H; 3. memoreaz programul imediat dup PSP; 4. ncarc adresa PSP n registrele DS i ES (din acest motiv, programele trebuie s le iniializeze dac le utilizeaz); 5. ncarc adresa segmentului de cod n CS i pune IP la offsetul primei instruciuni din segmentul de cod; 6. ncarc adresa stivei n SS i pune SP la dimensiunea stivei; 7. transfer controlul programului pentru execuie, ncepnd cu prima instruciune din segmentul de cod.

n mod asemntor se ncarc pentru execuie i un program de tip .COM, cu deosebirea c toate registrele segment sunt iniializate cu aceeai adres (PSP), ntruct ntreg programul, inclusiv datele i stiva, sunt coninute n acelai segment. Diferena major dintre ele este c editorul de legturi insereaz o nregistrare antet special pentru un fiier de tip .EXE, cnd este memorat pe disc, iar programul de ncrcare utilizeaz aceast nregistrare pentru ncrcare. Interfaa I/O Cnd un program utilizator solicit un serviciu I/O ctre sistemul de operare, se transfer cererea la BIOS, care realizeaz accesul. Unele servicii pot fi solicitate direct BIOS-ului, n special cele pentru tastatur i ecran. O sarcin a DOS-ului este s interfaeze cu BIOS-ul cnd este necesar accesul la facilitile sale. Interfaarea programelor utilizator cu dispozitivele sau hardul sistemului se realizeaz aa cum se poate observa n figura alturat:

Program utilizator DOS BIOS Dispozitive / Hardware

Utilizarea funciilor BIOS n timp ce BIOS-ul manipuleaz ntreruperile INT 00H 1FH, DOS-ul manipuleaz ntreruperile INT 20H 3FH. Principalele puncte de intrare ale BIOS-ului ce pot fi folosite de utilizator sunt urmtoarele: INT 00H = este de fapt o excepie de mprire prin zero, pentru care se afieaz un mesaj corespunztor; INT 01H = Single Step, este utilizat de programele de depanare (Debug, TD); INT 02H = ntrerupere nemascabil (NMI) care este utilizat de erori hardware severe, cum ar fi eroarea de paritate la memorie; INT 03H = este ntreruperea de breakpoint, adic cea utilizat de programele de depanare, ntruct ocup un singur octet i poate substitui uor primul octet al instruciunii unde se stabilete punctul de suspendare a execuiei programului (este descris n seciunea dedicat ntreruperilor); INT 04H = ntreruperea de depire a rezultatului operaiilor aritmetice (INTO); INT 05H = ntreruperea imprim memoria video; aceeai operaie poate fi activat extern (nu intern, cum o face instruciunea INT 05H) prin combinaia de taste CTRL+PrtSc; la adresa 50:00H din zona de date BIOS se poate citi starea acestei operaii; INT 08H = ceasul de timp real; o ntrerupere hard actualizeaz ora i data sistemului (un circuit de ceas programabil genereaz o ntrerupere la fiecare 54,9256 ms, adic de 18,2 ori pe secund); INT 09H = ntrerupere dedicat tastaturii, generat la apsarea i eliberarea unei taste; INT 0BH, INT 0CH = controleaz dispozitivele seriale, adic porturile COM1 i COM2; INT 0DH, INT 0FH = controleaz dispozitivele paralele, adic porturile LPT1 i LPT2; INT 0EH = controleaz operarea dischetei; INT 10H = utilizare terminal grafic; INT 11H = determinare configuraie sistem i returneaz valoarea la locaia BIOS 40:10H, n AX; INT 12H = determinare dimensiune memorie RAM (returneaz n AX dimensiunea memoriei

de baz, exprimat n Ko); INT 13H = utilizare disc, adic operaiile de intrare/ieire, formatare etc. (numrul funciei solicitate se transmite n AH); INT 14H = utilizare interfa serial prin portul de comunicaie serial RS232; INT 15H = servicii de sistem determinate de valoarea transmis n AH, cum ar fi: - POST (power-on self-testing, AH=21H), adic testrile executate de sistem la pornire; - citire stare sistem (AH=43H); - suport joystick (AH=84H); - determinarea dimensiunii memoriei extinse (AH=88H); - comutare procesor n modul protejat (AH=89H); - interfaa cu mouse-ul (C2H). Dup aceast operaie trebui reactivate ntreruperile, ntruct revenirea se produce fr a le reactiva. INT 16H = utilizare tastatur; INT 17H = utilizare imprimant; INT 18H = intrare de baz n ROM; apelat de BIOS dac sistemul este pornit fr un disc care s conin programele sistemului de operare DOS; INT 19H = ncrctorul sistemului de operare de pe disc; dac este disponibil o dischet sistem, cu sistemul de operare DOS, va citi pista 0, sectorul 1 n locaia de ncrcare n memorie la adresa 7C00H i transfer controlul la aceast locaie; dac nu exist un disc sistem, se transfer controlul la punctul de intrare din ROM, via INT 18H; INT 1AH = utilizare ceas de timp real, adic se poate citi sau iniializa ora n funcie de codul transmis n AH; INT 1BH = permite controlul asupra tastei Break; cnd se tasteaz CTRL+Break, ROM BIOS transfer controlul la adresa sa de ntrerupere, unde este iniializat un indicator.

Utilizarea funciilor DOS


n timp ce BIOS-ul permite manipularea dispozitivelor la nivel cobort, DOS-ul furnizeaz o interfa de nivel ridicat pentru multe dispozitive. De exemplu, una dintre rutinele BIOS permite accesul la unitatea de dischet. Cu aceast rutin se pot citi sau scrie blocuri pe dischet. Din pcate, BIOS-ul nu cunoate mecanismele legate de fiiere i directoare, ci opereaz doar la nivel de blocuri (sectoare). Dac se dorete o operaie pe disc, utiliznd BIOS ul, trebuie tiut exact locul de pe disc (sectorul) unde se afl fiierul. Pe de alt parte, utiliznd DOS-ul se poate opera cu nume de fiiere, n locul adreselor de pe disc. DOS-ul pstreaz informaii asupra localizrii fiierului pe disc i apeleaz rutina ROM-BIOS pentru citirea/scrierea blocurilor respective. Interfaa de nivel ridicat reduce efortul programatorului necesar pentru accesul la date. Utilizarea funciilor DOS este, n general, mai uoar dect cea a funciilor BIOS echivalente, primele fiind mult mai independente de main. ntreruperile de la 20H pn la 3FH sunt rezervate pentru operaii DOS, dup cum urmeaz: INT 20H = terminare program; operaia termin execuia unui program .com, reface adresele pentru CTRL+Break i pentru erorile critice, golete bufferele i red controlul sistemului DOS. INT 21H = solicitare funcie DOS, al crei cod este transmis n AH i este descris n detaliu n

continuare. INT 22H = adresa de terminare. Se copiaz adresa acestei ntreruperi n PSP -ul programului (la offset 0AH) cnd programul ncrctor ncarc un program pentru execuie. La terminarea programului, operaia transfer controlul la adresa ntreruperii. INT 23H = adresa pentru CTRL+Break. Este destinat pentru transferul controlului la o rutin DOS (prin PSP, offset 0EH) cnd se tasteaz CTRL+Break sau CTRL+C. Rutina termin execuia unui program sau a unui fiier batch. Un program poate nlocui aceast adres cu aceea a unei rutine proprii, pentru a realiza aciuni specifice fr terminarea programului. INT 24H = manipulare erori critice. Este utilizat de sistem pentru a transfera controlul (prin PSP, offset 12H) cnd este recunoscut o eroare critic (de obicei la o operaie cu discul sau cu imprimanta). Aceste ultime trei ntreruperi, n mod normal, nu ar trebui s fie apelate de programul utilizator. INT 25H = citire absolut de pe disc a unuia sau mai multor sectoare (este nlocuit de INT 21H, funcia 440DH, codul minor 61H). INT 26H = scriere absolut pe disc, din memorie, a unuia sau mai multor sectoare (este nlocuit de INT 21H, funcia 440DH, codul minor 41H). INT 27H = programul se termin, dar rmne rezident. Determin ca un program .COM, dup terminare, s rmn rezident n memorie (nlocuit de INT 21H, funcia 31H). INT 2FH = ntrerupere multiplexare. Aceasta implic o comunicaie ntre programe, cum ar fi comunicarea strii unei imprimante, prezena unui driver de disc, sau comenzi sistem cum ar fi ASSIGN sau APPEND. INT 33H = manipulare mouse, deci furnizeaz serviciile pentru manipulare mouse. Vom prezenta cteva funcii DOS, INT 21H, mai des utilizate: Funcia 0 terminare execuie program: xor int ah, ah 21h

Funcia 1 citire caracter de la tastatur, cu ecou: mov int ah, 1 21h

; (AL) = codul ASCII al caracterului citit sau 0 daca este o ; tasta functionala, cum ar <Home>, <F1> sau <PgUp>

Funcia 2 afiare caracter: mov mov int dl, cod_ASCII_caracter ah, 2 21h

Funciile 3 i 4 intrare sau ieire la un port de comunicare: Cele dou funcii permit citirea (n AL), respectiv scrierea (din DL) a unui caracter la un port, dar este preferat operaia BIOS INT 14H.

Funcia 5 scrie caracter la LPT: mov mov int dl, caracter ah, 5 21h

Funcia 6 intrare/ieire direct la consol: Aceast funcie poate transfera orice caracter sau cod de control fr interferen cu DOS-ul. Sunt dou versiuni, una pentru intrare i alta pentru ieire. Pentru intrare se ncarc 0FFH n DL. Dac nu exist un caracter n bufferul tastaturii, operaia pune ZF=1 i nu ateapt intrarea. Dac exist un caracter, acesta este memorat n AL i ZF=0. Operaia este fr ecou i nu verific eventualele combinaii <Ctrl>+<Break> sau <Ctrl>+PrtSc. Dac AL este diferit de 0, este codul ASCII al unui caracter, dac ns este 0, atunci este o tast cu funcie extins (cum ar fi <Home>, <F1> sau <PgUp>) Pentru ieire, caracterul se ncarc n DL (ns nu 0FFh) mov dl, caracter ; sau 0FFh pentru iesire mov ah, 6 int 21h ; pentru iesire se testeaza ZF, dupa care se ia valoarea din AL, daca ZF=0. Funcia 7 citire de la tastatur, fr ecou i fr interpretare break (<Ctrl> + <Break>): mov int ah, 7 21h

; (AL) = codul ASCII al caracterului citit

Funcia 8 citire de la tastatur, fr ecou: mov int ah, 8 21h

; (AL) = codul ASCII al caracterului citit

Funcia 9 afiarea unui ir de caractere, ce se termin cu $: lea mov int dx, sir ah, 9 21h ; (DS:DX)=adresa de inceput a sirului de caractere

Funcia 0Ah citire ir de caractere: Aceast funcie accept date de la tastatur, dar necesit o list de parametri. Primul care trebuie cunoscut este numrul maxim de caractere (date) de intrare care nu mai poate fi introdus, valoare la apariia creia se anun sonor utilizatorul. Un al doilea parametru, actualizat de funcie, va conine numrul de caractere efectiv introduse. Lista de parametri const din urmtoarele elemente: 1. Prima intrare furnizeaz numele listei de parametri, n forma LABEL BYTE. 2. Primul octet din list conine limita maxim a numrului de caractere de intrare (ntre 0 i 255).

3. Al doilea octet este rezervat pentru memorarea numrului efectiv de caractere tastate. 4. n continuare, este rezervat memorie pentru memorarea caracterelor. n concluzie, o astfel de list poate fi definit astfel: param_list label dim_max dim_efectiv dat byte db db db

50 ; dimensiunea spatiului de memorie alocat ? ; numarul efectiv de caractere citite 50 dup (?); aici se depun caracterele

Apelul funciei se realizeaz astfel: lea dx, param_list mov ah, 0Ah int 21h

; (DS:DX) = adresa listei descrisa anterior

irul de caractere tastat se va termina cu tasta <Enter>, al crei cod nu este numrat, dar este transferat n zona de date. n cazul n care contorul numrului de caractere n momentul apsrii tastei <Enter> este mai mic dect limita numrului maxim de caractere, va fi depus n list ca al doilea octet (parametru). Dac se tasteaz mai multe caractere dect limita maxim stabilit, vor fi memorate doar primele caractere tastate care, alturi de codul tastei <Enter>, 0Dh, se ncadreaz n zona de memorie rezervat (deci mai puin cu unul dect numrul maxim de caractere specificat n lista de parametri). n acest capitol este prezentat un exemplu de utilizare a acestei funcii; programul citaftxt.asm citete un text de maximum 30 de caractere i l afieaz pe centrul ecranului, program care se execut ciclic pn la citirea unui text vid.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic


Programare n limbaj de asamblare

13. ntreruperi interne i externe.

ntreruperi externe
ntreruperile externe, care pot fi transmise de dispozitive externe, sunt primite de procesor pe dou linii: NMI i INTR. Linia INTR este controlat de PIC (Programmable Interrupt Controller), 8259A; rolul su este de a accepta cereri de ntrerupere de la dispozitivele externe, determin care cerere este cea mai prioritar i activeaz linia INTR, dac dispozitivul care a cerut ntreruperea este mai prioritar dect cel deservit n momentul respectiv. Cnd linia INTR devine activ, procesorul execut diferite aciuni, depinznd de starea indicatorului de validare a ntreruperilor (IF); oricum, nu se execut nici o aciune pn nu se termin execuia instruciunii curente, pe durata creia a aprut ntreruperea. Dac IF=0, deci ntreruperile mascabile sunt dezactivate, procesorul ignor semnalul INTR. ntreruperile se activeaz cu instruciunea STI (SeT Interrupt enable flag), deci IF=1, i se dezactiveaz cu instruciunea CLI (CLear Interrupt enable flag). Ele pot fi, de asemenea, mascate selectiv prin transmiterea de comenzi corespunztoare ctre PIC. Instruciunile de activare a ntreruperilor se vor lansa dup sfritul instruciunii urmtoare, pentru a nu ncrca excesiv stiva. ntreruperea este recunoscut prin executarea a dou cicluri de magistral de recunoatere ntrerupere (INTA\); pe durata acestor dou cicluri se activeaz semnalul LOCK\, pentru a indica altor procesoare c nu pot obine acces la magistral. Primul ciclu este utilizat de procesor pentru a semnaliza PIC c se onoreaz cererea, iar n timpul celui de-al doilea ciclu PIC rspunde plasnd un octet pe magistrala de date, care conine tipul ntreruperii (32 255), asociat cu servirea cererii de ntrerupere. Tipul este atribuit la iniializarea procesorului, prin program. Procesorul utilizeaz acest cod pentru a apela o procedur de tratare a ntreruperii. PIC poate accepta ntreruperi de la pn la opt dispozitive diferite. Numrul de dispozitive ce pot solicita ntreruperi poate fi extins pn la 64, prin utilizarea a 9 circuite de ntrerupere PIC, conectate n cascad astfel: opt dintre dispozitive la cele opt intrri ale unui PIC, iar fiecare ieire PIC devine o nou intrare pentru cel de-al noulea PIC. Un calculator obinuit utilizeaz dou circuite PIC pentru a furniza 15 intrri de ntreruperi (apte pe PIC master i nc opt de la PIC slave). O cerere extern de ntrerupere poate veni i pe linia NMI, care e comandat pe front (INTR e comandat pe nivel) i este utilizat pentru evenimente deosebite (cdere tensiune, restartare). ntreruperile nemascabile NMI nu pot fi dezactivate i au prioritate fa de cele mascabile INTR.

ntreruperi interne
ntreruperile interne sunt evenimente sincrone i reprezint rspunsuri ale procesorului la anumite evenimente detectate n timpul execuiei unei instruciuni. ntreruperile externe (mascabile i nemascabile) sunt evenimente asincrone. Deosebirea major ntre aceste dou tipuri de ntreruperi const n originea lor: o ntrerupere intern este ntotdeauna reproductibil prin reexecuia programului i a datelor ce au cauzat ntreruperea, n timp ce o ntrerupere extern este, n general, independent de execuia task-ului curent. ntreruperile interne sunt de dou tipuri. Un tip de ntrerupere este denumit excepie, deoarece ntreruperea apare numai dac exist o anumit condiie de eroare, care nu permite execuia corespunztoare a instruciunii; cellalt tip genereaz ntrerupere ori de cte ori instruciunea INT n este executat. Aceste instruciuni sunt utilizate fie pentru a testa rutinele utilizatorului de tratare a ntreruperilor externe, fie pentru a apela rutine DOS. Pentru apelul rutinelor DOS se utilizeaz acest mecanism

i nu mecanismul de apel de procedur din dou motive: fie nu se cunosc aceste adrese, fie ele se modific de la o versiune la alta. Exemple de excepii sunt: eroare de mprire, depire detectat de instruciunea INTO, depire limite detectat de instruciunea BOUND, depire segment (overrun), cod de operaie invalid, eroare de extensie procesor etc. n modul protejat sunt detectate mult mai multe condiii de eroare, care determin o ntrerupere intern. n acest mod, de adresare virtual, tabela de vectori de ntrerupere nu are adrese fizice fixe i deci nu poate fi adresat direct. De aceea programele care, n modul real de adresare, manipuleaz direct tabela de vectori de ntrerupere, nu vor lucra n modul protejat. ntreruperile interne au urmtoarele caracteristici: codul ntreruperii este coninut n instruciune sau este predefinit; nu se execut cicluri de recunoatere ntrerupere; nu pot fi dezactivate, cu excepia ntreruperii single step; sunt prioritare fa de cele externe.

ntreruperea Single Step


Aceast ntrerupere, de tipul 1, este generat n mod automat dup execuia fiecrei instruciuni, dac indicatorul TF a primit valoarea 1. Ea mai este denumit i excepie de depanare deoarece permite execuia unui program instruciune cu instruciune (adic pas cu pas). Procesorul salveaz registrul indicatori i adresa urmtoarei instruciuni de executat n stiv i pune indicatorii TF i IF pe zero, astfel ca, la intrarea n procedura de tratare a ntreruperii single step, procesorul nu mai este n modul pas cu pas; se evit astfel recursivitatea infinit. Procedura va permite vizualizarea programului ntrerupt (registre, indicatori, variabile memorie etc.); la sfritul procedurii se vor reface indicatorii din stiv, astfel c programul poate reveni n modul de execuie pas cu pas. Procesorul nu dispune de instruciuni directe pentru modificarea acestui indicator (TF); el poate fi modificat numai prin modificarea imaginii sale din stiv (utiliznd instruciunile PUSHF, POPF).

ntreruperea de breakpoint (suspendare)


Aceast instruciune, INT 3, este singura instruciune de ntrerupere care are lungimea de un octet (toate celelalte ocup cte doi octei, primul fiind codul instruciunii, iar cel de-al doilea tipul ntreruperii). Ea este folosit la implementarea de programe de depanare, deoarece necesit un singur octet de cod i poate substitui, foarte uor, orice octet de cod de instruciune. Ea permite, n acest mod, suspendarea programului i executarea rutinei de tratare a ntreruperii de pe acest nivel. Instruciunea permite, n plus, i inserarea de noi instruciuni n program, fr a fi recompilate sau reasamblate. Aceasta se poate face salvnd primul octet de instruciune i nlocuindu-l cu instruciunea INT 3. Procedura de tratare a ntreruperii de suspendare va conine noile instruciuni, plus codul pentru refacerea octetului de instruciune salvat (nlocuit anterior de INT 3) i s decrementeze adresa de revenire, salvat n stiv (mai exact IP) nainte de revenire, astfel ca instruciunea nlocuit sa fie executat dup instruciunile inserate. Metoda aceasta de depanare a unui program este mai complicat dect utilizarea registrelor de depanare, deoarece necesit crearea unui alias pentru segmentul de cod, salvarea octetului instruciunii originale, nlocuirea lui cu INT 3 i refacerea octetului la terminarea ntreruperii.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

14. Tabela vectorilor de ntrerupere.

Tabela vectorilor de ntrerupere Aceast tabel reprezint legtura dintre codul ntreruperii i procedura definit pentru a servi ntreruperea asociat cu acel cod. Civa din vectorii cei mai prioritari sunt rezervai de INTEL pentru funcii dedicate. Utilizatorul nu poate folosi nici unul din primii 32 de vectori. n modul real, aceast tabel ocup 1 Ko de memorie (pentru fiecare tip de ntrerupere din cele 256 posibile este rezervat un pointer, adic un dublu cuvnt), care conine adresa procedurilor de tratare a ntreruperilor. Adresa este memorat astfel: cuvntul cel mai semnificativ conine adresa de baz a segmentului, iar cuvntul mai puin semnificativ conine offsetul, acestea fiind memorate la adrese succesive n ordinea urmtoare: cuvntul mai puin semnificativ (offsetul) i apoi cuvntul mai semnificativ (selectorul de segment). n tabel sunt prezentai vectorii de ntrerupere pentru modul real. Excepia de eroare la mprire (nivel 0) apare n cazul n care ctul este prea mare (mai mare dect destinaia) sau dac se ncearc mprirea la zero, utiliznd o instruciune DIV sau IDIV. Se salveaz n stiv adresa instruciunii (CS:IP) care a generat eroarea; registrele DX i AX rmn nemodificate. ntreruperea single step (nivel 1) apare dup fiecare instruciune dac TF=1; evident c TF este pus pe 0 dup intrarea n aceast procedur pentru a preveni recursivitatea infinit. Valoarea salvat n stiv pentru CS:IP va face referire la urmtoarea instruciune. ntreruperea NMI (nivel 2), apare dac se primete un semnal extern pe pinul NMI; n mod normal, NMI este utilizat pentru a implementa proceduri de cdere de tensiune sau repornire. Valoarea salvat n stiv pentru CS:IP va face referire la primul octet al instruciunii ntrerupte. Dac NMI apare n timp ce se execut o servire curent NMI, prezena ei va fi salvat pentru o servire ulterioar, dup execuia primei instruciuni IRET. ntreruperea de suspendare (nivel 3) apare n urma execuiei acestei instruciuni, INT 3. Aceast instruciune este folosit pentru implementarea de programe de depanare, deoarece necesit un singur octet de cod, i poate substitui foarte uor orice prim octet de instruciune. Se va salva n stiv adresa urmtoarei instruciuni de executat. Excepia de depire detectat de instruciunea INTO (4) apare la execuia acestei instruciuni dac indicatorul OF=1; instruciunea va salva n stiv adresa urmtoarei instruciuni. Excepia de depire de domeniu detectat de instruciunea BOUND (5) este cauzat de execuia instruciunii BOUND dac indexul vectorului specificat este invalid n raport cu limitele date ale vectorului. Un program poate utiliza instruciunea BOUND pentru a verifica dac indexul cu semn al unui vector se ncadreaz n limitele definite ntr-un bloc de memorie. Valoarea salvat n stiv pentru CS:IP va face referire la primul octet al acestei instruciuni. Excepia generat de cod de operaie invalid (6) se genereaz dac se ncearc execuia unui cod de operaie invalid. Excepia este detectat numai la ncercarea de execuie a unui cod inexistent, nu i la citirea anticipat a acestui cod n coada de instruciuni. n modul real, majoritatea instruciunilor corespunztoare modului protejat sunt considerate invalide i nu trebuie utilizate. De asemenea, aceast excepie poate s apar dac adresa specificat de anumite instruciuni (LES, LDS, BOUND, LIDT) specific un registru n loc de o locaie de memorie. Aceast excepie poate s mai apar i dac au fost utilizate prefixe redundante n faa instruciunii, astfel nct lungimea total a instruciunii depete 8 octei, la 286, sau 16 octei la 386/486. n stiv se va salva adresa primului octet al instruciunii invalide.

Funcia excepie eroare mprire ntreruperea Single Step ntreruperea NMI ntreruperea de breakpoint excepie depire detectat de instr. INTO excepie depire domeniu detectat de instr. BOUND excepie cod instruciune invalid excepie extensie procesor nu este disponibil excepie limit tabela de ntreruperi prea mic excepie depire segment extensie procesor excepie depire segment excepie eroare extensie procesor ntreruperi rezervate

Numr ntrerupere 0 1 2 3 4 5 6 7 8 9 13 16

Instruciuni legate Returneaz de ntrerupere adresa instr. ce a generat excepia DIV, IDIV da toate toate INT 3 INTO nu BOUND orice cod nedefinit ESC sau WAIT LIDT ESC toate instr. cu referire la memorie ESC sau WAIT da da da da da da -

10-12, 14, 15, 17-31 ntreruperi definite de utilizator 32-255 Vectorii de ntrerupere rezervai i dedicai

Excepia pentru extensie procesor inexistent (7) poate s apar la execuia unei instruciuni ESC dac biii de stare din MSW arat c funciile extensiei procesor sunt emulate prin soft, sau la execuia instruciunilor ESC, WAIT, dac MP=1 i TS=1, adic n situaia n care a avut loc o comutare de task, pentru a verifica n ce msur contextul coprocesorului corespunde contextului curent. Se salveaz n stiv adresa primului octet al acelei instruciuni. Excepia pentru limita tabelei de ntreruperi prea mic (8) va aprea dac limita tabelei de ntreruperi a fost modificat de instruciunea LIDT de la valoarea 3FFH. Valoarea salvat pentru CS:IP va face referire la primul octet al instruciunii ce a cauzat ntreruperea, sau cea care era gata de execuie naintea apariiei unei ntreruperi externe. Excepia pentru depirea segmentului de ctre extensia procesor (9) va aprea dac un operand din memorie solicitat de extensia procesor (prin instruciunea ESC) nu ncape ntr-un segment; se va salva adresa instruciunii ce a cauzat ntreruperea. Excepia pentru depirea segmentului (13) apare dac un operand nu ncape ntr-un segment; se salveaz adresa instruciunii ce a cauzat ntreruperea. ntreruperea generat de eroare la extensia procesor (16) apare dup execuia unei instruciuni aritmetice care cauzeaz o eroare, semnalat pe linia ERROR\, care este testat la execuia instruciunilor ESC, WAIT. Ea poate s apar numai cnd se execut instruciunea WAIT sau ESC urmtoare celei care a generat eroarea. Valoarea salvat n stiv pentru CS:IP va face referire la primul octet al instruciunii ESC sau WAIT executat ulterior. Adresa

instruciunii numerice eronate este salvat n extensia procesor. Valoarea salvat n stiv pentru CS:IP va include i toate prefixele care preced instruciunea respectiv. n modul real nu se realizeaz verificri de limit sau de acces. Toate segmentele pot fi citite, scrise sau executate i au limita FFFFH. Segmentele incomplet utilizate se pot suprapune, dar n modul protejat de adresare virtual, programele care adreseaz un segment (B) dintr-un alt segment (A) devin incompatibile.

Segmentul B (64 K) suprapunere Segmentul A (64 K)

Baza segmentului B

Baza segmentului A

Accesarea unui segment din cadrul altui segment

ntreruperi n modul protejat


n modul protejat sunt detectate mult mai multe condiii de eroare care genereaz o ntrerupere intern. Programul utilizat pentru servirea ntreruperii poate fi executat n contextul task-ului care a generat ntreruperea, sau poate fi un task separat; alegerea depinde de funcia de realizat i de nivelul de izolare dorit. Pentru acest mod este definit o tabel de descriptori de ntrerupere IDT (Interrupt Descriptor Table), care definete procedurile pentru toate cele 256 de ntreruperi. Aceast tabel este referit de un registru intern al procesorului IDTR Interrupt Descriptor Table Register care conine adresa de baz a tabelei (24 bii) i limita acesteia (16 bii). Registrul IDTR este ncrcat de instruciunea LIDT, de codul executat pe nivelul 0 de privilegiu, de ctre rutina de iniializare a sistemului. Tabela poate fi plasat oriunde n memorie (figura urmtoare). Fiecare intrare n tabela IDT conine un descriptor de poart (gate), format din 4 cuvinte (8 octei), care conine referina la rutina respectiv. n tabela IDT sunt permise doar trei tipuri de pori: ntrerupere (interrupt gate), capcan (trap gate) i task (task gate). Primele dou prelucreaz ntreruperile n cadrul aceluiai task, n timp ce a treia realizeaz o comutare de task. Porile task din IDT sunt identice cu acelea din GDT (descriptorii sunt asemntori celor de sistem) i opereaz n acelai mod. Diferena dintre primele dou este c prima pune indicatorul IF pe zero

(dezactiveaz ntreruperile), n timp ce a doua las indicatorul nemodificat. IDT nu necesit toate cele 256 de intrri; registrul limit (16 bii) un numr de intrri mai redus dect numrul total. Intrrile neutilizate vor avea zero n octetul de drepturi de acces. Accesul n afara limitelor sau la un descriptor eronat va genera o eroare de protecie general (GP), cu un cod de identificare a erorii (a vectorului IDT invalid). ntreruperile 031 sunt rezervate de INTEL, astfel c limita IDT trebuie s fie cel puin 255, pentru numrul minim de intrri.

poarta pt. ntrerupere # n poarta pt. ntrerupere #n1 CPU 15 Limita IDT Baza IDT 23 0 Tabela de descriptori de ntrerupere (IDT) O poart task poate fi invocat de o ntrerupere/excepie; starea mainii se salveaz n TSSul curent i se ncarc o nou stare din TSS-ul asociat porii task. Astfel, o ntrerupere poate avea propriul su spaiu de adres (LDT). O comutare de task dureaz mai mult dect un transfer de poart, dar ofer avantajul separrii fa de task-ul curent. Descriptorul pentru aceste pori are forma din figur: 15
D

IDT

poarta pt. ntrerupere # 1 poarta pt. ntrerupere # 0

8 7 Offset 31 - 24
P L

S Type 0 Selector 15 - 0 Offset 15 - 0

Structura unui descriptor de port ntrerupere/capcan Caracteristicile porilor de ntrerupere/capcan sunt asemntoare celor de apel (call). Ele pot face referire la segmente de cod la anumite niveluri de privilegiu, sau conform regulilor de privilegiu; spre deosebire de porile de apel, acestea nu conin cmpul contor. Revenirea din ntrerupere se face cu instruciunea IRET, care reface registrul indicatori i segmentul de stiv. Dac NT a fost 1 (n registrul indicatori) se va realiza o comutare de task la TSS -ul original. La

apariia unei excepii de eroare se salveaz n stiv, dup indicatori i CS:EIP, i un cod de eroare (de un cuvnt). Programatorul trebuie s extrag orice cod de eroare (generat de poart i pus n stiv) din stiv, nainte de revenirea din procedura de ntrerupere. Unele excepii determin un transfer al controlului prin IDT; altele determin depunerea unui cod de eroare n stiv, cum ar fi: 8 (Double Fault), 10 (TSS invalid), 11 (NP), 12 (eroare stiv), 13 (GP), 14 (PG) i 17 (AC). Codul de eroare este 0 sau de urmtoarea form:

31 Nedefinit

16 15 32 1 Index Selector TI I
Codul de eroare returnat de excepii

0 EX

Indexul selectorului i TI sunt luai din selectorul segmentului asociat cu excepia. n locul cmpului RPL se afl codul de eroare, de 2 bii, cu urmtoarea semnificaie: dac I=1, selectorul face referire la un index din tabela IDT, iar bitul TI este ignorat; dac I=0, bitul TI indic dac selectorul este din GDT (TI=0) sau din LDT (TI=1); dac EX=1, eroarea a fost determinat de un eveniment din afara programului n execuie. Pe lng cele trei tipuri de pori, mecanismul de protecie mai suport i un al patrulea tip de poart, cea de apel (call gate). Porile de apel sunt invocate printr-o instruciune de apel de rutin standard. Ele sunt utilizate pentru a realiza comunicaia internivel, permind astfel unei aplicaii ce ruleaz pe nivelul de privilegiu 3 s poat apela serviciile sistemului de operare, care ruleaz pe nivelul 0, de protecie. Cnd se invoc o rutin printr-o poart de apel, nivelul de privilegiu al rutinei ce se execut se modific la nivelul segmentului de cod la care se refer poarta. Pentru a asigura integritatea datelor (parametrii i adresa de revenire) salvate n stiva nivelului mai puin privilegiat (care ar putea fi modificat de aplicaie), o parte a stivei este copiat, prin poart, ntrun segment de stiv mai privilegiat (al rutinei care se execut). Descriptorul unei pori de apel conine, pe lng adresa rutinei (selector i offset), un cmp (denumit contor) care indic numrul de cuvinte duble copiate din stiva mai puin privilegiat n cea mai privilegiat. Fiind patru niveluri de privilegiu, fiecare aplicaie trebuie s aib tot attea segmente de stiv. Pointerul pentru stiva activ, dintre cele patru posibile, se afl memorat n SS: (E)SP. Celelalte sunt memorate ntr-un obiect sistem, denumit segment de stare task (TSS Task State Segment). Cnd un apel sau ntrerupere, printr-o poart, determin o modificare n nivelul de privilegiu, noile valori pentru SS: (E)SP sunt ncrcate din TSS, din una din cele trei perechi disponibile : SS0: (E)SP0, SS1: (E)SP1, SS2: (E)SP2. Selectorul pentru TSS-ul curent este memorat ntr-un registru de task (TR). Cnd apare o comutare de task, toate registrele task-ului executat (generale i segment) sunt salvate n TSS-ul activ, apoi registru task (TR) este ncrcat cu selectorul noului TSS (al taskului care urmeaz s se execute) i fiecare registru (general/segment) este ncrcat cu valorile corespunztoare din noul TSS. Noul TSS conine i un cmp care face legtura cu task -ul anterior, astfel ca la terminarea sa s se poat comuta la task-ul anterior. ntruct modul virtual 8086 (V86) este parte a modului protejat, ntreruperile sunt manipulate prin IDT n modul protejat standard.

Excepii specifice modului protejat


ntreruperea de depanare (1) poate aprea la ndeplinirea uneia dintre condiiile: ntrerupere single step, breakpoint (suspendare) datorat unui registru de depanare (DR) sau la o comutare de task. La apariia unei ntreruperi de depanare, bitul RF (Resume Flag, din registrul indicatori) este setat (1), mascnd ntreruperile de depanare suplimentare. Dup execuia complet a unei instruciuni, procesorul terge bitul RF (0). Setarea bitului TF conduce la o ntrerupere single step, vectorul IDT(1), care pune TF pe 0. Un program de depanare nu poate executa single step o instruciune INT n, dar poate plasa un breakpoint fie la destinaia porii referite de INT n, fie imediat dup instruciunea INT. Un apel de poart nu terge TF, astfel c programul de depanare verific toate instruciunile JMP/CALL de tip FAR, pentru a vedea dac determin o modificare de privilegiu. Dac este aa, programatorii nu vor avea permisiunea la single-step ntr-un cod mai privilegiat dect aplicaia lor. ncepnd de la procesorul 386, exist i 8 registre de depanare (DR0-DR7), care pot memora 4 adrese de breakpoint (suspendarea execuiei programului curent la anumite adrese). Fiecare identific o adres liniar. Dac procesorul adreseaz acele adrese, se genereaz ntreruperea de depanare (1). Pentru a fixa puncte de ntrerupere, se utilizeaz instruciunea MOV DRx,reg (reg este un registru general de 32 de bii). Primele 4 registre (DR0-DR3) sunt registre de adres, n care se ncarc adresa liniar din descriptori. DR4 i DR5 sunt rezervate Intel. DR6 este un registru de stare, care indic condiiile ce determin ntreruperea; sunt cte 4 bii pentru fiecare dintre cele 4 registre de adres, specificnd care dintre ele a generat ntreruperea: BT, ntrerupere single-step, dac TF=1; BT, comutare de task; bitul T al noului task este pus pe 1; BD este pus pe 1 dac se utilizeaz hardware ICE (In-Circuit Emulator), adic registrele de depanare sunt rezervate pentru acest emulator (ICE). Dac BD=1, orice ncercare de a plasa o valoare n registrele de depanare va genera ntreruperea 1. Procedura de tratare a ntreruperii de depanare trebuie s tearg coninutul registrului DR6. Procesorul seteaz biii, dar biii pot fi teri numai prin program. DR7 este registrul de control depanare. Numai ncrcarea unei adrese n DR0-DR3 nu va activa o ntrerupere. Trebuie setai biii de activare din DR7 i pus condiia i lungimea breakpoint-ului: cmpul lungime specific, pe doi bii, tipul adresei: octet (orice adres), cuvnt (acoper cele dou adrese ale unui cuvnt), dublu cuvnt (acoper patru adrese); un alt cmp specific, pe doi bii, tipul accesului la memorie, al breakpoint-ului pentru cod (execuie program), scriere sau scriere/citire memorie. Mai exist biii Ln, Gn, care permit ca punctele de suspendare s fie locale sau globale. Astfel, dac Ln=1, o comutare de task terge biii Ln. Sistemul marcheaz bitul T din TSS-ul task-ului utiliznd breakpoint-uri locale, astfel c o ntrerupere pe nivel 1 apare cnd task-ul este reactivat; atunci biii Ln pot fi teri. ntruct exist doar 4 puncte de breakpoint (registre) active la un moment dat , este de preferat utilizarea registrelor de depanare pentru date i ntreruperea de breakpoint (INT 3) pentru instruciuni. Excepia Dubl Eroare (DF Double Fault (8)) apare cnd la o singur instruciune se detecteaz dou violri de protecie separate (de ex. o eroare de protecie pe nivelul trei este urmat de o eroare de segment not present (NP) datorit absenei segmentului) sau, cu alte cuvinte, la apariia a dou excepii succesive, ce nu pot fi serializate. Dac apar i alte violri de

protecie pe durata prelucrrii excepiei 8, atunci procesorul se blocheaz (shutdown), stare din care iese numai prin comand pe linia NMI, caz n care rmne n mod protejat, respectiv pe linia RESET, caz n care trece n modul real. La ncrcarea registrului SS ntreruperile hard i de depanare sunt mascate pe durata instruciunii urmtoare ncrcrii lui SS. Astfel, se poate ncrca registrul (E)SP fr riscul apariiei unei ntreruperi cu un pointer incorect la stiv. Poate s apar doar ntreruperea 14 (PG), care va invoca, eventual, o stiv incorect, conducnd la o dubl eroare (8). Pentru a evita acest lucru se pot ncrca ambele registre (SS i ESP) utiliznd o singur instruciune, LSS. Excepia datorat unui segment de stare task (TSS) invalid (10), care poate s apar dac pe durata unei comutri de task noul TSS referit de poarta task este invalid: de exemplu, stiva definit este un segment n care nu se poate scrie sau selectoarele de segment sunt n afara limitelor. Excepia Not Present (NP), pe nivelul 11, apare la ncercarea de a ncrca un segment care nu e prezent, sau la utilizarea unui descriptor de segment care este marcat not -present. Aceast eroare permite repornirea programului, adic dac rutina excepiei face segmentul prezent i returneaz controlul, programul ntrerupt i va relua execuia. Excepia eroare de stiv (12) apare la depirea superioar sau inferioar a stivei de ctre instruciunile ce lucreaz cu stiva (POP, PUSH, ENTER, LEAVE) sau n urma ncercrii de a ncrca registrul SS cu un descriptor care este marcat not-present n timpul unei tranziii inter-task sau inter-nivel. O instruciune ce determin aceast eroare este restartabil. Eroarea de protecie general (GP-General Protection), pe nivelul 13, apare n urma unei violri de protecie (transferul controlului la un segment care nu este executabil, scrierea ntr-un segment de cod), care nu este acoperit de celelalte ntreruperi (violri limit, scriere n segmente de tip read-only), referire la un segment de date cu nivel de privilegiu mai mare dect cel curent, sau ncrcri ale registrelor segment (SS, DS, ES, FS, GS) cu descriptori de sistem, cu segmente executabile sau care nu pot fi citite; n cazul acestei excepii se returneaz, pe lng adresa instruciunii respective, i un cod de eroare. La 386/486 mai pot s apar ntreruperile 14 i 17. ntreruperea 14 (PG-Page Fault), eroare de pagin, apare cnd adresarea paginat este activat i procesorul detecteaz, la translaia adresei liniare n adres fizic, o eroare: fie tabelele de pagin nu sunt prezente (bitul P=0), fie procedura curent nu are drepturi de privilegiu la pagina respectiv. ntreruperea 17 (AC-Alignment Check), eroare de aliniere, apare n cazul unei referine la un operand din memorie care nu este aliniat, n cazul procesorului 486. Aceast eroare este activat de bitul 18 (AC) din registrul indicatori. Un astfel de acces se realizeaz dac se face acces la un cuvnt de 16 bii memorat la o adres impar sau la un dublu cuvnt, de 32 bii, care se gsete la o adres ce nu este multiplu de 4, sau la o dat de 64 bii (de ex. un real de tip double) a crei adres nu este divizibil cu 8. Aceste transferuri sunt denumite transferuri nealiniate. Alinierea operandului i dimensiunea sa determin numrul de cicluri de magistral necesare pentru transfer. Dac datele sunt aliniate, ele pot fi transferate pe durata minim, adic un ciclu de magistral, altfel fiind necesar un ciclu suplimentar pentru a finaliza transferul. Aceste erori de nealiniere sunt generate de programe ce ruleaz pe nivelul 3 de privilegiu. Bitul AC este ignorat la nivelurile superioare de privilegiu (0, 1, 2). Referinele la TSS se gsesc implicit pe nivelul 0, chiar dac instruciunea care face referina este executat pe nivelul 3.

Toate aceste excepii sunt clasificate n urmtoarele tipuri: eroare, capcan i abandon (abort), n funcie de modul n care sunt semnalate i dac se poate restarta instruciunea care a determinat excepia. n prima categorie de excepii de eroare intr excepiile care sunt semnalate nainte de instruciunea ce determin excepia. Ele sunt detectate fie nainte s nceap execuia instruciunii, fie pe durata execuiei; eroarea este semnalat printr-o stare ce permite ca instruciunea s fie restartat, prin salvarea adresei instruciunii ce a determinat excepia. De exemplu, o astfel de excepie se genereaz cnd operandul unei instruciuni se afl ntr-un segment marcat ca non-prezent. Un numr special de ntrerupere este asociat cu fiecare condiie de eroare. Pointerul salvat n stiv dup o astfel de excepie face referire la instruciunea ce a cauzat-o, astfel c sistemul de operare poate corecta eroarea i relua execuia instruciunii. Astfel de excepii sunt: 0, 5, 6, 7, 10, 11, 12, 16. Cea de-a doua categorie, excepii capcan, este semnalat la execuia instruciunii imediat urmtoare celei care a determinat excepia; n acest caz, adresa salvat face referire la instruciunea urmtoare celei ce a generat excepia. De exemplu instruciunea INTO. La execuia ei, procesorul verific starea indicatorului OF; dac OF=1 se genereaz ntrerupere (INT 4). Toate ntreruperile soft (INT n) sunt de acest tip. Pentru a executa o astfel de instruciune trebuie s existe un privilegiu de acces la descriptorul IDT pentru numrul ntreruperii. De exemplu, dac o aplicaie pe nivelul 3 de privilegiu execut instruciunea INT 47, descriptorul la IDT(47) trebuie s aib DPL=3, altfel apare o eroare de protecie. Acest mecanism mpiedic aplicaiile de a executa instruciunile INT n, asociate cu ntreruperi hard, deoarece porile pentru aceti vectori fac referire la codul sistemului de operare, care ruleaz la nivelul cel mai privilegiat (0). Ultima categorie de excepii, abandon (abort), cuprinde acele excepii care nu permit localizarea precis a instruciunii i a contextului ce le-au generat, i deci nu permite restartarea programului (8, 9, 13). Tot n aceast categorie intr i erorile severe, hardware, sau detectarea unor valori ilegale n tabelele de sistem. ntreruperile din intervalul 32-255 sunt disponibile pentru utilizare de ctre sistemul de operare. n acest spaiu se pot instala pori de ntrerupere/capcan/task. Procedurile de ntrerupere pot fi invocate prin soft (INT n) sau prin semnale hardware (pe linia INTR).

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

15. Proceduri de tratare a ntreruperilor.

Proceduri de tratare a ntreruperilor


Rspunsul procesorului la apariia unei ntreruperi este prezentat n figura urmtoare. Procesorul servete ntreruperile numai ntre sfritul unei instruciuni i nceputul instruciunii urmtoare. Dac se utilizeaz un prefix de repetare a unei instruciuni pe iruri, ntreruperile i excepiile pot aprea ntre repetri. Cnd o procedur de tratare a ntreruperii este executat, indicatorii i registrele CS i IP sunt puse n stiv, iar TF i IF sunt teri. Procedura poate reactiva semnalele de ntrerupere externe cu instruciunea STI, permind astfel s fie ntrerupt de o cerere pe linia INTR mai prioritar dect cererea servit n momentul respectiv. Procedura de ntrerupere poate fi totui ntrerupt de o cerere NMI, chiar dac sistemul de ntreruperi nu este activat. Ca orice alt procedur, i procedurile de tratare a ntreruperilor trebuie s sal veze registrele nainte de a le actualiza i s le refac nainte de terminare. De obicei, pe durata seciunilor critice, adic de salvare i refacere a strii programului ntrerupt, ntreruperile sunt dezactivate, urmnd a fi reactivate dup aceste seciuni. Dac ntreruperile sunt dezactivate un timp prea ndelungat ntr-o procedur, cererile de ntrerupere pe linia INTR pot fi pierdute. Procedura de tratare a ntreruperii se termin cu instruciunea IRET (Interrupt RETurn); se presupune c stiva este adus n aceleai condiii ca la apelul procedurii. Procedurile de ntrerupere soft pot fi avantajoase n sisteme care realoc dinamic programe n timpul execuiei. De exemplu, n cea de-a doua figur se arat cum sunt prelucrate ntreruperi simultane (eroare la mprire, ntreruperea single step este activ i pe durata execuiei instruciunii de mprire apare o cerere de ntrerupere pe linia INTR).

instruciune curent complet ntr. da intern nu NMI nu INTR nu TF 0 execut instruciunea urmtoare NMI 1 temp = IF clear TF, IF Push CS, IP da 0 Push Indic. IF 1 recunoatere ntrerupere citete cod ntrerupere da

temp

Exec. Proc. ntrerupere Pop CS, IP Pop Indic. Reia Proc. ntrerupt Rspunsul procesorului la apariia unei ntreruperi

TF=1, IF=1 instruciune mprire INTR eroare mprire Push Ind., CS, IP Clear TF, IF ntrerupere Single Step Push Ind., CS, IP Clear TF, IF Procedura eroare mprire Pop Ind. Pop CS, IP instruciune mprire recunoatere INTR Push Ind., CS, IP Clear TF, IF ntrerupere Single Step Push Ind., CS, IP Clear TF, IF Procedura ntrerupere INTR Pop Ind. Pop CS, IP execut urmtoarea instruciune TF=1, IF=1 Procedura Single Step Pop Ind. Pop CS, IP TF=0, IF=0 TF=1, IF=1 Procedura Single Step Pop Ind. Pop CS, IP TF=0, IF=0

Prelucrarea ntreruperilor simultane

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

16. Formatul instruciunilor (codificare, moduri de adresare).

Formatul instruciunilor
Instruciunile procesorului 80286 au o lungime variabil i pot include 1 6 octei. Formatul general al unei instruciuni este urmtorul: 7 2 1 0 7 6 543 210 7 CodOp d w mod reg r / m 07 Deplas ament 07 07 Deplas ament 0

7 Cod

07 Operaie

07 6 543 210 7 mod reg r / m

07 Deplas ament

Formatul instruciunii la 286 Codificarea instruciunilor n figura anterioar sunt prezentate dou tipuri de format corespunztoare cazurilor n care codul operaiei este reprezentat pe un octet pentru primul format, respectiv pe doi octei pentru cel de-al doilea format. Semnificaia biilor este urmtoarea: d direction specific direcia rezultatului operaiei, i anume: d = 0, r/m r/m [Op] reg (registru) d = 1, reg reg [Op] r/m (registru sau memorie). w word bit indic tipul operanzilor, astfel: w = 0, operand de tip octet; w = 1, operand de tip cuvnt (doi octei); la 386/486, aceast valoare nseamn operand de dimensiune complet (16/32 de bii n funcie de modul de lucru). n ceea ce privete cmpul mod, acesta reprezint o codificare a modului de calcul al adresei efective sau lungimea deplasamentului i este utilizat pentru a determina adresa efectiv mpreun cu cmpul r/m. Dac mod = 11, cmpul r/m este tratat ca un cmp registru. n acest caz, precum i pentru cmpul reg, adresele utilizate pentru referirea (codificarea) registrelor sunt prezentate n tabel: Registru Adresa 000 001 010 011 100 101 110 111 Cuvnt W=1 AX CX DX BX SP BP SI DI Octet W=0 AL CL DL BL AH CH DH BH

Celelalte valori ale cmpului mod precizeaz prezena cmpului deplasament n instruciune i dimensiunea acestuia: MOD Semnificaie 00 Cmpul deplasament nu este prezent. Cmpul r/m specific un mod de adresare indirect prin registre, sau un mod de adresare bazat/ indexat, mai puin pentru r/m=110, care denot adresare direct, cu deplasament. 01 Cmpul deplasament are 8 bii (low). Cmpul r/m specific un mod de adresare indexat sau un mod de adresare bazat/ indexat, cu deplasament. 10 Cmpul deplasament are dimensiune complet, adic are 16 bii, n modul de lucru pe 16 bii, i respectiv 32 bii, n modul pe 32 bii; deplasamentul este cu semn i urmeaz dup cmpul r/m. Cmpul r/m specific un mod de adresare indexat sau un mod de adresare bazat/ indexat, cu deplasament. 11 Cmpul r/m specific un registru, i utilizeaz aceeai codificare cu cmpul reg. Cmpul r/m conine fie adresa unui registru, care conine operandul dac mod = 11, fie o codificare care este utilizat pentru calculul adresei efective a operandului, astfel: r/m Adresa efectiv Adresa efectiv (386/486) 000 [BX] + [SI] + deplasament [EAX] + scala*index + depl 001 [BX] + [DI] + deplasament [ECX] + scala*index + depl 010 [BP] + [SI] + deplasament [EDX] + scala*index + depl 011 [BP] + [DI] + deplasament [EBX] + scala*index + depl 100 [SI] + deplasament [ESP] + scala*index + depl 101 [DI] + deplasament [EBP] + scala*index + depl 110 [BP] + deplasament [ESI] + scala*index + depl 111 [BX]+ deplasament [EDI] + scala*index + depl Codificarea modului de adresare Exist i o excepie de la modurile de adresare din tabel, i anume: dac mod=00, adresa efectiv nu se calculeaz utiliznd registrul BP, ci doar un deplasament (care este prezent n acest caz) de 16, respectiv 32 de bii (pentru operarea pe 16 bii, pentru r/m=110, AE= deplasament de 16 bii, iar pentru operarea pe 32 de bii, pentru r/m=101, AE= deplasament de 32 de bii). Majoritatea instruciunilor cu doi operanzi permit fie ca memoria sau un registru s fie un operand, fie un registru sau o constant, coninut n instruciune, s fie utilizat ca al doilea operand. Operaiile cu ambii operanzi n memorie sunt excluse (cu excepia operaiilor pe iruri i a operaiilor cu stiva). Operanzii din memorie pot fi adresai direct, cu un offset (deplasament) de adres de 16 bii, sau indirect, cu un registru de baz (BP sau BX) i/sau registre index (SI sau DI) i, eventual, adunate cu o constant de deplasament, de 8 sau 16 bii. Toate operaiile cu doi operanzi, cu excepia nmulirii, mpririi i a operaiilor cu iruri, permit ca operandul surs s apar n instruciune ca dat imediat. Operanzii imediai de 16 bii,

avnd octetul mai semnificativ extensia bitului de semn a octetului mai puin semnificativ, pot fi abreviai la 8 bii. Operanzii imediai de 16 bii sunt memorai, dup constantele de deplasament, n ordinea obinuit pentru date: primul este octetul mai puin semnificativ, iar cel de-al doilea este octetul mai semnificativ. Unitatea de execuie (EU) are acces la operanzii imediai i registre; cnd are nevoie de un operand din memorie, transmite la AU offsetul acestuia i registrul segment, iar AU determina adresa fizic a operandului, n funcie de modul de adresare, pe care o transmite ctre BU. Exist, n principal, ase moduri de adresare: direct, adresa efectiv (AE) a operandului este reprezentat de deplasamentul coninut n instruciune; indirect, AE se afl ntr-unul din registrele de baz sau index; bazat, AE este suma dintre deplasament i coninutul unui registru de baz (BX sau BP); indexat, AE este suma dintre deplasament i coninutul unui registru index (SI sau DI); bazat i indexat, AE este suma dintre coninutul a dou registre: unul de baz i unul index; bazat i indexat cu deplasament, AE se obine ca suma a unui registru de baz, a unui registru index i un deplasament. Mai pot fi puse n eviden i urmtoarele moduri de adresare: imediat, operandul este coninut n instruciune; la registre, operandul se afl ntr-un registru. n afara acestor moduri de adresare de baz, mai exist i dou moduri de adresare speciale: adresarea irurilor; adresarea porturilor de I/O. Modul de calcul al adresei fizice a operandului este reprezentat schematic n figur.
simpl indexare BX sau BP sau SI sau DI BX sau BP dubl indexare SI sau DI

codificat n instruciune explicit n instruciune implicit, numai dac nu este specificat de prefix segment

+ +
Deplasament Registru Segment CS, DS, ES, SS Adresa de baz a segmentului din Descriptor

AU

+ BU

Adresa Fizic Generarea adresei fizice

n funcie de modul de lucru, real sau protejat, pentru determinarea adresei fizice se utilizeaz fie unul din registrele segment, fie adresa de baz dintr -un descriptor de segment. Pentru procesoarele 386/486, aceast adres este denumit adres liniar i, dac adresarea paginat nu este activ, atunci ea reprezint chiar adresa fizic. Dac adresarea paginat este activ, atunci unitatea de paginare o transform intr-o adres fizic; modul de obinere al adresei fizice pentru aceste procesoare este prezentat n figur. Adresa fizic determinat de AU din adresa logic se calculeaz din surse diferite, n funcie de tipul referinei:
Calcul Adresa Efectiv Index
Baza

Deplasament

Scala 1, 2, 4, 8

+
15 2 1 0 Selector RPL Reg. segment
32 AE Adresa Logic

Unitate

32 Adresa Liniar

Segmentare

Unitate Paginare

32 Adresa Fizic

Index Descriptor

Determinarea adresei fizice pentru 386/486 Tipul referinei la memorie Fetch instruciune Operaii cu stiva Variabile de memorie Operaii pe iruri - irul surs - irul destinaie BP utilizat ca registru de baz Adresa de baz a segmentului Implicit Alternativ CS SS DS CS , ES , SS DS ES SS CS , ES , SS CS , ES , SS

Offset IP SP Adresa Efectiv SI DI Adresa Efectiv

Registrele utilizate pentru calculul adresei fizice Pentru adresarea ntr-un alt segment dect cel implicit se va preceda instruciunea respectiv cu un prefix de segment (override) care va specifica, n mod explicit, registrul segment utilizat. Formatul instruciunilor la procesoarele 386/486 i Pentium este asemntor:

Cod operaie 12 octei

mod reg r/m SIB 01 octei 01 octei

Deplasament 0, 1, 2, 4 octei

Operand 0, 1, 2, 4 octei

n plus fa de formatul anterior, n instruciune poate fi prezent octetul SIB (ScaleIndex + Base), ce specific registrul index utilizat (care poate fi oricare dintre registrele EAX, EBX, ECX, EDX, EBP, ESI sau EDI, deci nu poate fi utilizat ca registru index ESP), factorul de scalare cu care se nmulete registrul index (care poate avea una din valorile 1, 2, 4, 8) i registrul de baz (oricare dintre registrele EAX,..., EDI) utilizat pentru calculul adresei efective. Dac n cazul procesorului 286 o instruciune nu poate fi precedat dect de prefixe de segment (care specific registrul segment utilizat pentru determinarea adresei fizice) sau prefixe instruciune (de repetare sau de blocare a accesului altui procesor la magistrala sa), instruciunile procesorului 386/486 pot fi precedate de urmtoarele prefixe (de cte un octet fiecare): Prefix instruciune Prefix segment Prefix dimensiune Prefix dimensiune adres operand

n cadrul octetului sau al celor doi octei de cod de operaie, pot fi definite cmpuri codificate mai mici, care difer n funcie de clasa operaiei. Aceste cmpuri definesc diverse informaii : direcia operaiei, dimensiunea deplasamentului, codificarea registrelor sau extensia de semn. Aproape toate instruciunile cu referire la un operand din memorie au un octet de mod de adresare, plasat dup primul octet de cod de operaie. Unele codificri ale acestui octet (mod, r/m) indic un al doilea octet de adresare, octetul scal-index-baz SIB. Octetul SIB conine, codificat, urmtoarele informaii: factorul de scal (ce poate fi 1, 2, 4 sau 8), pe primii doi bii; registrul index utilizat, pe urmtorii 3 bii (ca registre index pot fi utilizate 7 dintre cele 8 registre generale, mai puin registrul ESP); registrul de baz utilizat, pe ultimii 3 bii. Dac octetul SIB este prezent n instruciune, el specific doar indexul i factorul de scal (dup cum se poate vedea i n tabela 7.4). Cnd octetul SIB nu este prezent, cmpul registru de baz alturi de celelalte cmpuri din acest octet (SIB) este utilizat doar pentru r/m=100 (n cazurile mod=00, 01 i 10, adic pe poziia utilizrii registrului ESP pentru adresare, n locul utilizrii registrului ESP, cnd octetul SIB este, totui, prezent n instruciune), la operarea pe 32 de bii; pentru celelalte valori ale cmpului r/m, octetul SIB nu este prezent. Deplasamentul, dac este prezent n instruciune, poate fi de 8, 16 sau 32 de bii (n funcie de dimensiunea implicit a adresei). Mai exist un cmp de un bit, care permite extensia de semn a datelor de 8 bii la 16/32 bii, n funcie de tipul destinaiei. n cadrul instruciunilor de test sunt codificate i condiiile de test. Setul de instruciuni de la 386/486 este extins n dou direcii: pentru a permite date pe 32 bii; pentru a permite moduri de adresare pe 32 bii. Extensia aceasta se face n funcie de bitul D (Default) din descriptorul de segment de cod i prin utilizarea celor dou prefixe: dimensiune operand i dimensiune adres. Modul de operare implicit al instruciunilor, fie pe 16, fie pe 32 de bii, depinde de bitul D din descriptorul de segment de cod. Bitul D specific dimensiunea implicit (0 pentru 16 i 1 pentru 32 de bii) att pentru operanzi, ct i pentru adresa efectiv. Cele dou prefixe, pentru

dimensiune adrese i dimensiune operanzi, permit prefixarea i deci modificarea dimensiunii operandului i adresei peste selecia implicit (a bitului D). n modurile de lucru real i virtual 8086 (V86) nu se utilizeaz descriptori de segment, dar valoarea lui D (egal cu 0) este presupus intern de 386/486. Cele dou prefixe permit selectarea individual a bitului D. Aceste prefixe pot preceda orice cod de operaie i afecteaz numai instruciunea ce o preced. Utilizarea celor dou prefixe va determina dimensiunea operandului sau a adresei la valoarea opus fa de starea bitului D. De exemplu: dac dimensiunea operandului era de 32 de bii, prezena prefixului pentru dimensiune operand va determina operarea cu date de 16 bii, iar dac dimensiunea implicit a adresei efective este de 16 bii, prezena prefixului de dimensiune adres efectiv va determina calculul adresei efective pe 32 de bii. Extensiile la 32 de bii sunt posibile n toate modurile, inclusiv n modul real sau virtual 8086. n aceste moduri, implicit se lucreaz pe 16 bii, astfel c sunt necesare prefixe pentru a specifica adrese i operanzi de 32 de bii. Utilizarea modului extins de adresare (adic utilizarea registrelor extinse) va determina asamblorul s insereze prefixul, deci nu este nevoie de a specifica explicit instruciunea prefix. Bitul w are semnificaia, la 386/486, de operare pe 8 bii (dac este 0) sau pe 16/32 bii, adic dimensiunea complet a operandului (dac este 1). n ceea ce privete codificarea registrelor (cmpurile reg i respectiv r/m) la 386/486, aceasta se face n mod asemntor: cmpul w este prezent n instruciune: pentru operaiile pe 16 bii sunt aceleai adrese; pentru operaiile pe 32 bii, pentru w=0 la fel ca n tabel, iar dac w=1 atunci se adreseaz n aceeai ordine registrele EAX, EBX,... EDI; cmpul w nu este prezent n instruciune: pentru operaiile pe 16 bii se adreseaz cu aceleai adrese registrele AX, BX,..., DI; pentru operaiile pe 32 bii se vor adresa registrele de 32 bii EAX, EBX,..., EDI. Pentru selecia registrului segment se utilizeaz doi bii la 286, pentru selecia unuia din cele patru registre segment: CS, DS, ES, SS, respectiv 3 bii la 386/486, pentru a putea selecta i registrele de date suplimentare FS, GS. Codificarea modurilor de adresare la 486 este aceeai ca la 286, dac se lucreaz cu adrese de 16 bii, iar dac se utilizeaz adrese de 32 bii, atunci se pot utiliza ca registre de baz i index oricare dintre registrele EAX, EBX,..., EDI (cu excepia registrului ESP, care nu poate fi utilizat ca registru index). Calculul adresei efective se face n mod asemntor, cu deosebirea c pentru mod=10 deplasamentul este pe 32 bii (n loc de 16), iar dac se utilizeaz octetul SIB, atunci la calculul adresei efective se utilizeaz scala i registrul index indicat de acest octet (EAX,..., EDI), ca n tabela 7.4. Utilizarea componentelor de baz i index se face pentru referirea la: parametrii i variabilele locale din stiv ale unei proceduri; o structur, pentru mai multe apariii ale aceluiai tip de structur sau ntr-un vector de structuri; un vector cu una sau mai multe dimensiuni; un vector alocat dinamic.

Toate completrile aduse la procesoarele 386/486 sunt valabile i pentru procesoarele Pentium. 7.2. Moduri de adresare Adresarea direct nu implic nici un registru; adresa efectiv este specificat chiar n codul instruciunii, prin deplasament, ca n figur:
7 0 7 0 15 8 7 0

Cod Op.

mod r/m

Deplas ament

Memorie

AE + AE - Adresa Efectiv AS - Adresa de Segment AF - Adresa Fizic Adresarea direct Exemple de instruciuni: mov ax, adr_w mov adr_w[2], si ; adr_w adresa operand cuvant ; transfer la adresa adr_w + 2 AS AF Operand

Adresarea indirect prin registre face referire la memorie prin intermediul registrelor index sau de baz, care vor conine, n acest caz, adresa efectiv a operandului, ca n figur:
7 0 7 0

Cod Op.

mod r/m BX BP SI DI Memorie AE + AF Operand

AE - Adresa Efectiv AS - Adresa de Segment AF - Adresa Fizic

AS

Adresarea indirect, prin registre

Sintaxa instruciunilor n limbaj de asamblare utilizeaz pentru adresarea indirect operatorul index []. Exemple de instruciuni: mov ax, [bx] mov bx, [si] La procesorul 286, pentru adresarea indirect prin registre pot fi utilizate doar registrele index i de baz.
Adresarea bazat determin adresa efectiv adunnd coninutul unui registru de baz cu deplasamentul din instruciune, ca n figur:
7 0 7 0 15 8 7 0

Cod Op.

mod r/m BX BP

Deplas ament

Memorie AE + AF Operand

AE - Adresa Efectiv

AS

AS - Adresa de Segment AF - Adresa Fizic Adresarea bazat Dac se utilizeaz registrul BP ca registru de baz, atunci se pot obine operanzi din segmentul curent de stiv la care face referire SS (dac nu este prezent un alt prefix segment). n acest mod se poate face referire la datele din stiv fr a descrca stiva. Adresarea bazat furnizeaz, de asemenea, un mod convenabil pentru a adresa structuri de date similare, care pot fi memorate la adrese diferite de memorie. n acest caz, registrul de baz se va referi la baza structurii, iar elementele structurii vor fi adresate prin deplasamentul lor fa de baz. Aceleai cmpuri ale structurii pot fi accesibile prin simpla modificare a registrului de baz cu adresa de nceput a noii structuri. Prin modificarea doar a deplasamentului se poate face referire la alte cmpuri ale structurii (figura urmtoare). Exemple de instruciuni: mov ax, depl[bx] mov ax, [depl + bx] mov ax, [bx] + [depl]

Adresa Efectiv Deplasament + Registru de baz

Memorie vrsta sex ... ... departament funcie nume & prenume

Adresarea elementelor unei structuri


Adresarea indexat este asemntoare cu adresarea bazat, ntruct adresa efectiv se obine tot ca o sum ntre un registru, de aceast dat index SI sau DI, i deplasamentul din instruciune.
7 0 7 0 15 8 7 0

Cod Op.

mod r/m

Deplas ament Memorie SI DI + AE + AF Operand

AE - Adresa Efectiv AS - Adresa de Segment AF - Adresa Fizic

AS

Adresarea indexat Acest mod de adresare este utilizat pentru referirea la elementele unui vector. Deplasamentul va marca nceputul vectorului, iar registrul index va selecta elementul, prin poziia sa relativ n cadrul vectorului. Deoarece toate elementele vectorului sunt de aceeai lungime, prin operaii aritmetice elementare aplicate registrului index se va selecta orice element; din acest motiv, la procesoarele 386/486 se poate specifica un factor de scal (1,2,4,8) pentru index, n vederea referirii la vectori av nd componente de lungime fix, de 1, 2, 4, 8 octei.

Adresa Efectiv Registru Index + Deplasament

Memorie V (n) ... V . (2) .. V (1) V (0)

Adresarea elementelor unui vector


Adresarea bazat i indexat utilizeaz pentru calculul adresei efective dou registre, de baz i index, i un deplasament, ca n figur:
7 0 7 0 15 8 7 0

Cod Op.

mod r/m

Deplas ament Memorie BX BP SI DI + AE + AS AF Operand

AE - Adresa Efectiv AS - Adresa de Segment AF - Adresa Fizic

Adresarea bazat i indexat Este un mod flexibil de adresare, deoarece pot fi modificate dou componente. n acest mod pot fi adresate diferite structuri sau parametrii (de tip structurat) transmii prin stiv, respectiv variabilele locale unei proceduri, cum este prezentat n figura urmtoare. Registrul BP va conine deplasamentul unui punct de referin n stiv, de obicei vrful acesteia, dup ce procedura a salvat registrele, i aloc memorie local variabilelor procedurii. Offsetul unui vector din stiv, fa de nceputul stivei, poate fi exprimat prin valoarea deplasamentului, iar un registru index este utilizat pentru a adresa elementele individuale ale vectorului. n mod asemntor pot fi adresate i alte structuri (de exemplu matrice etc.). Exemple de instruciuni: mov ax, aw[bx][si]

mov

ax, depl[bp][di] Memorie adrese mici Registrul BP + Deplasament + Registru index + Adresa Efectiv adrese mari Adresarea unei structuri din stiv var_local_1 var_local_2 V (0) V (1) V (2) registre salvate Adresa de revenire parametru_2 parametru_1

n cazul adresrii elementelor unui vector, adresa (deplasamentul) unui element, de exemplu pentru un vector bidimensional, se obine astfel: adr_element = adr_baza + (index_linie*dimens_coloana + index_coloana)*dimens_element unde adr_element este adresa primului element din vector, v[0][0] , dimens_element este dimensiunea unui element din vector (n octei), dimens_linie este numrul de linii ale vectorului, iar index_coloan i index_linie reprezint indecii elementului curent adresat. Pentru un vector tridimensional, adresa unui element se va obine astfel: adr_elem=adr_baza+((index_1*dimens_2+index_2)*dimens_3+index_3)* dimens_element ceea ce ar corespunde, n pseudocod, unei secvene de forma: for index_1 = 1 to dimens_1 do for index_2 =1 to dimens_2 do for index_3 = 1 to dimens_3 do v[index_1][index_2][index_3]........ n mod asemntor, pentru un vector cu 4 elemente, adresa unui element va fi:

adr=baza+(((index_1*dim_2+index_2)*dim_3+index_3)*dim_4+index_4)*dim_element i n acest mod se poate generaliza pentru un vector de orice dimensiune, n.


Adresarea imediat presupune c operandul se afl chiar n instruciune octetul 3 sau octeii 3-4, dac operandul are 16 bii i dac nu avem deplasament, respectiv octeii 5 i respectiv 5 6, dac instruciunea are i deplasament.

Exemple de instruciuni: mov add mov

ax, 100h beta [bx][si], 0ce43h alfa [bp][di], 0f7h

De fapt, se poate realiza o combinaie ntre acest mod de adresare i celelalte moduri (bazat, indexat, bazat i indexat), dup cum se poate vedea i din ultimele exemple.
7 0 7 0 15 8 7 0 15 8 7 0

Cod Op.

mod r/m

Deplas ament

Oper and

AE Adresarea imediat
Adresarea la registre

n acest caz, adresa efectiv a operandului este adresa unui registru general, adic operandul se gsete ntr-un registru.
7 0 7 0

Cod Operaie

mod reg r /m

Adresarea la registre Exemple de instruciuni: mov ax, si; mov ah, cl; mov ds, bx
Adresarea irurilor

Instruciunile pe iruri nu utilizeaz modurile normale de adresare a memoriei pentru a adresa operanzii irurilor. Se utilizeaz, n mod implicit, registrele index pentru a determ ina adresa efectiv, iar pentru a determina adresa de segment se utilizeaz registrele segment ES

pentru irul destinaie, respectiv DS pentru irul surs (dac nu este prefixat un alt registru segment pentru surs). Dac operaia pe ir se execut n mod repetat, atunci registrele index sunt ajustate automat pentru a face referire la elementul urmtor din ir. Exemple de instruciuni: movs sir_dest, sir_sursa movsb cmpsw

0 Cod Operaie
15 0

SI
15 0

AE surs

DI

AE destinaie

Adresarea irurilor
Adresarea porturilor de intrare/ieire (I/O)

Pentru a adresa porturile din spaiul de I/O se pot utiliza dou moduri: adresarea direct a porturilor, care presupune c adresa portului de I/O se gsete n instruciune, pe 8 bii, i deci pot fi adresate porturile din spaiul de adrese 0-255. Exemple de instruciuni: in al, port_octet; citire de port de tip octet in ax, port_cuvant; citire de la port cuvant out port_oct, al; scriere la port octet out port_cuv, ax; scriere la port cuvant
7 0 7 0

Cod Operaie

Data
7 0 Adres port

Adresarea direct a porturilor de I/O adresarea indirect a porturilor de I/O, care se realizeaz n mod implicit prin registrul DX, care conine adresa efectiv a portului (instruciunea are un singur octet). n acest mod pot fi adresate toate porturile din spaiul de I/O: 0 65535. Exemple: in al, dx ; citire de la port octet

in out out
7

ax, dx ; citire de la port cuvant dx, al ; scriere la port octet dx, ax ; scriere la port cuvant
0

Cod Operaie
15

DX (implicit)
0

Adresa port Adresarea indirect a porturilor de I/O Trebuie menionat c pentru adresarea porturilor de I/O, deci a spaiului de I/O, nu se utilizeaz registrele segment. Adresa furnizat de instruciune este adresa efectiv a portului respectiv n spaiul de I/O, de 64 Ko.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

17. Limbajul de asamblare (definire constante, propoziii i instruciuni).

Limbajul de asamblare
Limbajul de asamblare se caracterizeaz prin: utilizarea simbolurilor i expresiilor simbolice pentru exprimarea codurilor operaiilor, a adreselor i a operanzilor; utilizarea unor comenzi simbolice pentru controlul procesului de asamblare i gestiunea resurselor calculatorului. Elementele constitutive ale limbajului de asamblare sunt: alfabetul; cuvintele formate cu acest alfabet; propoziii formate din aceste cuvinte i alfabet. Alfabetul const din: caracterele alfabetice: litere mici + litere mari; caractere numerice: 0 9; caractere speciale: + * / () [],. : ; @ $ _ ? ! etc. Cuvintele sunt formate dintr-o succesiune de caractere din alfabet, construite dup anumite reguli i care au o anumit semnificaie. Se mpart n dou categorii: identificatori i constante. Identificatorii sunt secvene de lungime 1 31 caractere alfanumerice i speciale: ? _ @ $. Nu este permis introducerea spaiilor libere ntr-un identificator. Un identificator trebuie s nceap cu o liter sau cu unul din caracterele speciale. Dac identificatorul ncepe cu punct (.), atunci are semnificaia de comand adresat asamblorului. Asamblorul nu deosebete literele mari de cele mici. Identificatorii sunt i ei de dou tipuri: standard sau predefinii i definii de utilizator. Identificatorii standard, sau cuvinte cheie, cum mai sunt denumii, se utilizeaz pentru denumirea unor funcii i argumente stabilite la definirea limbajului i fac parte din vocabularul limbajului. Astfel de identificatori sunt: nume de instruciuni: MOV, ADD, SUB, INT etc.; nume de resurse: AX, BX,..., CS, DS,..., AH, AL etc.; nume de operatori: MOD, OFFSET, SEG, PTR, TYPE etc.; pseudoinstruciuni pentru asamblor: ASSUME, MODEL etc. Identificatorii definii de utilizator vor fi folosii pentru: nume de variabile, adrese de instruciuni, operanzi; nume de proceduri, segmente, macroinstruciuni.

Definirea constantelor
Constantele pot fi numerice sau iruri de caractere formate pe baza anumitor reguli i crora li se asociaz o valoare. Constantele numerice pot fi ntregi, reale sau zecimale (codificate binar). Constantele ntregi reprezint numere ntregi ce pot fi utilizate n funcie de context pentru date, adrese sau operanzi imediai. Constantele pot fi reprezentate n binar, octal, zecimal sau hexazecimal; reprezentarea ntr-una din aceste baze se specific printr-una din literele B, Q, D sau H, care urmeaz dup constant: binar: 01101010B; octal: 152Q; zecimal: 106D sau 106; hexazecimal: 6aH. Pentru a evita confuzia ntre constantele hexazecimale i identificatori, ntotdeauna o constant hexazecimal trebuie s nceap cu o cifr (de ex.: 0abcdH, pentru a nu fi confundat cu identificatorul abcdH). Constantele zecimale pot fi urmate sau nu de litera D, deoarece se consider implicit baza 10. Exist o directiv de asamblare care permite stabilirea reprezentrii ntr-o baz implicit a constantelor: .RADIX < expresie > unde < expresie > trebuie s aib o valoare ntreag, n spe 2, 8, 10 sau 16, i este evaluat n zecimal. Iat, de exemplu, valorile care se ncarc n registrul AX dup utilizarea acestei directive (am folosit constante pentru expresia bazei): .RADIX 2 mov .RADIX 8 mov .RADIX 10 mov .RADIX 16 mov

AX,100 AX,100 AX,100 AX,100

; (AX) = 0004H ; (AX) = 0040H ; (AX) = 0064H ; (AX) = 0100H

Constantele ntregi pot fi reprezentate n memorie pe 8, 16, 32 sau 64 bii. Constantele reale sunt reprezentate n virgul mobil, prin mantis i exponent, n general sub forma: [] intreg. fractie [ E exponent ] Asamblorul codific aceste constante reale n reprezentarea cu virgul mobil pe 32, 64 sau 80 de bii, dup cum se specific tipul constantei: dd (define double word), 32 de bii, real simpl precizie; dq (define quadruple word), 64 de bii, real dubl precizie; dt (define ten bytes), 80 de bii, real temporar.

Codificarea n virgul mobil difer de la un asamblor la altul, de la un compilator la altul, dar formatul cel mai rspndit este (IEEE): Sm exponent mantis Sm semnul mantisei (1 bit); exponent este exponentul numrului deplasat cu o anumit valoare, n funcie de tipul reprezentrii: 7fH, pentru formatul pe 32 de bii; 3ffH, pentru formatul pe 64 de bii; 3fffH, pentru formatul pe 80 de bii. exponentul pentru cele trei formate se reprezint pe 8, 11 i respectiv 15 bii; mantisa este normalizat, adic : 1.00...0 <= mantisa <=1.11...1

i se reprezint, pentru cele trei formate, pe 23, 52 i respectiv 64 de bii; de remarcat c pentru primele dou formate nu se reprezint prima cifr, deci prima unitate din faa virgulei, care este presupus implicit, cu ajustarea corespunztoare a exponentului. Pentru cel de-al treilea format se reprezint i prima unitate, cea din faa virgulei (punctului zecimal). Exponentul, la reprezentarea intern, este deplasat, pentru a simplifica operaiile de comparare cu numere reale; n acest mod, procesorul lucreaz numai cu valori pozitive pentru exponent. De exemplu, pentru valori reale simpl precizie (32 de bii), exponentul este n intervalul [1, 254], n loc de [-127, +126], ct ar fi fost domeniul exponentului pentru o reprezentare cu semn. Exponentul minim (0) este utilizat doar pentru reprezentarea valorii 0.0 i pentru valori nenormalizate, iar cel maxim (255) este utilizat pentru a reprezenta o condiie de eroare (NaN Not a Number), cu alte cuvinte codificarea cu exponent 1111 nu reprezint o valoare numeric. Numerele negative difer de numerele pozitive numai prin bitul de semn al mantisei. S considerm, de exemplu, reprezentarea ctorva numere; am considerat, pentru simplitatea reprezentrii valori care se reprezint exact. Pentru o declaraie de forma a) dd 1.0 ; 20 deci Sm = 0; exponent = 0 + 7f (deplasarea); mantisa = 1.00...0; se obine urmtoarea reprezentare intern: Sm, exp, mant = 0, 01111111, 00...0 = 3F 80 00 00 H b) dd -1.0 ; -20 deci Sm, exp, mant = 1, 01111111, 00...0 = BF 80 00 00 H c) dd 4.0 ; 22

deci exponent = 2 + 7f = 81H; Sm, exp, mant = 0, 10000001, 00...0 = 40 80 00 00 H d) dd -0.625 ; 2-1 + 2-3 ; deci exponent = -1 + 7f = 7e; mantisa = 1.0100...0; Sm, exp, mant = 1, 01111110, 010...0 = BF 20 00 00 H Valorile se memoreaz n ordinea invers scrierii lor, adic la adresa cea mai mic octetul cel mai puin semnificativ, iar la adresa cea mai mare (ultima) se memoreaz octetul cel mai semnificativ. Un alt tip de constante l reprezint constantele zecimale codificate binar (BCD); procesorul poate opera cu dou tipuri i anume: zecimal mpachetat; zecimal nempachetat (denumit i format ASCII). Primul format se caracterizeaz prin faptul c fiecare din cele dou tetrade ale unui octet conine o cifr zecimal, deci valoarea unui astfel de octet este cuprins n intervalul 0 99; cel de-al doilea format conine numai o singur cifr, pe tetrada mai puin semnificativ, cealalt fiind 0, ca n reprezentarea urmtoare: 7 4 3 0 7 43 0 09 09 0 09 a) BCD mpachetat b) BCD nempachetat

n limbaj de asamblare, aceste constante sunt reprezentate n formatul mpachetat, pe 80 bii, utiliznd declaraia de tip: dt 12345678 pentru care se pot introduce maxim 18 cifre, deoarece octetul cel mai semnificativ conine, pe primul bit, semnul numrului, restul acestui octet (7 bii) fiind nefolosit. Memorarea se realizeaz dup aceeai regul, adic ncepnd cu octetul cel mai puin semnificativ i terminnd cu octetul cel mai semnificativ. Formatul zecimal nempachetat mai este d enumit i format ASCII deoarece exist o coresponden direct ntre formatul BCD nempachetat i cel ASCII (singura diferen ntre acest format i BCD este c prima tetrad conine valoarea 3, bineneles, pentru cifre).

adresa:
79

+9 71

+8

+7 63
55

+6 47

+5 39

+4 31

+3 23

+2 15

+1

adr 7 0

sx...x

18 cifre format zecimal mpachetat bit semn

Memorarea acestui numr se realizeaz conform regulii cunoscute, ncepnd cu octetul cel mai puin semnificativ la adresa adr i terminnd cu octetul cel mai semnificativ la adresa adr + 9. De exemplu, pentru o declaraie de forma: dt 12345678 reprezentarea intern va fi: 00 00 00 00 00 00 12 34 56 78. Constantele exprimate prin iruri de caractere constau dintr-o succesiune de caractere incluse ntre apostrofuri (Exemplu) sau ntre ghilimele ("sir caractere"). Dac n interiorul unui ir de caractere un subir trebuie s apar ntre apostrofuri sau ghilimele, atunci aceste caractere se dubleaz: 1 Dec1918

Propoziii n limbaj de asamblare


O propoziie este o succesiune de cuvinte i caractere din alfabetul limbajului de asamblare, construit dup anumite reguli sintactice, de lungime maxim egal cu 128 de caractere i care poate fi: instruciune; pseudoinstruciune. O instruciune reprezint o propoziie care este tradus n cod main. O pseudoinstruciune este o propoziie care nu se traduce n cod main, ea reprezentnd o directiv pentru coordonarea modului de lucru al asamblorului: definiri constante; rezervri zone de memorie; controlul procesului de asamblare.

Instruciuni n limbaj de asamblare


Sintaxa general a unei instruciuni este: [ eticheta : ] [ mnemonica [ operanzi ] ] [ ; < comentarii > ] unde etichet este un cmp care conine un nume simbolic format din maximum 31 de caractere alfanumerice i caractere speciale _, ?, @, $. Primul caracter este o liter sau un caracter special. Fiecare etichet are asociat o valoare numeric reprezentnd adresa relativ n cadrul segmentului (sau grupului de segmente) din care face parte; mnemonica reprezint numele instruciunii sau pseudoinstruciunii; operanzi este un cmp a crui existent i format depinde de tipul instruciunii. Dac instruciunea are doi operanzi, acetia se numesc destinaie i surs, i apar n instruciune n aceast ordine . Operanzii pot fi i expresii care conin registre, constante, identificatori, i operatori aritmetici, de indexare, logici, de deplasare, relaionali, de tip sau de conversie.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

18. Operatori i directive.

Operatori
Operatorii aritmetici Operatorii aritmetici pot fi unari (cu un singur operand): +, (deci stabilesc semnul unei expresii) sau binari: +, -, *, /, MOD (cu doi operanzi); MOD reprezint restul mpririi ntregi. / este operator pentru mprire ntreag. Operatorul index Acest operator este specificat prin paranteze drepte [ ] reprezint practic o adunare; este utilizat pentru precizarea operanzilor prin adresare indirect, indexat, bazat, bazat i indexat: depl [bx] [di] depl [bx + di] echivalente cu: depl + (bx) + (di) [depl + bx + di] sau o referin de forma: alfa [4] specific de fapt referirea la locaia: alfa + 4. Operatori logici Aceti operatori sunt: NOT, AND, OR, XOR i realizeaz operaiile logice respective bit cu bit, pentru expresii care sunt evaluate, la asamblare, la valori constante: NOT < expresie > < expresie 1 > AND < expresie 2 > < expresie 1 > OR < expresie 2 > < expresie 1 > XOR < expresie 2 > Aceti operatori nu trebuie confundai cu instruciunile de procesor anonime, care opereaz asupra registrelor sau memoriei n timpul execuiei programului. Operatorii logici utilizeaz expresii, evaluate valori constante, n faza de asamblare a programului. De exemplu: alfa db 01110111B and 0f0H Operatori de deplasare Aceti operatori sunt utilizai pentru deplasarea logic a unor expresii, evaluate la valori constante n momentul asamblrii programului, cu un numr de bii la stnga sau dreapta: < expresie > SHR < numr > SHL unde < numr > reprezint o expresie ntreag care indic numrul de bii pe care se execut deplasarea. La deplasare, biii deplasai n afara operandului se pierd, iar cei eliberai prin deplasare devin zero (indiferent de sensul deplasrii). Aceti operatori nu trebuie confundai cu

instruciunile de procesor anonime, dar care acioneaz asupra unor operanzi din registre sau din memorie. Operatori relaionali Aceti operatori compar dou expresii, rezultatul fiind o valoare logic (true = ffH sau false = 00H) n funcie de valoarea de adevr a relaiei dintre cei doi operanzi. Operatorii sunt: EQ egalitate; NE inegalitate; GT mai mare; GE mai mare sau egal; LT mai mic; LE mai mic sau egal. Sintaxa pentru utilizarea acestor operatori este: < expresie 1 > [operator] < expresie 2 > Operatori de tip i de conversie Aceti operatori specific/analizeaz tipul operanzilor din memorie sau alte expresii, sau pot realiza conversie de tip. a) HIGH, LOW < expresie > Cei doi operatori furnizeaz octetul mai semnificativ, respectiv octetul mai puin semnificativ al unei expresii de tip cuvnt (doi octei). De exemplu: data_16 equ 0abcdh mov ah, high data_16 mov al, low data_16 pentru a ncrca primii opt bii, respectiv urmtorii opt bii dintr-o constant de tip cuvnt. b) SEG < expresie > Acest operator furnizeaz adresa de segment a unei adrese exprimat printr-o expresie, care poate fi variabil, operand memorie, etichet, numele unui segment sau numele unui grup de segmente. Exemplu: beta dw...... . . mov mov bx, seg beta ds, bx

c) OFFSET < expresie > Operatorul furnizeaz deplasamentul n cadrul segmentului pentru o expresie de tip variabil (simpl sau structurat), operand memorie, etichet. Aplicat unei variabile sau etichete, operatorul furnizeaz offsetul (deplasamentul) variabilei sau etichetei. Valoarea este cunoscut n momentul link-editrii, cnd se face alinierea final a segmentului, deoarece offset-urile de la

asamblare se pot modifica, la localizare, dac segmentul este combinat cu pri ale aceluiai segment, definite n alte module sau dac nu este aliniat la un paragraf. De exemplu, poate fi utilizat n adresarea indirect a variabilelor: sir dw ....... .... mov bx, offset sir ; adresa de inceput a sirului mov si, 0 ; se initializeaza indexul primului element din sir ... ... add ax, [bx] [si] ; se insumeaza elementele Dac se utilizeaz directiva group, operatorul OFFSET nu va returna offset-ul unei variabile din grup, ci pe acela al variabilei din segmentul s u. Pentru a returna offset-ul variabilei din grupul respectiv trebuie utilizat prefixul grupului respectiv n faa variabilei: dgrup group data1, data2 data1 segment ...... data1 ends data2 segment ..... val db .... ...... dw val ; offfsetul in cadrul segmentului furnizat de asamblor dw dgrup:val ; offsetul in grup dd val ; offset in segment + adresa segment dd drgup:val ; offset in grup + adresa segment data2 ends mov bx,offset val ; offset in segment mov bx,offset dgrup:val ; offset in grup Observaie: - offset [bx] este echivalent cu [bx] - offset depl[bx] este echivalent cu [depl+bx]

d) TYPE < expresie > Furnizeaz un numr ntreg ce reprezint tipul expresiei asupra creia se aplic; are un singur argument, care poate fi o variabil sau etichet. Dac expresia este o variabil (simpl sau structurat), operatorul returneaz numrul de octei pe care se reprezint componentele variabilei simple sau numrul de octei ai variabilei structurate. Valorile returnate de operator, n funcie de tipul variabilei, sunt: byte - 1; word - 2; dword - 4; qword - 8; pword - 6; fword - 6;

tbyte - 10; structura numarul de octeti ai structurii; Se utilizeaz, de obicei, n calcule asupra vectorilor sau structurilor, pentru a determina adresa urmtorului element. Dac argumentul este de tip etichet, operatorul, n funcie de tipul etichetei, returneaz valorile: near - ffffH; far - fffeH; Exemple: var dw mov bx, vector dd mov si, num_BCD mov bx, ...... type var ; (BX) = 2 10 dup (?) type vector ; (SI) = 4 dt 13245768,..... type num_BCD; (BX) = 10

e) LENGTH < expresie > Acest operator furnizeaz o valoare ntreag ce reprezint numrul de elemente ale unei variabile (declarat utiliznd operatorul DUP). Dac variabila a fost declarat prin utilizarea operatorului DUP imbricat (unul inclus ntr-altul), atunci operatorul LENGTH va returna o valoare asociat operatorului exterior. Dac variabila nu a fost declarat utiliznd operatorul DUP, atunci operatorul LENGTH va returna valoarea 1. Exemple: n1 n2 n3 mes db dw dd db 50 dup (?); 150 dup (0, 1, ?); 200 dup (10, 20, 15 dup (?)); Exemplu de mesaj;

length n1 = 50; length n2 = 150; length n3 = 200; length mes = 1; f) SIZE < expresie > Furnizeaz o valoare ce reprezint numrul de octei ocupai de o variabil i este corelat cu operatorii LENGTH i TYPE prin identitatea: SIZE = LENGTH * TYPE Dac o variabil a fost declarat utiliznd operatorul DUP imbricat, SIZE furnizeaz, conform relaiei anterioare, numai valoarea operatorului DUP exterior. Pentru declaraiile anterioare, acest operator va furniza urmtoarele valori:

size n1 = 50; size n2 = 300; size n3 = 800; size mes = 1; g) PTR < expresie > Acest operator realizeaz conversia de tip pentru o variabil, un operand memorie sau o etichet fie pentru a specifica tipul adresrii, fie pentru a permite adresarea unor date cu un alt tip dect utilizat la declararea acestora. Sintaxa acestui operator este: tip PTR < expresie > unde tip poate fi BYTE, WORD, DWORD, QWORD, PWORD, FWORD, TBYTE sau nume de structur pentru operanzi din memorie i variabile, respectiv NEAR, FAR, PROC sau unknown pentru etichete de instruciuni, nume de proceduri. De fapt, acest operator asociaz urmtoarele atribute expresiei: Tip expresie Segment Variabil sau etichet Expresie numeric Exemple: i) Explicitarea tipului referinei la memorie, pentru referine anonime: inc byte ptr [bx] inc word ptr [si] mov byte ptr [bx], 99 mov word ptr [di], 100 and word ptr [bp], 100h Specificarea tipului de salt (intersegment sau intrasegment): jmp dword ptr [bx] jmp near ptr etich ; pentru etich declarata in alt modul, daca ; aceasta eticheta este in acelasi segment sau ; grup de segmente cu instructiunea de salt Referirea unor variabile cu un alt tip dect cel utilizat la declararea acestora: aw dw 0abcH, 12abH ab db 0aH, 12H mov al, byte ptr aw mov ax, word ptr ab SEG <expresie> nedefinit Atribute asociate Offset OFFSET <espresie > <expresie> Type tip tip

ii)

iii)

iv)

Crearea unei variabile anonime la un offset dat dintr-un segment: mov al, ds: byte ptr 5 ; face referire la octetul de la ds:5 mov bx, data1: word ptr 3000H ; face referire la cuvantul de ; offsetul 3000H din segmentul data1

la

Aceste dou declaraii sunt echivalente cu urmtoarele dou: mov al, ds:[5] mov bx, data1:[3000] h) SHORT Acest operator accept un argument de tip etichet (un offset adresabil prin registrul segment CS). Se utilizeaz n instruciuni de salt condiionat, necondiionat i n instruciuni de apel de procedur, cnd codul int are un deplasament autorelativ de un octet cu semn (adic inta saltului se afl n intervalul -128 127 fa de instruciunea de salt). n mod normal, o instruciune de salt va codifica deplasamentul la instruciunea int ca un numr ntreg, pe 16 bii. Utiliznd acest operator, cu condiia ca inta s se gseasc n intervalul [-128, 127], asamblorul va codifica deplasamentul intei pe un singur octet, reducnd cu un octet codul generat: jmp short etich De fapt, asamblorul genereaz n mod automat un deplasament pe 8 bii dac deplasamentul autorelativ al intei este n intervalul [-128,+127], dar pentru referine externe (adic pentru etichete definite n alte module, de tipul near) va genera un deplasament pe 16 bii. Dac referina se afl n intervalul menionat, atunci utiliznd operatorul SHORT ca n exemplul anterior, se va genera un deplasament de un octet, reducnd cu un octet codul generat pentru instruciunea de salt. i) WIDTH, MASK Aceti operatori sunt folosii pentru a returna numrul de bii sau o masc de bii pentru o nregistrare care reprezint un tip de date structurat. Operatorul WIDTH returneaz numrul de bii ai unei nregistrri sau al unui cmp al unei nregistrri, dup cum argumentul su este numele nregistrrii sau numele unui cmp al nregistrrii. Operatorul MASK are ca argument numele unui cmp al unei nregistrri, i returneaz o masc de bii, definii ca fiind 1 pentru poziiile cmpului respectiv, respectiv zero pentru celelalte poziii. Exemplu: model record A:3, B:1, C:4, D:5, E:3; reprezinta numele ; asociate campurilor respective, impreuna ; cu numarul de biti pentru fiecare camp mov cx, mask C ; (CX) = 000 0 1111 00000 000 = 0f00H mov cl, width D ; (CL) = 5, dimensiunea campului D mov cl, C ; (CL) = 8, pozitia campului C Prioritatea operatorilor Ordinea de evaluare a unei expresii este determinat de prioritile asociate operatorilor. Operatorii cu prioritate mai mare sunt evaluai primii. Expresiile cu aceeai prioritate sunt

evaluate de la stnga la dreapta. Ordinea de evaluare poate fi modificat utiliznd paranteze, n care caz expresiile dintre paranteze se vor evalua primele. Dac expresiile conin paranteze pe mai multe niveluri, atunci evaluarea ncepe cu prima parantez interioar. Prioritatea operatorilor este urmtoarea: 1. length, size, width, mask, (), [ ], < >, operatorul cmp de structur; 2. seg, offset, type, ptr, prefix segment : ; 3. high, low; 4. +, (operatorii unari); 5. *, /, mod, shl, shr; 6. +, (operatori binari); 7. eq, ne, gt, lt, ge, le (operatori relaionali); 8. not; 9. and; 10. or, xor; 11. short

Definirea i iniializarea etichetelor


Etichetele identific locaii de memorie ale instruciunilor, operanzilor sau apeluri de proceduri. Ele au trei atribute: segment, deplasament (offset) i distan (near sau far) pentru etichete de instruciune i nume de proceduri, sau tip (byte, word etc.) pentru etichete de operanzi. Etichetele de tip near pot fi definite astfel: etich_near: mov ax, bx proc_alfa label near calcul proc near n acest ultim caz, dac nu se specific tipul, n mod implicit acesta va fi tot de tip near. Exemple pentru tipul far: beta etich_far proc label far far

Aceast directiv nu incrementeaz contorul de program ($). n cazul unei etichete de operand se va specifica tipul acesteia, ca de exemplu n cazul declarrii vrfului stivei din segmentul de stiv: stiva dw varf_stiva stiva segment 100 dup (?) label ends

word

pentru a permite, ulterior, iniializarea registrului SP cu vrful stivei. Directiva EQU Aceast directiv permite atribuirea unei valori, n momentul asamblrii, la un simbol. Sintaxa este: <nume> EQU <expresie>

unde expresia poate fi: constant: val1 equ 1 valc equ 5*5 orice expresie corect n limbaj de asamblare: inreg record A:5, B:5, C:5 v321 equ inreg < 3, 2, 1 > e1 equ (mask a) or (0f0h and mask b) e2 equ valc mod 10
simbol definit anterior: unu

equ

val1

ir de caractere, cu diferite semnificaii: referin indexat: rbp equ

[ bp + 8 ]

care poate fi apoi folosit astfel: mov ax, rbp.camp operator prefix segment i operanzii si: rdsbp8 equ ds:[bp + 8] nume de instruciuni: IDAI equ

AAD

; se poate apoi inlocui in program mnemonica ; AAD cu cea nou definita.

ir de caractere: octet equ <db> ; se poate folosi in pr. in loc de db noul nume: octet; sir_car equ <mesaj, 0DH, 0AH, $> sau sir_car equ mesaj, 0DH, 0AH, $

Observaie: parantezele unghiulare trebuie utilizate la redefinirea pseudoinstruciunilor, pentru a le delimita precis. n mod asemntor, pentru valori numerice se mai poate folosi i operatorul =, cu sintaxa: <nume> = <expresie> Diferena dintre cei doi operatori este c numele simbolice utiliznd operatorul EQU nu i pot modifica valoarea pe durata asamblrii programului, pe cnd identificatorii definii cu operatorul = i pot modifica valoarea, adic se pot utiliza declaraii de forma: n=0 .....

n=n+1 Operatorul THIS Acest operator creeaz un operand cu adresa de segment i offset egal cu aceea a locaiei curente a contorului program. Formatul general este: this tip unde specificatorul tip poate fi BYTE, WORD, DWORD, QWORD sau TBYTE pentru operanzi din memorie i variabile, respectiv NEAR, FAR, PROC pentru etichete. El poate fi u tilizat, de obicei, cu directivele EQU sau semnul =. Exemplul urmtor definete eticheta param: param equ this byte Efectul acestei declaraii este acelai cu acela al utilizrii directivei LABEL: param label byte Simbolul contor program $ (contor locaii) Simbolul $ reprezint adresa curent a contorului program, adic adresa relativ n cadrul segmentului curent a instruciunii sau datelor de asamblat. La nceputul fiecrui segment contorul de locaii este iniializat la zero i este actualizat de asamblor pe msura asamblrii programului. Exemple: lista dw 11, 22, 33, 0aah lung_lista equ ($ lista)/2 mesaj db mesaj $ lung_mesaj equ $ mesaj n ambele exemple s-a determinat numrul de elemente, respectiv de cuvinte/octei, din cele dou declaraii utiliznd acest simbol. S nu se confunde simbolul $ cu caracterul $. Directiva ORG Cu aceast directiv, contorul de locaii poate fi iniializat cu o anumit valoare pozitiv, astfel: ORG < expresie > unde expresia este evaluat modulo 64K i nu trebuie s conin referine ulterioare. Exemple: org 100h ; ce urmeaza in continuare va fi depus in ; segmentul respectiv de la adresa relativa 100h org offset $ + 100 ; se rezerva, de la ultimul octet asamblat, ; 100 octeti neinitializati Directiva nu poate fi atribuit la o etichet, adic o declaraie de forma start: org 100h va genera o eroare. n schimb putem proceda astfel:

org start: sau pentru date: date org

100h ....

label $ + 100

byte

i n acest fel se rezerv 100 de octei de la adresa specificat. Observaie: o declaraie de forma org offset $ 100 nu are sens, deoarece nseamn c datele care urmeaz dup aceast directiv vor fi scrise peste ultimii 100 de octei. (definii anterior).

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

19. Declararea datelor n LA. Declarare etichete n limbajul de asamblare.

Declararea datelor n limbaj de asamblare


Declararea datelor se realizeaz cu ajutorul unor pseudoinstruciuni care asigur: alocarea de memorie pentru date, specificarea tipului datelor i iniializarea datelor. Datele pot fi specificate prin nume, expresii sau iruri de caractere, care se evalueaz n procesul de asamblare la constante. Operaia de alocare i iniializare a datelor are loc n procesul de asamblare; datele sunt nscrise n fiierul obiect, de unde vor fi preluate la execuie. Sintaxa este urmtoarea: [ nume_variabila ] sau [ nume_variabila ] tip [numar] DUP ([ lista_expresii ]) unde nume_variabil = identificator, construit dup regulile specificate anterior; tip = mnemonica pseudoinstruciunii, care specific implicit tipul datelor: db define byte; definete date de tip octet ntregi, cu sau fr semn; dw define word; cuvnt de 16 bii ce definete date ntregi, cu sau fr semn; dd define double; dublu cuvnt, de 32 de bii ce poate defini un pointer sau o valoare ntreag sau real, cu sau fr semn; dq define quadruple; cuvnt de 64 de bii ce poate defini o valoare real sau ntreag; df define float; real pe 6 octei; dp define pointer; referin specific pentru 386, reprezentat pe 6 octei (segmentul pe 2 octei, iar deplasamentul pe 4 octei); dt define ten bytes; dat de 10 octei de tip real sau zecimal mpachetat; nume_structur numele unei structuri utilizat pentru definirea unor date cu aceast structur; list_expresii = expresii, separate prin virgule, evaluate la constante, care reprezint valorile folosite la iniializarea datelor definite. Simbolul ? arat c datele respective nu se iniializeaz. Construcia este recursiv. Evaluarea expresiilor se face la asamblare.
numr = expresie ce reprezint factorul de multiplicare al listei de expresii care urmeaz dup operatorul DUP.

tip

[ lista_expresii ] [;comentarii]

Exemple: a lit

db db

aw dw AB dw adrAB dw off_AB seg_AB rez dw v1 dd v2 dd

-100; se pot defini valori n intervalul [-128, +127] sau [0, 255] abcde; se vor memora codurile ASCII ale caracterelor din list: 61h, 62h, 63h, 64h, 65h -1000 ; domeniul de valori: [-32768, 32767], sau [0, 65535] AB ; va depune la adresa AB: 42h, 41h AB ; se va depune deplasamentul etichetei AB, stabilit la asamblare dw offset AB ; deplasamentul etichetei AB, stabilit la locatare dw seg AB; adresa segment de la locatare ? ; coninut nedefinit 1.0 ; valoare real definit pe 32 bii 1A2B3C4Dh ; valoare ntreag pe 32 bii

adr_v1 dd

v1 ; pointer pentru referirea lui v1

Pentru a multiplica definirea unor date se utilizeaz operatorul DUP, alturi de db, dw etc. Sintaxa este urmtoarea: < numar > DUP (expresie pt. valoarea iniial) n acest fel se definete o structur format dintr-un <numr> de elemente, iar un element poate fi expresie numeric, semnul ? dac nu se specific valoarea iniial, o list de elemente sau ali operatori DUP. Exemple: db 100 dup (0) ; multiplicarea valorilor initiale db 2 dup (0, 3 dup (1)), 10, 25, 100) dw 100 dup (5 dup (4), 7) db 10 dup (mesaj , 0dh, 0ah) Declararea etichetelor Etichetele identific locaii de memorie ale instruciunilor, operanzilor sau apeluri de proceduri. Ele au trei atribute: segment, deplasament (offset) i distan (near sau far) pentru etichete de instruciune i nume de proceduri, sau tip (byte, word etc.) pentru etichete de operanzi. Etichetele de tip near pot fi definite astfel: etich_near: mov ax, bx proc_alfa label near calcul proc near n acest ultim caz, dac nu se specific tipul, n mod implicit acesta va fi tot de tip near. Exemple pentru tipul far: beta proc far etich_far label far Aceast directiv nu incrementeaz contorul de program ($). n cazul unei etichete de operand se va specifica tipul acesteia, ca de exemplu n cazul declarrii vrfului stivei din segmentul de stiv: stiva dw varf_stiva stiva segment 100 dup (?) label ends

word

pentru a permite, ulterior, iniializarea registrului SP cu vrful stivei.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

20. Definirea i utilizarea segmentelor (directive simplificate i complete).

Definirea i utilizarea segmentelor


Un segment este definit ca o colecie de instruciuni sau date, ale cror adrese sunt relative fa de nceputul segmentului (fa de registrul segment corespunztor). Specificarea segmentelor se poate face n dou moduri: definire simplificat a segmentelor; definire complet a segmentelor. Cele patru registre segment la care procesorul are acces n orice moment, CS, DS, ES i SS, deci care pot face referire la patru segmente logice, pot corespunde la patru segmente fizice distincte sau pot exista suprapuneri pariale sau totale ale acestor segmente. Adresa fizic aferent unui segment este multiplu de paragraf (16 octei). Forma simplificat are avantajul, din punct de vedere al utilizatorului, c ofer o gestiune mai simpl a segmentelor. Un program are, n general, un segment de cod, unul de date i unul de stiv. Excepie de la aceast regul fac programele cu extensia .com, care pot fi definite utiliznd definirea simplificat, modelul tiny i opiunea respectiv de editare de legturi (/t), fr a fi necesar definirea unui segment de stiv i iniializarea registrelor segment, deoarece toate vor fi iniializate cu aceeai valoare, reprezentnd adresa de nceput a segmentului ce conine ntregul program, date i stiv (toate intr ntr-un segment de 64 Ko). La ncrcarea n memorie a unui program, pentru execuie, sistemul de operare iniializeaz registrul segment CS cu prima adres de segment disponibil, iar registrul IP cu adresa relativ, din cadrul segmentului, a primei instruciuni ce trebuie executat. Dac programul conine cele trei segmente (cod, date i stiv), atunci aceste segmente logice se ncarc n memorie n ordinea logic: cod, date, stiv.

Forma complet de definire a segmentelor


Se utilizeaz o declaraie de forma: nume_seg SEGMENT [tip_aliniere][tip_combinare][tip_utilizare][clasa_seg] .... ... < corpul segmentului > ; instructiuni sau date .... nume_seg ENDS unde nume_seg este numele asociat segmentului, care trebuie s fie unic i cruia i se asociaz o adres de segment (de 16 bii) corespunztoare poziiei n memorie a segmentului n faza de execuie a programului. Iniializarea unui registru segment (DS, ES sau SS) cu un segment declarat revine utilizatorului, care o va executa n mod explicit n cadrul programului, utiliznd pentru aceasta numele segmentului respectiv: mov ax, <nume_seg> mov ds, ax ; in mod asemanator pentru ES sau SS Urmtoarele referiri la memorie care implic registrul DS trebuie s conin trimiteri la date din acest segment (asamblorul nu verific dac aceste referine sunt corecte).

tip_aliniere este o informaie referitoare la adresa fizic de nceput la care este depus segmentul n memorie, i anume dac este divizibil cu 1, 2, 4, 16 sau 256. Acest tip poate fi: byte adres divizibil cu 1; word adres divizibil cu 2; dword adres divizibil cu 4; para adres divizibil cu 16 (paragraf); page adres divizibil cu 256. Omiterea operatorului tipului de aliniere pentru primul segment va cauza alinierea implicit la tipul para. Omiterea tipului de aliniere pentru un segment care nu este unic, implicit va determina alinierea la tipul specificat la definirea anterioar a segmentului cu acelai nume. Pentru alinierea datelor, de exemplu la dublu cuvnt, se poate folosi directiva ALIGN 4. tip_combinare sau tip segment constituie o informaie pentru editorul de legturi, care specific raportul dintre acest segment i alte segmente definite n alte module obiect. Acest parametru poate fi: PUBLIC ceea ce arat c acest segment va fi concatenat (nlnuit) cu alte segmente cu aceleai nume din alte module obiect, obinndu-se un singur modul cu acest nume; COMMON precizeaz c acest segment i alte segmente cu aceleai nume din alte module vor fi suprapuse, deci vor ncepe de la aceeai adres. Lungimea unui astfel de segment va fi lungimea celui mai mare segment dintre cele suprapuse; AT <expresie> un astfel de segment va fi plasat la adresa reprezentat de valoarea <expresie>, care este o valoare de 16 bii, reprezentnd adresa n memorie a segmentului. Un astfel de segment nu va conine, ns, cod sau alte date iniializate. El reprezint un ablon care se poate suprapune peste codul sau datele aflate deja n memorie. Asamblorul nu genereaz cod sau date pentru un segment de acest tip, dar permite adresarea n cadrul acestui segment. Exemplu de utilizare: RAM_graph segment at 0b800H start_buffer label byte RAM_graph ends . . . mov ax, RAM_graph mov es, ax assume es:RAM_graph ; in continuare se poate face referirea in acest ; segment utilizand adresa de start start_buffer
MEMORY segmentul curent de acest tip va fi aezat n memorie n spaiul rmas disponibil dup aezarea celorlalte segmente (ctre sfritul memoriei). Dac sunt editate mpreun mai multe segmente de acest tip, urmtoarele vor fi tratate ca segmente obinuite. STACK va concatena toate segmentele cu aceleai nume, pentru a forma un segment unic; referirea acestui segment se face prin SS:SP. Registrul SP va fi iniializat, n mod automat cu lungimea stivei.

NONE segmentul va fi separat logic de late segmente, dei ele se pot termina fizic adiacent. Acest tip este implicit pentru directivele complete de segmentare. Se presupune c segmentul va avea propria sa adres de baz.

tip_utilizare reprezint atributul modului de utilizare, pentru procesoarele de la 386 n sus, ce poate lua valorile: USE16, USE32 sau FLAT; aceste atribute specific modul de lucru, de baz, pentru aceste segmente: pe 16 bii sau pe 32 de bii. Pentru codul ce se va executa n modul real sub DOS se vor utiliza segmente de 16 bii, n timp ce segmentele ce lucreaz pe 32 de bii vor fi cele ce se execut n modul protejat. Amnunte suplimentare pentru aceste dou atribute vor fi prezentate n capitolul referitor la combinarea ntre codul de 16 bii i codul de 32 de bii. Pentru a stabili sau fora, ca implicit, un anumit tip de utilizare pentru anumite segmente dintr-un modul se poate plasa nainte de nceputul segmentelor directiva: option segment: use16 Ca tip_utilizare se mai pot utiliza i atribute de tipul read-only, pentru ca asamblorul s genereze mesaje de eroare la ncercarea (doar la asamblare) de a scrie n acel segment. Cu toate acestea, la execuia programului, acesta poate s scrie ntr-un astfel de segment. clasa_seg este un nume cuprins ntre apostrofuri simple; rolul acestui nume este de a permite controlul ordinii n care vor fi depuse n memorie segmentele care compun un program. Dac nu se precizeaz clasa, atunci aceasta este considerat irul vid de caractere. Dou segmente cu aceeai clas vor fi dispuse n memorie la adrese succesive. Specificarea clasei furnizeaz un mijloc de a colecta segmente specificate similar la editarea legturilor (primul mijloc este numele segmentului). S considerm, de exemplu, dou module care conin urmtoarele declaraii: Modul 1: aseg segment byte public code start: . ....... . aseg ends bseg . ....... . bseg cseg . ....... . cseg dseg ....... . ends segment at 0b800H ends segment para stack stack segment word common data

dseg end Modul 2: aseg . ....... . aseg bseg . ...... . bseg end

ends start code

segment

byte

public

ends segment word common data

ends

Pentru aceste declaraii, editorul de legturi va dispune segmentele n memorie astfel: aseg (M1) aseg(M2) bseg (M2) cseg bseg (M1) (M1+M2) 00000H dseg (M1) B8000H

FFFFFH

Segmentele sunt plasate n memorie n ordinea n care au fost declarate. Segmentul de stiv, dac este declarat complet, va fi amplasat, indiferent de poziia sa n textul surs, dup celelalte segmente. Dac are clasa stack, SP va fi iniializat automat cu dimensiunea stivei, altfel nu va fi iniializat. Un segment poate fi redeschis, deci cu un nume declarat anterior, n care caz contorul de locaii $ este ncrcat cu valoarea salvat n momentul ntlnirii directivei ENDS pentru acel segment. Pe lng tipurile de combinare menionate anterior mai exist i tipul PRIVATE, care este un tip special (none) i care nu se combin cu nici un alt tip. Segmente imbricate Segmentele nu sunt niciodat fizic imbricate (incluse unul ntr-altul); totui, este permis s se codifice o poriune de segment, apoi s se nceap i s se ncheie un alt segment, dup care s se termine codul nceput primul. Cnd se editeaz un program n acest mod, asamblorul va concatena cea de-a doua poriune a segmentului la prima. Se spune c segmentele sunt logic imbricate, dar nu fizic imbricate. De exemplu: code1 assume data1 data1 segment cs:code1, ds:data1 ....... segment ....... ends

....... code1 ends

n schimb, aceste segmente nu se pot intersecta: data3 ....... data4 ....... data3 ....... data4 ends n consecin, o astfel de declarare a segmentelor nu este permis. ends segment segment

Directive simplificate de segmentare


.MODEL tip_model Prin aceast directiv se specific dimensiunea i modul de dispunere a segmentelor n memoria RAM. Modelele de implementare, tip_model, sunt urmtoarele: tiny pentru care LP + LD + LS < 1 segment (64K) small pentru LP < 1 seg (64K), LD + LS < 1 seg. medium pentru LP > 1 seg (64K), LD + LS < 1 seg. compact pentru LP < 1 seg (64K), LD + LS > 1 seg. large pentru LP > 1 seg (64K), LD + LS > 1 seg. huge la fel cu modelul anterior, cu diferena c referinele sunt normalizate. Abrevierile utilizate sunt LP, LD, LS i reprezint lungimea programului (codului), dimensiunea memoriei pentru date i respectiv pentru stiv. Aceste abrevieri pot fi interpretate i ca numr de segmente de cod (LP), respectiv numr de segmente de date (LD), n sensul c, de exemplu pentru modelul small exist numai un segment pentru cod i unul pentru date, n timp ce pentru modelul large sunt definite mai mult de cte un segment, att pentru cod, ct i pentru date. Referinele la variabile i etichete care se gsesc n alte segmente se pot exprima n dou forme: a) prin adresa logic: adresa segmentului + offsetul, care nu este unic; de exemplu, aceeai adres fizic poate fi exprimat astfel: 1234H:0005H, sau 1230H:0045H, sau 1200H:0345H etc. b) prin adresa normalizat (sau fizic), adic un ntreg de 32 bii, sau 48 bii la 386, care ns este unic; pentru exemplul anterior, aceasta este: 12345H. Directiva model este prima din programul surs. Cnd se leag programe scrise n limbaje de nivel nalt cu programe scrise n limbaj de asamblare, toate trebuie s posede acelai model. Mai exist i modelul TPASCAL, care este echivalent cu modelul LARGE, PASCAL, la care se adaug conveniile de transfer pentru parametri ntre subprograme, conform conveniilor din TPascal.

n cazul n care programul n limbaj de asamblare se va lega cu un program scris n limbajul C sau PASCAL, acest lucru se va specifica n directiva .model: .model small, C .model large, Pascal (echivalent cu modelul TPascal) Aceasta este necesar pentru a se respecta conveniile specifice fiecrui limbaj n ceea ce privete simbolurile externe i transferul parametrilor ntre subprograme. Directiva .model presupune o directiv implicit ASSUME, care se refer doar la registrele segment de cod, date i stiv, dar nu i la extrasegmentul de date (ES). .STACK [dimensiune] Aceast directiv aloc o zon de memorie, de dimensiune specificat, pentru segmentul de stiv. Dac nu se specific parametrul dimensiune, acesta va fi implicit de 1Ko; de fapt, cu valoarea acestui parametru va iniializa asamblorul registrul SP. .CODE [nume] Aceast directiv precede segmentul de cod (program). ncrcarea aces tui registru segment (CS) se va face automat de ctre DOS la ncrcarea segmentului pentru execuie. Sistemul de operare DOS are sarcina amplasrii segmentelor n memorie. Se pot asocia nume (maxim 6 caractere) pentru segmentele de cod, pentru modelele medium, large i huge; pentru celelalte modele, el este ignorat. .DATA Aceasta descrie segmentul de date pentru care utilizatorul trebuie s iniializeze, n mod explicit, registrul segment DS, cu adresa segmentului de date, @DATA; simbolul acesta va primi adresa segmentului de date, dup editarea legturilor, n momentul ncrcrii sale de ctre sistemul de operare. Pentru ca programele s fie relocabile, registrele segment nu se ncarc niciodat cu valori absolute. Pe lng acestea mai exist directivele: .DATA? pentru date neiniializate, referine de tip NEAR; .FARDATA [nume] date iniializate sau nu, referine de tip FAR; .FARDATA? [nume] date neiniializate, referine de tip FAR; .CONST segment cu date de tip read-only (constante), care pot fi rezidente i n ROM, spre deosebire de celelalte care sunt rezidente numai n RAM. Segmentele definite cu directivele: data, .const, .data?, .stack vor fi grupate automat n grupul predefinit DGROUP pentru acele modele la care dimensiunea acestora nu depete un segment. Directivele simplificate nu specific un nume pentru segmentele logice declarate, ele avnd nume implicite: directiva .code .data .const .data? .stack numele nume_TEXT _DATA CONST _BSS STACK aliniere word word word word para combinare public public public public stack clasa 'CODE' 'DATA' 'CONST' 'BSS' 'STACK' grupul DGROUP DGROUP DGROUP DGROUP

.fardata .fardata?

FAR_DATA para FAR_BSS para

private private

'FAR_DATA' 'FAR_BSS' -

Numele concatenat cu _TEXT este numele asociat n directiva .code sau, dac acesta lipsete, va fi numele fiierului. Tabela de segmente i grupuri de la sfritul listingului con ine denumirile reale ale segmentelor; la asamblare se poate solicita (prin opiunea /l) furnizarea listingului (adic lista de instruciuni asamblate, alturi de codurile i adresele lor) ntr-un fiier care are extensia .lst. Directiva model (pentru tiny, small i medium) va genera liniile surs adecvate n care apare directiva GROUP: DGROUP GROUP _DATA, CONST, _BSS, STACK iar pentru modelele small i compact, linia surs pentru directiva ASSUME: ASSUME CS:nume_TEXT, DS:DGROUP, SS:DGROUP Utilizarea formei simplificate de declarare a segmentelor nu scutete programatorul de sarcina specificrii modului de utilizare a registrelor de segment i nici de asigurarea coninutului registrelor segment, conform pseudoinstrucunii ASSUME. Numele implicite ale segmentelor pot fi obinute utiliznd simbolurile predefinite: @CODE numele segmentului de cod; @DATA?, @DATA numele segmentului de date (ne)iniializate; @FARDATA numele segmentului de date iniializate, de tip FAR; @FARDATA? numele segmentului de date neiniializate, FAR; @CURSEG numele segmentului curent executat; forma: @curseg ends conduce la nchiderea segmentului curent; Aceste simboluri pot fi utilizate n directivele ASSUME i la iniializarea registrelo r segment: assume cs:@code, ds:@data mov ax, @data mov ds, ax Alte simboluri predefinite: @FILENAME numele de baz al fiierului surs curent; aceast facilitate permite modificarea simpl a tuturor denumirilor ce depind de numele fiierului surs. @CODESIZE are valoarea: 0 pentru tiny, small i compact 1 pentru medium, large, huge. @DATASIZE are valoarea: 0 small, medium 1 compact, large 2 huge. Simbolurile @CURSEG i @FILENAME pot fi folosite i n directivele complete de segmentare. n forma simplificat, dac dorim s utilizm instruciuni specifice procesoarelor

286/386/, se specific acest lucru prin directive de forma .286, .386 etc., care se plaseaz imediat dup directiva model. Pentru a plasa segmentele de cod, date i stiv n ordinea logic (cod, date, stiv) se poate utiliza directiva DOSSEG, altfel ele vor fi plasate n ordinea n care apar fiierele n comanda TLINK (mai puin segmentul de stiv, care este oricum plasat la sfrit). returneaz o valoare de 16 bii, care determin directivele procesor active, dup bitul respectiv setat: 0-8086, 1-186, 2-286, 3-386, 4-486, 5-Pentium, 6-rezervat 8086, 7-instruciuni specifice modului protejat, biii 8-11 sunt pui pe 1 pentru coprocesoarele 8087, 287, respectiv 387 (bitul 11 este setat pentru toate procesoarele ncepnd de la 486/ Pentium). @WORDSIZE returneaz o valoare de 16 bii, care determin tipul de utilizare al segmentului: 2 pentru segment de 16 bii, respectiv 4 pentru segment de 32 de bii. @MODEL returneaz 1 pentru tiny, 2 pentru small, 3-compact, 4-medium, 5-large, 6-huge, 7-flat. @CPU Alte directive: .SEQ .ALPHA se pot utiliza pentru dispunerea segmentelor n ordine secvenial, respectiv alfabetic. Segmentele ce aparin aceleiai clase vor fi dispuse mpreun, indiferent de ordinea secvenial sau alfabetic din fiierul surs. Se mai pot utiliza urmtoarele directive cu semnificaia specificat pentru fiecare. .STARTUP genereaz instruciunile pentru iniializarea registrelor segment, i .EXIT care poate fi utilizat pentru generarea funciei de ieire dintr-un program i revenire n DOS, adic funcia 4Ch, int 21h. ALIGN determin asamblorul s alinieze data sau instruciunea care urmeaz ncepnd de la o adres n concordan cu o anumit valoare. Alinierea aceasta poate facilita procesorului accesul la cuvinte sau cuvinte duble. Formatul ei este urmtorul: align valoare unde valoare este o putere a lui 2, cum ar fi 2, 4, 8 sau 16. S presupunem c valoarea contorului de locaii este 0005, cnd se d directiva ALIGN: 0005H 0008H ALIGN 4 dublu_cuv dd 0

care va alinia variabila dublu_cuv la o adres de tip cuvnt dublu, adic divizibil cu 4.

Asamblorul va umple octeii nefolosii cu 0 pentru date i cu NOP pentru instruciuni. EVEN cere asamblorului s avanseze contorul de locaii astfel nct data sau instruciunea urmtoare s fie aliniat la o adres par. Dac n exemplul anterior se plaseaz directiva EVEN n locul directivei ALIGN, data dublu_cuv va fi plasat la adresa 0006H. .CREF specific asamblorului s genereze tabela cu referine ncruciate. Ea este implicit, dar dac se dorete suprimarea acestei tabele, atunci aceast directiv trebuie urmat de .XCREF. .tip_procesor Pentru a specifica utilizarea unui anumit tip de procesor, i deci a unor instruciuni specifice acestuia, se pot utiliza directivele procesor, care sunt plasate, de obicei, la nceputul programului surs. Ele pot fi ns plasate i n interiorul unui program, n punctul n care se dorete activarea sau dezactivarea caracteristicilor unui procesor. De exemplu: .286 .386 .486 permit utilizarea instruciunilor specifice acestor procesoare. .286P .386P .486P .586P permit utilizarea instruciunilor specifice acestor procesoare, plus instruciunile modului protejat. Pe lng acestea, se mai pot utiliza directivele ce specific utilizarea instruciunilor n virgul mobil specifice unui anumit tip de coprocesor matematic: .8087, .287 sau .387. Directivele care specific tipul de procesor (.8086, .286,. 386) permit (activeaz) n mod implicit i utilizarea instruciunilor coprocesor corespunztoare (8087, 287, 387). Singurul scop al directivelor coprocesor este acela de a permite execuia de instruciuni specifice unui coprocesor alturi de cele ale unui alt tip de procesor: 287 cu 8086 sau 186, sau instruciuni 387 cu instruciuni 8086, 186 sau 286. COMMENT Aceast directiv permite comentarii pe mai multe linii, n formatul urmtor: COMMENT [comentarii] [comnetarii .....] delimitator delimitator [comentarii]

[comentarii]

Delimitatorul este primul caracter diferit de spaiu, cum ar fi % sau + sau orice alt caracter ce urmeaz dup directiva COMMENT. Comentariile se termin pe linia pe care apare cel de-al doilea delimitator: COMMENT este un comentariu pe mai multe $ linii $ acesta

Exemplu de utilizare a celor dou forme de declarare a segmentelor:

S scriem un program care afieaz un mesaj, utiliznd ambele forme de declarare a segmentelor. a) Forma complet de declarare a segmentelor: date segment mesaj db date ends cod segment assume cs:cod, ds:date, ss:stiva start: mov ax, date mov ds, ax mov dx, offset mesaj mov ah, 9 int 21h mov ax, 4c00h int 21h cod ends stiva segment word dw 10 dup (?) stiva ends end start b) word public data exemplu program 1a$ public code

word

; initializare registru segment ; pentru date DS ; initializare adresa mesaj in DX ; apel functia 9 DOS, de afisare ; a unui text, cu adresa data in DX ; revenire in DOS stack stack ; rezervare memorie pentru stiva

Forma simplificat de definire a segmentelor: .model .stack .data .code start: mov mov mov mov int mov int ax, @data ; initializare registru segment ds, ax ; pentru date DS dx, offset mesaj ; initializare adresa mesaj in DX ah, 9 ; apel functia 9 DOS, de afisare 21h ; a unui text, cu adresa data in DX ax, 4c00h ; revenire in DOS 21h small 10 mesaj db exemplu program 1b$

end

start

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

21. Iniializarea registrelor segment, asocierea segmentelor cu registrele.

Iniializarea registrelor segment


Registrele CS:IP sunt iniializate de SO (sistemul de operare) la ncrcar ea programului executabil n memorie pentru execuie astfel nct ele s conin adresa primei instruciuni ce trebuie executat din program. Aceast instruciune este etichetat i se specific prin intermediul directivei END: END [adresa_de_start] <adresa_de_start> este o adres sau expresie care specific prima instruciune executabil i care va iniializa coninutul registrului IP; acesta poate fi iniializat i cu pseudoinstruciunea ORG. Adresa de start este opional deoarece poate lipsi pent ru unele module de program (cele care conin date sau proceduri). CS va fi iniializat de SO cu prima adres de segment disponibil, iar IP cu offsetul, din cadrul segmentului, al primei instruciuni executabile. Pentru perechea de registre SS:SP care face referirea la stiv, iniializarea va fi executat de utilizator, dac se folosesc directive complete de segmentare i nu se specific tipul i clasa segmentului de stiv. Dac, ns, se utilizeaz directive simplificate sau directive complete, cu precizarea tipului i clasei stack, atunci cele dou registre vor fi iniializate automat (SP va fi iniializat cu dimensiunea segmentului de stiv, declarat n directiva .stack, sau rezervat n declararea complet a segmentului de stiv). Dac segmentul este declarat astfel: stiva segment dw 100 dup (?) ; se rezerva 100 cuvinte pt. stiva varf_stiva label word stiva ends atunci utilizatorul trebuie sa iniializeze cele dou registre: assume cs: seg_cod, ds: seg_date, ss: stiva ............. mov ax, seg_date ; initializare DS mov ds, ax mov ax, stiva ; initializare SS mov ss, ax mov sp, offset varf_stiva ; initializare SP ............. n ceea ce privete celelalte registre segment (DS, ES etc.), acestea trebuie iniializate explicit i ntotdeauna de ctre programator, conform directivei ASSUME (ca n exemplele anterioare). Asocierea segmentelor cu registrele Pseudoinstruciunea ASSUME Deoarece ntr-un program n limbaj de asamblare pot exista mai multe segmente, de diferite tipuri, asamblorul trebuie informat n legtur cu cele 4 segmente logice curente. Acest lucru se realizeaz cu pseudoinstruciunea ASSUME: ASSUME <reg_segment>:<segment>

unde <reg_segment> poate fi unul dintre registrele CS, DS, ES, sau SS, iar <segment> este numele unui segment sau grup de segmente care va fi adresat de registrul segment respectiv; segmentul mai poate fi precizat i de operatorul SEG, urmat de numele unei variabile sau numele unei etichete din segmentul respectiv: assume cs: code, ds: dgrup, es: SEG var_a, ss: SEG varf_stiva Pentru anularea unei astfel de asocieri se poate utiliza una din formele: assume <reg_seg> : NOTHING ; care anuleaza asocierea ; reg_seg la orice segment, facuta anterior assume NOTHING ; sau care anuleaza ; toate registrele.

asocierile

facute

pentru

De remarcat c ASSUME este o pseudoinstruciune pentru care nu se genereaz cod, rolul su fiind numai de a informa asamblorul cu privire la intenia programatorului. Asamblorul nu are nici un mecanism prin care s verifice dac ntr-adevr coninutul registrului segment este cel specificat n pseudoinstruciunea ASSUME. n schimb aceast pseudoinstruciune este utilizat de asamblor pentru a face referire la date i instruciuni. Cnd o instruciune face o referire la o variabil, fr prefix segment, asamblorul determin segmentul ce conine variabila i apoi examineaz pseudoinstruciunea ASSUME, pentru a determina registrul segment ce adreseaz acel segment. Asocierea dintre segmentul logic i registrul segment trebuie fcut nainte de a face referire la vreo informaie din segmentul logic; deoarece aceste referiri se fac, de regul, n segmentul de cod, directiva este plasat la nceputul segmentului de cod sau, dac se modific aceste asocieri, nainte de prima referire la date din segmentul respectiv. S considerm urmtoarele declaraii: data1 segment alfa beta data1 ends data2 segment var1 var2 data2 ends cod ; dw dw 0 100 db dw 5 25

segment assume cs:cod, ds:data1, es:data2 initializarea registrelor segment conform lui ASSUME start: mov ax, data1 mov ds, ax mov ax, data2 mov es, ax referiri la date mov bx, beta ; se va utiliza DS, beta data1 DS mov alfa, al ; alfa data1 din ASSUME DS

add ;

data_cs cod end ends start

var1, bx ; var1 data2 ES modificam continutul lui DS mov ax, cs mov ds, ax assume ds:cod mov data_cs, bx ; se va utiliza DS mov cs:data_cs, cx ; utilizare explicita a lui CS ................. dw 1000

Prefix segment Dac o referin la o variabil nu este acoperit de o directiv ASSUME, asamblorul poate fi informat n mod explicit asupra registrului segment al variabilei prin codificarea unui prefix segment de forma: reg_seg : instructiune (referinta) anterior variabilei respective. Sarcina iniializrii acestui registru segment revine, ca i n cazul anterior, utilizatorului. Cu toate c aceast construcie prezint avantajul c nu necesit directiva ASSUME, ea are dou dezavantaje: este valabil doar pentru o instruciune; n loc de ASSUME, prefixul segment trebuie precizat pentru fiecare referin la o variabil; erorile sunt uor de comis, deoarece se refer la un registru segment i nu la un nume de segment, i deci este mai uor de omis. Exemplu de utilizare: exemplu assume data_cs start:

exemplu end

segment cs: exemplu dw 1000 mov ax, seg rez mov es, ax mov ax, seg val1 mov ds, ax mov ax, data_cs add ax, ds: val1 mov es: rez, ax ....... ends start

; initializare registre segment ; ES si DS cu segmentele respective

; data_cs exemplu CS ; utilizare explicita a lui DS ; utilizare explicita a lui ES

Referine anonime Variabile la care se face referire sub forma: [bx],

[bp], word ptr [si], byte ptr [di], [bx].camp, sunt denumite referine anonime, deoarece nu este precizat numele variabilei din care s se poat determina segmentul cruia i aparin. n astfel de situaii, registrele segment utilizate pentru adresare sunt determinate n mod implicit pe baza unor reguli. 9.6. Reguli pentru determinarea registrului segment implicit Aceste reguli se refer la cazurile n care n instruciune nu apar referiri explicite la registrele segment (prefix de segment) sau nu apar nume de variabile din care s se poat deduce registrul segment care trebuie utilizat. Registrele segment utilizate implicit sunt pentru registrele de baz: SS pentru BP, DS pentru BX; pentru registrele index: DS pentru ambele registre index (DI,SI). n cazul n care instruciunea folosete i un registru de baz i unul index, atunci se va utiliza regula corespunztoare registrului de baz. Deci, n concluzie, ori de cte ori se utilizeaz registrul de baz BP, fr nume de variabil sau prefix segment, se va utiliza pentru adresare segmentul referit de SS; n caz contrar, se va utiliza segmentul referit de DS. Exemple de adresri: seg_date segment d1 dw 3 dup (3) d2 db 5 dup (5) seg_date ends cod segment assume cs:cod, ds:seg_date start: ...... mov bx, offset d2 mov al, [bx] ; utilizare implicita a registrului. DS mov bp, sp mov dx, [bp] ; utilizare implicita a registrului SS mov ax, es:[bp] ; utilizare explicita a registrului ES mov ax, d1[2] ; utilizare explicita a registrului DS mov ds:[bp+si], ax ; explicit DS mov si, offset d1 mov [si], dx ; utilizare implicita a registrului DS ........ cod ends end start

Instruciunile care lucreaz cu stiva (PUSH, POP, CALL, RET, INT, IRET) utilizeaz ntotdeauna SS:SP i nu pot fi prefixate. Instruciunile pe iruri utilizeaz ntotdeauna pentru irul destinaie registrul segment ES. Referinele anonime, care nu utilizeaz registrul segment DS pentru irul surs, considerat implicit de asamblor, necesit specificarea explicit nu numai a registrului segment utilizat, dar i tipul operanzilor: movs es:byte ptr [di], ss:[si] movs word ptr es:[di], ss:[si]

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

22. Grupuri de segmente.

Definirea i utilizarea grupurilor de segmente


Directiva GROUP Se poate utiliza directiva GROUP pentru a specifica c anumite segmente se afl n acelai segment fizic de memorie. Forma directivei este: <nume_grup> GROUP <lista_nume_segmente> <nume_grup> este numele grupului de segmente, ce va fi utilizat pentru a determina adresa de segment utilizat pentru referirea n cadrul grupului de segmente (segmentele componente se concateneaz, fiind adresate de acelai registru segment). <lista_nume_segmente> poate conine nume de segmente sau expresii de forma: SEG nume_variabila SEG nume_eticheta ntr-o astfel de list nu poate s apar numele unui alt grup. Numele grupului poate fi utilizat: pentru a iniializa un registru segment; ntr-o pseudoinstruciune ASSUME, pentru a preciza c toate segmentele din grup sunt acoperite de registrul segment: assume ds:dgrup mov ax, dgrup mov ds, ax
ca prefix operand, pentru a specifica utilizarea valorii de baz a grupului sau offsetul n cadrul acestuia, i nu valoarea de baz a segmentului, sau offsetul n cadrul segmentului:

mov dd

ax, offset dgrup:var1 dgrup:var2

; offsetul in grup ; adresa in cadrul grupului

Segmentele dintr-un grup nu sunt amplasate n mod obligatoriu n poziii succesive n memorie, n ordinea declarrii lor n directiva GROUP. Ordinea lor este determinat de parametrul clas i de ordinea declarrii segmentelor. Aceast directiv poate fi utilizat i pentru a permite apelul unor proceduri i referirea unor variabile din alte segmente, cu nume diferite, fr a utiliza apeluri de tip FAR: cod1 segment public extrn proc1: near cod1 ends cod2 segment public extrn proc2: near cod2 ends data1 segment extrn d1: byte data1 ends data2 segment

extrn data2 dgrup cgrup code ends

d2: word

code end

group data1, data2 group cod1, cod2, code segment public assume cs:cgrup, ds:dgrup start: mov ax, dgrup mov ds, ax ..... mov al, d1 ..... mov d2, ax ..... call proc2 ..... ends start

O astfel de grupare poate fi utilizat pentru generarea de programe executabile de tip .COM. O cutum de programare pentru urmrirea declarrii etichetelor i a variabilelor este de a crea fiiere INCLUDE, pentru fiecare modul de asamblare, care s conin declaraiile EXTRN pentru simbolurile declarate PUBLIC n ele. Aceste fiiere vor conine, pentru fiecare segment, directivele EXTRN urmate de lista variabilelor, i tipul lor.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

23. Setul de instruciuni.

Setul de instruciuni
Din motive descriptive, setul de instruciuni de la procesorul 286 este mprit n trei subseturi distincte: setul instruciunilor de baz; setul extins de instruciuni; setul de instruciuni de control sistem. Ierarhizarea seturilor de instruciuni prin aceast mprire ajut la clarificarea relaiilor dintre diferite procesoare din familia x86. PENTIUM III, 4 seturile de instruciuni pentru SSE i SSE2 PENTIUM setul de instruciuni MMX (date/ 64 bii) 80486 instruciuni n virgul mobil 80386 instruciuni pe 32 de bii 80286 instruciuni control sistem 80186 setul extins de instruciuni 8086 (88) instruciuni de baz Ierarhia seturilor de instruciuni Setul de instruciuni de baz cuprinde subsetul comun de instruciuni care se gsesc pe toate procesoarele din familia INTEL86, cum ar fi cele de transfer, aritmetice, logice, pe iruri, de transfer al controlului programului sau de control procesor. Setul extins de instruciuni const din acele instruciuni care se gsesc ncepnd de la procesorul 186, cum ar fi instruciunile pentru intrarea/ieirea din proceduri, structurate pe bloc (ENTER, LEAVE), validare parametri (BOUND) i cele de intrare/ieire pe bloc (INS/OUTS). Setul de instruciuni de control sistem const din instruciunile ce apar pentru prima dat la procesorul 286: instruciuni pentru controlul mecanismelor de administrare i protecia memoriei virtuale. La procesorul 386, instruciunile anterioare sunt extinse la 32 bii, dar mai apar i alte cteva noi instruciuni: extensie de semn (CWDE, CDQ), transfer cu extensie de semn (MOVSX, MOVZX), nmulire cu trei operanzi (destinaia putnd fi i un alt registru n afara celor prestabilite), modificare/testare/scanare pentru un bit, deplasare pe operand dublu, setare a unui octet, dac o condiie este ndeplinit. Toate instruciunile prezentate n continuare ca fiind executabile pe 386/ 486 sunt similare i se pot executa i pe procesoarele urmtoare, cele din familia Pentium.

Setul de instruciuni de baz Aceste instruciuni sunt grupate n ase tipuri, i anume: transfer date; aritmetice; operare pe bit (logice, deplasare, rotire); operare pe iruri; transfer control program; control procesor. Aproape fiecare instruciune poate opera fie pe octet, fie pe cuvnt (sau dublu cuvnt, la 386/486). Operanzii instruciunilor pot fi interschimbabili, cu excepia datelor imediate care pot fi numai surs, nu i destinaie. Variabilele din memorie pot fi operate direct n memorie, fr s fie mutate n registre. Setul de instruciuni poate fi considerat ca avnd dou niveluri: nivel de asamblare i nivel main. Pentru programatorul n limbaj de asamblare, procesorul apare ca avnd circa o sut de instruciuni. O instruciune n limbaj de asamblare (de ex. MOV) corespunde, de fapt, la mai multe forme de instruciuni main (pt. MOV sunt circa 30 de tipuri, n funcie de tipul operandului: octet/cuvnt, registru/memorie, dat imediat etc.). La nivel main exist circa trei sute de instruciuni. Instruciunile nivelului de asamblare simplific viziunea programatorului asupra setului de instruciuni: programatorul scrie instruciunea (de ex. INC, de incrementare a unui operand 8/16 bii, registru sau locaie de memorie), asamblorul examineaz operandul i determin instruciunea nivel main ce trebuie generat.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

24. Instruciuni de transfer, aritmetice, de prelucrare la nivel de bit.

Instruciuni de transfer date.


- instruciuni de transfer cu scop general ("clasice"); - instruciuni specifice acumulatorului; - instruciuni de transfer adrese obiect; - instruciuni de transfer registru indicatori. Instruciuni de transfer cu scop general MOV <dest>,<sursa> MOV <reg>,<reg> MOV <reg_16>,<reg_seg> MOV <reg_seg>,<reg_16> Exemple de instruciuni: mov ax,bx mov al,ch mov ax,cs mov ds,ax - registrul segment (reg_seg) CS nu poate fi destinaie; MOV <reg>,<mem> MOV <mem>,<reg> Exemple de instruciuni: mov vector[bx][si],ax ; vector este de tip word mov sp,varf_stiva mov bl,byte ptr vector[bp][di] Nu se pot transfera date direct ntre dou locaii de memorie. MOV <reg_seg>,<mem_16> MOV <mem_16>,<reg_seg> mov ds,adr_baza_seg mov [bx].salv_seg,cs - CS nu poate fi destinaie. MOV <reg>,<data_imed> MOV <mem>,<data_imed> mov ax,0 mov cl,4 mov byte ptr [si],2ch mov alfa[bp][si],100 - instruciunea nu se poate executa cu registrele segment. Instruciuni de conversie (extensie de semn) realizeaz extensia de semn a acumulatorului (AL, AX, EAX) n extensia sa (AH, DX sau EAX, EDX). Nu se modific nici un indicator. CBW (Convert Byte to Word) CWDE (Convert Word to Double word Extended) CWD (Convert Word to Double word) CDQ (Convert Double word to Quad word) La 386/486 transfer cu extensia bitului de semn sau de zerouri: MOVSX <dest>,<sursa> (MOVe with Sign eXtension)

Destinaia poate fi un reg 16/32 bii, iar sursa reg/mem 8/16 bii. MOVSX reg_16,reg/mem_8 MOVSX reg_32,reg/mem_8 MOVSX reg_32,reg/mem_16 Nu este afectat nici un indicator. MOVZX <dest>,<sursa> (MOVe with Zero eXtension) Instruciuni de interschimbare a datelor XCHG <dest>,<sursa> (eXCHanGe) (temp) (destinaie), (destinaie) (surs), (surs) (temp) XCHG <reg>,<reg> XCHG <reg>,<mem> XCHG <mem>,<reg> Dac unul dintre operanzi este din memorie, atunci procesorul activeaz, n mod automat semnalul LOCK\, pentru a asigura accesul exclusiv la memorie pentru un singur procesor, ntr-o structur multiprocesor. Exemplu: s inversm, ntre ei, octeii dintr-un ir de cuvinte. .model small .data mesajdw 'Ex','em','pl','u ','pr','og','ra','m ','2$' lung_mesaj equ ($-mesaj)/2 linie_noua db 0dh,0ah,'$' .code start: mov ax,@data ; iniializare registru segment DS mov ds,ax ; cu adresa segmentului de date lea dx,mesaj ; tiprim mesajul sub forma iniial mov ah,9 ; utiliznd funcia 9, din DOS : int 21h ; "xEmelp urpgora m" lea dx,linie_noua ; se trece pe o linie noua mov ah,9 int 21h ; pentru a aduce mesajul la forma dorit trebuie inversai ; octeii, fiecrui cuvnt ntre ei lea si,mesaj mov cx,lung_mesaj iar: mov ax,[si] ; se ia cte un cuvnt xchg al,ah ; i se inverseaz octeii mov [si],ax ; se depune la aceeai adres add si,type mesaj ; se actualizeaz adresa curent loop iar ; i se continu pentru tot irul ; se tiprete mesajul astfel obinut lea dx,mesaj mov ah,9 ; se va tipri mesajul: int 21h ; 'Exemplu program 2' mov ax,4c00h ; revenire DOS int 21h

end start BSWAP <dest> (Byte SWAP) care schimb ntre ei octeii operandului destinaie, care nu poate fi dect un registru de 32 de bii. Octeii sunt interschimbai astfel: primul octet cu ultimul i al doilea cu al treilea. Altfel spus instruciunea convertete o valoare de 32 de bii de la formatul micul indian la marele indian, care sunt formate de memorare a datelor reprezentate pe mai muli octei. Instruciuni de transfer cu stiva - salvarea / refacerea adresei de revenire pentru apel/ntreruperi; administrarea stivei pentru astfel de operaii este fcut, n mod automat, de ctre procesor; - salvarea / refacerea coninutului unor resurse (registre, memorie etc.) la intrarea ntr-o procedur, respectiv la ieirea din aceasta; - pentru transferul parametrilor de intrare / ieire ntre o procedur i programul apelant, precum i pentru alocarea dinamic de memorie. PUSH <sursa> - depune n vrful stivei <sursa>. (SP) (SP) - 2 ((SP)+1:(SP)) (sursa) Operandul surs poate fi registru, memorie de 16 bii, sau o dat imediat. Dac data imediat este octet, ea este extins, cu semn, la o valoare de tip cuvnt. Exemple: push si push cs push beta[bx][si] POP <dest> - extrage din vrful stivei i duce la dest. (dest) ((SP)+1:(SP)) (SP) (SP) + 2 Exemple: pop bx pop ds; cs nu poate fi destinaie pop beta[bp][di] Informaiile din stiv vor fi extrase n ordinea invers celei n care au fost introduse: ; salvm registrele: ax, bx, cx push ax push bx push cx ; refacem aceleai registre cu aceleai valori: pop cx pop bx pop ax Accesul la informaia din stiv se poate face, fr descrcarea stivei, utiliznd adresarea bazat, astfel: ; memorare informaii n stiv: mov bp,sp ; memorare "vrful" stivei push ax ; se va depune la adresa [bp-2] push bx ; [bp-4] push cx ; [bp-6] ; accesul la informaii se poate face, cu BP, n orice ordine mov ax,[bp-2]

mov bx,[bp-4] mov cx,[bp-6] ; descrcarea stivei se poate face modificnd valoarea lui SP add sp,6 ; depunerea de parametrii n stiv, nainte de apelul procedurii: push ax push bx push cx ; preluarea parametrilor din stiv, n cadrul procedurii: ; (s-a fcut abstracie, n acest exemplu, de salvarea, din stiv, a adresei de revenire ; i de parametrii, eventual, transmii prin stiv) push bp mov bp,sp mov ax,[bp+6] mov bx,[bp+4] mov cx,[bp+2] ; descrcarea stivei i refacerea registrului BP, salvat : pop bp add sp,6 PUSHA permite salvarea registrelor: AX, CX, DX, BX, SP, BP, SI, DI POPA care reface aceleai registre, bineneles n ordinea invers. La procesorul 386/486 salvarea i refacerea se face cu instruciunile: PUSHAD, POPAD pentru registrele de 32 bii (EAX, ECX, ..., EDI), n aceeai ordine. Pentru ambele tipuri de instruciuni de refacere n bloc a registrelor, registrul SP (respectiv ESP) nu va prelua din stiv valoarea salvat anterior execuiei instruciunii POPA/POPAD. n final coninutul registrului SP (ESP) va crete cu 16 (32). Instruciuni de transfer specifice acumulatorului Aceste instruciuni permit transferul de date ntre registrul acumulator (AL, AX sau EAX) i portul de I/O, din spaiul de I/O, specificat ca operand. Specificarea portului se poate face direct n instruciune, pe 8 bii, iar pentru adrese mai mari se folosete adresarea indirect prin DX. IN <acc>,<port> OUT <port>,<acc> Exemple: in al,port_oct out port_oct,al in ax,port_cuv out port_cuv,ax in eax,port_dcuv out port_dcuv,eax in al,dx out dx,al in ax,dx out dx,ax in eax,dx out dx,eax n principiu fiecrui periferic i sunt asociate porturi pentru: - citirea strii dispozitivului; - transmiterea comenzii ctre periferic;

- realizarea transferului propriu-zis. INS <dest>,DX OUTS DX,<sursa> (INput from port to String ; OUTput String to port) Aceste instruciuni transfer date la/de la un port de I/O. Operandul de memorie, dac este surs este referit de DS:(E)SI, iar dac este destinaie este referit de ES:(E)DI; selecia ntre registrele de 16 sau 32 de bii (ESI sau SI, respectiv EDI sau DI) se face n funcie de atributul de dimensiune de adres. INSB / INSW / INSD OUTSB / OUTSW / OUTSD XLAT - instruciune de transfer dintr-o tabel de octei, sau de transfer de octet, de la un cod la altul: (AL) ((BX) + (AL)) Coninutul acumulatorului este nlocuit de un octet dintr-o tabel. Adresa de nceput a tabelei se afl, n prealabil, n BX. Coninutul registrului AL este considerat ca adres relativ n aceast tabel de conversie (translaie). Valoarea corespunztoare din tabel (de tip octet) este mutat n AL. Referirea la o adres, n instruciunea XLAT, este necesar pentru a permite asamblorului s determine registrul segment care va fi utilizat la execuia instruciunii (registrul BX conine numai adresa relativ n cadrul segmentului din care face parte tabela de conversie): XLAT [adr_tabela], XLAT [[rs:] adr_tabela] sau XLATB putere db 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, , 225 mov bx, offset putere mov al, 9 xlat putere ; conversie din binar n hexa (ASCII) ; (AL) conine o valoare n intervalul 0-15 conv proc near lea bx,tabela_conversie xlat cs:tabela_conversie; sau xlat cs:[bx] ret conv endp tabela_conversie label byte db '0123456789ABCDEF' Programul citete de la tastatur codul ASCII al unei taste i afieaz acest cod (sub forma a dou cifre hexa). seg_date segment tab_conv db '0123456789ABCDEF' mesaj db '-are codul ASCII-' tasta db 2 dup (?), 0dh,0ah,'$' seg_date ends seg_cod segment assume cs : seg_cod, ds : seg_date start: mov ax,seg_date mov ds,ax

mov ah,1 ; citire cu ecou a unei taste int 21h ; fr ecou este funcia 8 mov ah,al ; salvare cod tast lea bx,tab_conv ; iniializare BX, pentru XLAT and al,0fh ; se reine doar a doua tetrad xlat tab_conv ; codul ASCII al acestei tetrade mov tasta+1,al ; este cea de-a doua cifr a codului mov al,ah ; codul iniial al tastei mov cl,4 ; contor numr de deplasri la dreapta shr al,cl ; deplasare logic la dreapta cu 4 bii xlat tab_conv ; conversia primei tetrade mov tasta,al ; codul ASCII al primei tetrade lea dx,mesaj mov ah,9 ; se tiprete codul tastei int 21h mov ax,4c00h ; revenire DOS int 21h seg_cod ends end start pentru caracterele 'obinuite' din setul ASCII de baz (0127): cod de scanare + codul ASCII (0127); setul ASCII extins (128255), 'ALT' + taste numerice,: cod scanare + codul ASCII (extins) ; pentru tastele speciale (funcionale, de deplasare, 'CTRL', 'insert', 'delete' etc.), se transmite: cod scanare + 0 ; Pentru utilizarea funciilor tastaturii se poate apela INT 16h, cu urmtoarele funcii (aceast valoare se ncarc n AH): - 0, citire caracter (AL=cod ASCII, AH=cod scanare); - 1, test caracter disponibil, i returneaz n ZF=0, dac este caracter disponibil n AX, ZF=1, dac nu este caracter disponibil; - 2, citirea strii tastelor de tip "shift", care este returnat n AL (acesta este memorat i la adresa 40h:17h). Instruciuni de transfer adrese LEA <dest_reg>,<sursa_mem> (Load Effective Address) lea bx, adr_tab este echivalent cu: mov bx, offset adr_tab dar instruciunea: lea si, adr_tab[bx][di] nu are un echivalent direct, care s utilizeze o singur instruciune, ci o secven de instruciuni: mov si, offset adr_tab add si, bx add si, di La procesoarele 386/486 destinaia i/sau sursa pot fi i de 32 bii. Pot apare, ns situaiile:

LEA <reg_16>,<mem_32> LEA <reg_32>,<mem_16> LDS <dest_reg_16>,<sursa_mem_32> (Load pointer using DS) LES <dest_reg_16>,<sursa_mem_32> (Load pointer using ES) Exemple: 1) sir db ....... adr_sir dd sir lds si,adr_sir 2) octeti db 20 dup (?) ptr_oct dw offset octeti dw seg octeti les di, dword ptr ptr_oct 3) ptr_1 dd 1a2b3d4ch adr_w dw 1234h, 0abcdh ptr_2 equ <dword ptr adr_w> les di, ptr_1 ; (ES) = 1a2bh, (DI) = 3d4ch lds si, ptr_2 ; (DS) = 1234h, (SI) = 0abcdh La 386/486 mai pot fi executate instruciunile: LFS / LGS / LSS < reg_16/32 >, < mem_16:16/32 > Instruciuni de transfer indicatori LAHF (Load AH from Flags) (AH) (SF, ZF, *, AF, *, PF, *, CF) SAHF (Store AH into Flags) (SF, ZF, *, AF, *, PF, *, CF) (AH) PUSHF (PUSH Flags) (SP) (SP) - 2 ((SP)+1:(SP)) Indicatori (flags) POPF Indicatori ((SP)+1:(SP)) (SP) (SP) + 2 Instruciunile PUSHF i POPF permit unei proceduri s salveze i s restaureze indicatorii programului ce o apeleaz. De asemenea numai utiliznd aceste instruciuni se poate modifica starea lui TF, pentru care nu exist o instruciune dedicat. Modificarea se poate realiza astfel: pushf ; se pun indicatorii n stiv push bp ; salvare registru (BP) mov bp,sp ; se ncarc vrful stivei n (BP) or word ptr [bp+2], 0100h ; se pune imaginea din stiv a lui (tf) pe 1 pop bp ; refacere (BP) popf ; i se extrage n indicatori valoarea 1 pentru (tf) n stiv, la apariia ntreruperii SS (INT 1), se salveaz: indicatorii i adresa de revenire (segment + offset). Presupunnd c stiva a fost adus la forma iniiala, tergerea lui TF se poate face astfel: push bp ; salvare (BP) mov bp,sp ; se ncarc vrful stivei n (BP)

and din stiv pop iret

word ptr [bp+6], 0feffh ; pune (tf) pe 0, n imaginea bp ; refacere (BP) ; revenire din procedura single-step

Instruciuni Aritmetice
Formatul datelor aritmetice Operaiile aritmetice pot fi efectuate pe patru tipuri de numere: - ntregi (binare:) - fr semn; - cu semn; - zecimale: - nempachetate; - mpachetate; (ambele fr semn).
Forma Numere binare Numere zecimale binar fr semn cu semn nempachetat mpachetat 07 H 0000 0111 B 7 +7 7 7 89 H 1000 1001 B 137 - 119 invalid 89 C5 H 1100 0101 B 197 - 59 invalid invalid Hexa

Numerele binare ntregi pot fi de 8 sau 16 bii, iar la 386/486 i de 32. Numerele ntregi cu semn sunt reprezentate n complement fa de doi. Numerele zecimale (BCD) sunt memorate n octei: - dou cifre pe un octet, la formatul zecimal mpachetat; - o cifr pe un octet, la formatul zecimal nempachetat. Procesorul consider, ntotdeauna, c operanzii specificai n instruciunile aritmetice conin date ce reprezint numere valide pentru tipul instruciunii ce trebuie executat. Date incorecte vor conduce la rezultate neprevzute. Sunt definite operaiile de nmulire i mprire, specifice tipului de date binar cu semn, iar operaiile de adunare i scdere sunt realizate cu instruciunile pentru numere binare fr semn. Dac pentru numere fr semn depirea este detectat de indicatorul CF, pentru numere cu semn aceasta este detectat de indicatorul OF. Pentru determinarea depirii se pot utiliza instruciunile de salt condiionat, pentru CF sau OF, dup operaia respectiv. Operaiile aritmetice cu numere zecimal nempachetat se realizeaz n dou etape. Operaiile de adunare, scdere i nmulire, de la numere binare fr semn, furnizeaz un rezultat intermediar n AL, care apoi n a doua etap este ajustat la o valoare corect, de numr zecimal nempachetat. mprirea se face n mod asemntor, cu excepia ajustrii care este realizat prima, asupra operandului numrtor, n registrul AL, i apoi se realizeaz mprirea binar fr semn; dac rezultatul nu este corect mai poate urma o a treia etap de ajustare final. Operaiile de adunare i scdere pt. nr. zec. mpach. se realizeaz n dou etape, la fel ca la numerele zecimal nempachetate: instr. respectiv (+, -), va furniza un rezultat n AL; corecia rezultatului din AL la formatul zec. mpachetat.

Nu exist instruciuni de ajustare pentru operaiile de nmulire sau mprire cu astfel de numere (zec. mpachetat). Indicatorii, dup execuia unei instruciuni aritmetice pot fi: modificai, conform rezultatului; nemodificai, deci vor rmne la valoarea avut anterior acestei instruciuni; nedefinii, adic sunt modificai de instruciunea respectiv, dar nu reflect starea rezultatului. Aceste instruciuni pot opera pe date din memorie sau registre, dar nu pot fi din registre segment, dar nu pot avea ambii operanzi din memorie. Operandul surs poate fi i o dat imediat.

Instruciunile de adunare / scdere ADD <dest>,<surs> (ADDition) (dest) (dest) + (sursa) Modific: OF, SF, ZF, AF, PF, CF ADC <dest>,<surs> (ADdition with Carry flag) (dest) (dest) + (sursa) + (CF) Modific: OF, SF, ZF, AF, PF, CF INC <dest> (INCrement) (dest) (dest) + 1 Modific: OF, SF, ZF, AF, PF; Nu modif. CF ; AAA (ASCII Adjust for Addition) modific AL la un numr zecimal nempachetat corect, astfel: if ((AL) & 0FH) > 9 or (AF)=1 then (AL) (AL) + 6; (AH) (AH) + 1; (AF) 1; (CF) 1; (AL) (AL) & 0FH else (CF) 0; (AF) 0 Modific: AF, CF; Nedefinii: OF, SF, ZF, PF.

DAA

(Decimal Adjust for Addition) modific AL la un numr zecimal mpachetat astfel: if ((AL) & 0FH) > 9 or (AF)=1 then (AL) (AL) + 6; (AF) 1 else (AF) 0; if ((AL) > 9FH) or (CF)=1 then (AL) (AL) + 60H; (CF) 1 else (CF) 0; Modific: SF, ZF, AF, PF, CF; Nedefinit: OF. De la procesorul 486 se mai poate executa i instruciunea: XADD <dest>,<sursa> (eXchange and ADD)

SUB <dest>,<surs> (dest) SBB <dest>,<surs> (dest) DEC <dest> (dest) NEG <dest>

(SUBtraction) (dest) - (sursa); Modif: OF, SF, ZF, AF, PF, CF (SuBtraction with Borrow) (dest) - (sursa) - (CF); M: OF, SF, ZF, AF, PF, CF (DECrement) (dest) - 1; Modific: OF, SF, ZF, AF, PF; NU: CF ;

determin complementul fa de doi al destinaiei: (dest) compl'2 (dest) { (dest) 0 - (dest) }; Modific: OF, SF, ZF, AF, PF, CF Dac operandul este zero el rmne neschimbat i CF=0. Pentru toate celelalte numere CF=1. Dac se complementeaz cel mai mic numr negativ (de ex. -128 sau -32268), operandul nu se va modifica dar OF=1. CMP <dest>,<sursa> poziioneaz toi indicatorii pentru operaia: (dest) - (sursa) De obicei dup o astfel de instruciune urmeaz un salt condiionat. AAS (ASCII Adjust for Subtraction) if ((AL) & 0FH) > 9 or (AF)=1 then (AL) (AL) - 6; (AH) (AH) - 1; (AF) 1; (CF) 1; (AL) (AL) & 0FH else (CF) 0; (AF) 0 Modific: AF, CF; Nedefinii: OF, SF, ZF, PF. (Decimal Adjust for Subtraction) if ((AL) & 0FH) > 9 or (AF)=1 then (AL) (AL) - 6; (AF) 1 else (AF) 0; if ((AL) > 9FH) or (CF)=1 then (AL) (AL) - 60H; (CF) 1 else (CF) 0; Modific: SF, ZF, AF, PF, CF; Nedefinit: OF.

DAS

add_data segment numar_1 dw 0a8adh, 7fe2h, 0a876h,0 lung_nr1 equ ($ - numar_1)/2 numar_2 dw 0cdefh, 52deh, 378ah, 0 add_data ends multibyte_add segment assume cs: multibyte_add, ds: add_data

start: mov mov mov clc bucla:

mov ax, add_data ; iniializarea reg. DS ds, ax ; cu adresa de segment cx, lung_nr1 ; contor lungime numr si, 0 ; iniializare index elemente ; (CF)=0, transportul iniial

mov ax, numar_2[si] adc numar_1[si], ax inc si ; actualizare index element inc si loop bucla mov ax, 4c00h ; revenire n DOS int 21h multibyte_add ends end start Programul adun dou numere, fr semn, reprezentate pe mai multe cuvinte (octei), dar de lungimi diferite, iar rezultatul se va depune peste numrul mai lung. add_data_2 segment primul dw 0a8adh, 7fe2h, 0a876h,0 lung_1 dw ($ - primul)/2 al_doilea dw 0fedch, 0abcdh, 0cdefh, 52deh, 5678h, 0 lung_2 dw ($ - al_doilea)/2 add_data_2 ends multi_add_2 segment assume cs: multi_add_2, ds: add_data_2 start: mov ax,add_data_2 mov ds,ax ; se determin cel mai mare numr, unde se pune rezultatul ; vom considera c (BX)= adresa numrului mai lung ; (DX)= dimensiunea numrului mai lung ; (BP)= adresa numrului mai scurt ; (CX)= dimensiunea acestuia ; numrul de octei ai numrului mai mic va controla bucla_1 ; n care ambele numere au cuvinte ce trebuie adunate ; diferena dimensiunilor celor dou numere va controla bucla_2 ; necesar dac apare transport, pentru propagarea acestuia mov dx,lung_2 ; presupun, iniial numrul al lea bx,al_doilea ; doilea mai mare mov cx,lung_1 lea bp,primul cmp dx,cx ; verific presupunerea fcut jge num2_mai_mare ; dac e respectat se continu xchg bx,bp ; dac nu se schimb ntre ele coninutul

xchg cx,dx ; perechilor de registre, respective num2_mai_mare: sub dx,cx ; determin diferena dintre lungimile lor clc ; (CF)=0 mov si,0 ; se iniializeaz indexul elementelor bucla_1: mov ax,ds:[bp][si] adc [bx][si],ax inc si ; actualizare index inc si loop bucla_1 ; (CX)=contor pentru adunare mov cx,dx ; contor pentru propagarea transportului bucla_2: jnc gata ; dac nu mai este transport de propagat adc word ptr [bx][si],0 inc si inc si loop bucla_2 ; trebuie testat (CF), i dac avem transport, adic se ; depete dimensiunea iniial a numrului mai lung, ; transportul trebuie memorat la adresa urmtoare, ; dac s-a rezervat spaiu, sau semnalat depirea: jc eroare . . . gata: mov ax,4c00h int 21h multi_add_2 ends end start ; (DI) = va conine extensia de semn a numrului mai scurt num2_mai_mare: push cx ; salvare lungime numr mai scurt mov di,0 ; extensie de semn pentru numr pozitiv mov si,bp ; adresa de nceput a numrului mai scurt shl cx,1 ; lungimea * 2 = numr octei ai numrului add si,cx ; se poziioneaz pe primul element sub si,2 ; care conine bitul de semn mov ax,[si] ; i i testm bitul de semn cmp ax,0 ; dac este pozitiv se continu cu valoarea jp cont ; iniial pentru (di)=0 mov di,0ffffh ; altfel (di)=ffffh, extensie semn numr negativ cont: pop cx ; refacerea contorului sub dx,cx ; determin diferena dintre lungimile lor clc ; (CF)=0 mov si,0 ; se iniializeaz indexul elementelor bucla_1: mov ax,ds:[bp][si] adc [bx][si],ax inc si ; actualizare index

inc si loop bucla_1 ; (CX)=contor pentru adunare mov cx,dx ; contor pentru propagarea transportului bucla_2: adc word ptr [bx][si],di ; i a semnului numrului mai scurt inc si inc si loop bucla_2 ; n acest punct se testeaz OF pentru a detecta o depire ; a dimensiunii iniiale a numrului mai lung 4) S rezolvm aceeai problem (1) pentru dou numere zecimal mpachetate, de aceeai lungime, iar rezultatul s se depun la alt adres. mov si,0 mov cx,numar_octei clc reia_adunare: mov al,primul[si] adc al,al_doilea[si] daa mov rezultat[si],al inc si loop reia_adunare 5) Complementarea unui numr reprezentat pe mai multe cuvinte. complement fa de 2 pentru numr = 2n - numr; mov cx,lung_numar ; contor numr cuvinte clc ; iniializare transport cu 0 compl: mov ax,0 ; echivalentul lui 2n sbb ax,numar [si] ; se efectueaz scderea, cu propagarea mprumutului mov numar[si],ax ; se depune rezultatul inc si ; actualizare index cuvnt urmtor inc si loop compl Dac numrul iniial este valoarea minim negativ (80 00 . . .00H), dup complementare valoarea va fi aceeai. .model small .stack .data numar db 23h, 45h, 80h lung_numar equ $-numar mes_dep db 'Depasire compl2 (numar minim negativ)', 0dh, 0ah, '$' .code mov ax, @data mov ds, ax

mov cx, lung_numar ; contor numr octei mov si, 0 ; index la octetul curent compl2: neg numar[si] ; complementare fa de 2 inc si ; actualizare index pentru octetul urmtor jc gasit_bit_unu ; pn la prima unitate loop compl2 ; dac nu s-a gsit primul 1 se reia compl2 jmp gata ; dac se execut jmp operandul a fost 0 gasit_bit_unu: dec cx ; actualizare contor jcxz gata ; dac a fost ultimul octet, s-a terminat operaia compl1: not numar[si] ; se continu cu complementarea fa de 1 inc si loop compl1 gata: cmp numar[si-1], 80h jne quit lea si, numar ; test depire pentru 80.00. . . 00h mov cx, lung_numar mov al, [si] ; se face OR ntre toi octeii rezultatului inc si ; i dac este 80H -> depire compl2 dec cx ; pentru valoarea minim negativ jcxz gata_or test_dep: or al, [si] inc si loop test_dep gata_or: cmp al, 80h jne quit lea dx, mes_dep mov ah, 9 int 21h quit: mov ax, 4c00h int 21h end Instruciunile de nmulire / mprire MUL <sursa> ; MUL <acumulator>, <sursa> <sursa> * <AL, AX sau EAX> rezultat: (AX), (DX, AX), (EDX, EAX). Depire OF=CF=1, altfel OF=CF=0. Ceilali indicatori sunt nedefinii (SF, ZF, AF, PF). mov al,op1_octet ; nmulitorul de tip octet

mov ah,0 ; se extinde nmulitorul la cuvnt, fr semn mul op2_cuv ; se realizeaz nmulirea IMUL <sursa> ; IMUL <acumulator>, <sursa> IMUL r_16, r/m_16 IMUL r_16, r/m_16, data_8 IMUL r_32, r/m_32 IMUL r_32, r/m_32, data_8 IMUL r_16, data_8 IMUL r_16, r/m_16, data_16 IMUL r_32, data_8 IMUL r_32, r/m_32, data_32 IMUL r_16, data_16 IMUL r_32, data_32 AAM (Ascii Adjust for Multiply) (AH) (AL)/0AH (AL) (AL) mod 0AH Modific: SF, ZF, PF; Nedefinii: OF, AF, CF < sursa > sau DIV < acc >,< sursa > (temp) (numrtor) / (numitor) if (temp) > MAX then (ct), (rest) - nedefinii (SP) (SP) - 2; ((SP)+1:(SP)) indicatori; 0; (SP) (SP) - 2; ((SP)+1:(SP)) (CS); (CS) (2) (SP) (SP) - 2; ((SP)+1:(SP)) (IP); (IP) (0) else (ct) (temp) (rest) (numrtor) mod (numitor) MAX = FFH/octet, FFFFH/cuv., FFFFFFFFH/dublu cuv. al,num_octet ; operand octet mov ah,0 ; extensia dempritului/ cbw div divizor_octet ; idiv mov ax,num_cuvant ; operand cuvnt div divizor_octet ; idiv mov ax,num_cuvant ; operand cuvnt mov dx,0 ; extensia dempritului/ cwd div divizor_cuvant ; idiv mov eax,cuvant_dublu ; operand dublu cuvnt mov edx,0 ; extensie a dempritului n (EDX) div divizor_dublu_cuvant ; idiv

DIV

(tf),

(if)

mov

IDIV < sursa > sau IDIV < acc >,< sursa > la 386/486. if (temp) / (numitor) > MAX or (temp) / (numitor) < -MAX 1 ...... Constanta MAX are valorile: 7FH, 7FFFH i 7FFFFFFFH pentru cturi pozitive, i 80H, 8000H, 80000000H cele negative.

AAD

(ASCII Adjust for Division) (AL) (AH) * 0AH + (AL) (AH) 0 Indicatori: modific SF, ZF, PF, ceilali nedefinii: OF, CF, AF. mov al,7 ; nmulire 7 * 7 mov cl,7 mul cl ; se obine (ah,al) = (0h, 31h) aam ; corecie (ah,al) = (04h, 09h) mov ah,8 ; demprit 89 mov al,9 ; aad ; corecie demprit zecimal la binar mov bl,4 ; mpritor 4 div bl ; rezultat (ah,al) = (01h, 16h) mov dh,ah ; se salveaz restul (dh) = 01h aam ; corecie (ah,al) = (02h, 02h) Afiare AL n zecimal (AL<100) aam ; corecie la format BCD: ah = cifra zeci add ax,3030h ; al = cifra uniti. Conversie la ASCII mov dx,ax ; se salveaz codurile ASCII ale cifrelor xchg dh,dl ; se depune n (dl) cod ASCII pt. cifra zeci mov ah,2 ; se apeleaz funcia 2 din DOS int 21h ; de tiprire a caracterului din (dl) xchg dh,dl ;se depune n (dl) cod ASCII cifra uniti mov int ah, 2 21h

Afiarea n zecimal a coninutului registrului AX: ; (AX) conine o valoare care este n intervalul 065535 ; dac se mparte numrul la 100 se obine ca prim rest ; o valoare ce conine ultimele dou cifre (zeci, uniti) ; dac se mparte ctul anterior din nou la 100 se va obine ; o valoare ce conine urmtoarele dou cifre (mii, sute) ; iar acest ultim rest va avea valoarea primei cifre ; a zecilor de mii, care este n intervalul: 0 - 6. mov bx,100 ; mpritor mov dx,0 ; extensie semn demprit pozitiv div bx ; dx = ultimele 2 cifre (zeci, uniti) mov cx,dx ; ax = primele 3 cifre, cx = ultimele 2 cifre mov dx,0 ; extensie semn demprit pozitiv div bx ; dx = cifrele: mii, sute; ax = zeci de mii push dx ; se salveaz dx deoarece va fi modificat add al,30h ; se tiprete cifra zecilor de mii(06) mov dl,al ; caracterul de tiprit n DL mov ah,2 ; se apeleaz funcia 2 din DOS int 21h ; care tiprete caracterul din (DL)

pop aam add mov xchg mov int xchg mov int mov aam add mov xchg mov int xchg mov int

ax ax,3030h dx,ax dh,dl ah,2 21h dh,dl ah,2 21h ax,cx ax,3030h dx,ax dh,dl ah,2 21h dh,dl ah,2 21h

; se iau din stiva valoarea pt. mii, sute ; conversie la format zecimal nempachetat ; conversie la cod ASCII ; se salveaz cele dou cifre ; se tiprete cifra miilor ; se tiprete cifra sutelor ; ultimele dou cifre: zeci, uniti ; conversie la format zecimal nempachetat ; conversie la cod ASCII ; se salveaz cele dou cifre ; se tiprete cifra zecilor ; se tiprete cifra unitilor

Pentru a tipri valoarea din (AX) cu semn se va testa primul bit din AX, care reprezint semnul i se tiprete. Dac numrul este negativ se va complementa fa de 2, dup care programul este acelai ca n exemplul anterior. cmp ax,0 ; test semn mov bx,ax ; salvare valoare jns cont ; dac e pozitiv se continu mov dl,- ; se tiprete semnul mov ah,2 int 21h mov ax,bx ; refacere numr neg ax ; complementare (transformare n pozitiv) cont: .........

Instruciuni de prelucrare la nivel de bit


- instruciuni logice (NOT, AND, OR, XOR, TEST etc.); - instruciuni de deplasare (SHL, SAL, SHR, SAR etc.); - instruciuni de rotire (ROL, ROR, RCL, RCR); Instruciuni logice OF i CF 0; AF - nedefinit; SF, ZF, PF - sunt poziionai conform rezultatului instruciunii. NOT <dest> Nu afecteaz nici un indicator. AND <dest>, <sursa> (dest) (dest) and (sursa) OR <dest>, <sursa> (dest) (dest) or (sursa)

XOR <dest>, <sursa> (dest) (dest) xor (sursa) TEST <dest>, <sursa> Poziioneaz indicatorii pentru operaia (dest) and (sursa), fr a modifica nici un operand. Instruciuni de testare i modificare de bit. Bitul testat este specificat prin deplasamentul su (al doilea operand, dat de 8 bii sau reg_16/32) fa de bitul cel mai puin semnificativ al destinaiei (reg/mem_6/32). Ceilali indicatori sunt nedefinii. BT <dest>, <poziie> (Bit Test) (CF) Bit (dest, poziie) BTS <dest>, <poziie> (Bit Test and Set) (CF) Bit (dest, poziie), Bit (dest, poziie) 1 BTR <dest>, <poziie> (Bit Test and Reset) (CF) Bit (dest, poziie), Bit (dest, poziie) 0 BTC <dest>, <poziie> (Bit Test and Complement) (CF) Bit (dest, poziie), Bit (dest, poziie) Not (Bit (dest, poziie)) Instruciuni de scanare pe bit. Aceste instruciuni permit scanarea biilor din cel de-al doilea operand direct, ncepnd cu bitul mai puin semnificativ (forward) sau invers (reverse), pentru a determina primul bit egal cu 1. Dac toi biii sunt zero ZF=1, altfel ZF=0, i registrul destinaie va reine indexul primului bit 1 din operandul surs (reg/mem de aceeai dimensiune cu reg. Dest.). Modif. ZF, iar toi ceilali sunt nedefinii. - scanare direct: BSF <dest>, <sursa> (Bit Scan Forward) - scanare invers: BSR <dest>, <sursa> (Bit Scan Reverse) Instruciuni de setare condiionat. Pun octetul pe zero sau unu, n funcie de una din cele 16 condiii definite de indicatori. Operandul destinaie poate fi reg/mem. Aceste instruciuni sunt folosite pentru implementarea expresiilor booleene, din limbajele de nivel nalt. SETcond <dest> (SET byte on condition) if cond then (dest) 1 else (dest) 0 SETE / SETZ ZF = 1 SETNE / SETNZ ZF = 0 SETL / SETNGE SF <> OF, valori cu semn SETLE / SETNG SF <> OF sau ZF = 1, valori cu semn SETNL / SETGE SF = OF, valori cu semn SETNLE / SETG SF = OF i ZF = 0, valori cu semn SETB / SETNAE / SETC CF = 1, valori fr semn

SETBE / SETNA SETNB / SETAE / SETNC SETNBE / SETA SETO / SETNO SETP / SETPE SETNP / SETPO SETS / SETNS

CF = 1 sau ZF = 1,fr semn CF = 0, valori fr semn CF = 0 i ZF = 0,fr semn OF = 1 / respectiv OF = 0 PF = 1, adic paritate par PF = 0, adic paritate impar SF = 1 / respectiv SF = 0

Instruciuni de deplasare Deplasrile pot fi aritmetice sau logice. Se poate deplasa operandul destinaie cu pn la 31 de bii, corespunztor operandului contor, codificat n instruciune (sunt luai n considerare numai ultimii 5 bii ai acestuia). OF = este nedefinit ntr-o deplasare pe mai muli bii; = este poziionat pt. deplasare de un bit; CF = ultimul bit deplasat n afara operandului destinaie; AF = nedefinit; SF, ZF, PF = modificai conform rezultatului. SHL / SAL <dest>, <contor> (SHift logical / Arithmetic Left) Poziiile eliberate devin zero; ntre cele dou mnemonici nu exist nici o deosebire. Bitul cel mai semnificativ se deplaseaz n CF. SHR <dest>, <contor> (SHift logical Right) SAR <dest>, <contor> (Shift Arithmetic Right) Bitul cel mai semnificativ i pstreaz vechea valoare, dar este i deplasat spre dreapta (extensie de semn), ceea ce nseamn c nu poate s apar depire (schimbarea de semn a rezultatului) i (OF)=0 la o deplasare de 1 bit. Trebuie menionat c SAR nu furnizeaz acelai rezultat ca instruciunea IDIV, pentru aceeai operanzi, dac dempritul este negativ, i sunt deplasai (SAR) n afara operandului bii egali cu 1. De exemplu -5 deplasat la dreapta (SAR), cu un bit va furniza -3, n timp ce mprirea ntreag (IDIV) va furniza valoarea -2: (-5) = (11111011) (11111101) = (-3) Diferena dintre cele dou instruciuni este c IDIV trunchiaz toate cturile ctre zero, n timp ce SAR trunchiaz numerele pozitive ctre zero, iar pe cele negative ctre infinit negativ. La 386/486 pot fi realizate instruciuni de deplasare dubl, pe cuvnt sau dublu cuvnt. Operandul destinaie poate fi reg/ mem, iar sursa reg. general. Rezultatul nlocuiete operandul destinaie, iar contorul numrului de bii deplasai este specificat de registrul CL, sau ca o valoare imediat de 8 bii. Indicatorii sunt poziionai la fel ca la deplasrile anterioare. SHLD <dest>, <sursa>, <contor> (SHift Left Double) CF ...... Dest ...... SHRD <dest>, <sursa>, <contor> (SHift Right Double) Dest ... CF Surs ... Sursa

Registrul surs nu se modific. Instruciunea este util atunci cnd se mpacheteaz date din mai multe surse diferite. Instruciuni de rotire n cazul rotaiilor, biii deplasai n afara operandului nu sunt pierdui, ca n cazul deplasrilor, ci sunt rotii (circulai) napoi ctre cellalt capt al operandului. ncepnd de la procesoarele 286 contorul, chiar dac este diferit de 1, el poate fi specificat n instruciune, ca dat imediat. Rotaiile modific numai CF i OF: CF = ultimul bit rotit n afara operandului; OF = nedefinit pentru rotaii multibit; = 1 sau 0, pentru rotaie doar de 1 bit, dup cum s-a modificat sau nu bitul de semn al operandului. ROL <dest>, <contor> CF Bn ROR <dest>, <contor> B0 CF RCL <dest>, <contor> B0 CF Bn RCR <dest>, <contor> B0 CF Bn (ROtate Left) ...... B0 (ROtate Right) ...... B0 (Rotate through Carry Left) ...... B0 CF (ROtate through Carry Right) ...... B0 CF

Bn

Bn

Bn

1) nmulirea cu 20 a uni numr din registrul AX: ; 20 = 16 + 4 = 24 + 22 ; deci 2 deplasri la stnga, se salveaz rezultatul, mov cl, 2 ; care reprezint * 4, i nc dou deplasri shl ax, cl mov bx, ax ; se salveaz *4 n (BX) mov cl, 2 ; contorul pentru nc dou deplasri (*16) shl ax, cl ; care realizeaz * 16, i se adun cele dou add ax, bx ; rezultate pariale 2) mprirea la 1024 a valorii din registrul AX: mov cl, 2 ; 1024 = 210 = 28 * 22 sar ah, cl ; dup 8 deplasri la dreapta AL se pierde xchg ah, al ; (sau mov ah, al), e suficient s deplasm AH la cbw ; dreapta cu 2, i apoi s-i facem extensia de semn 3) mprirea unui numr de 32 bii (64) la o putere a lui 2, de exemplu la 64 = 26: mem_32 dd 50000; . . . . . ; trebuie deplasat numrul la dr. cu 6 bii mov cx, 6 ; contorul numrului de deplasri iar: sar word ptr mem_32[2], 1 ; bitul 17 (CF)

rcr word ptr mem_32[0], 1 loop iar

; (CF)

bitul 16

4) Determinarea numrului de bii egali cu 1 dintr-o variabil. .model small .stack 100h .data lung_var equ 8 variabila dw lung_var dup (0acfh) nr_unitati db ? .code assume cs: @code, ds: @data start: mov ax, @data mov ds, ax mov si, 0 ; indexul curent al cuvintelor din variabila mov dl, lung_var ; contor numr de cuvinte mov bl, 0 ; contor numr de uniti gsite bucla2: mov cx, 16 ; contorul de bii pentru un cuvnt mov ax, variabila[si] ; se citete cuvntul curent bucla1: rcl ax, 1 ; o rotaie pentru a deplasa un bit adc bl, 0 ; se contorizeaz numrul de uniti loop bucla1 ; pentru un cuvnt add si, type variabila ; se actualizeaz indexul dec dl ; se testeaz dac mai sunt cuvinte jnz bucla2 ; dac da se reia citirea cuvintelor mov nr_unitati, bl ; dac nu se depune rezultatul mov ax, 4C00h ; revenire DOS int 21h end 4a). Aceeai problem poate fi rezolvat utiliznd instruciunile BSF i BTR, astfel: mov cx, lung_var ; contor dimensiune variabil mov bl, 0 ; contor uniti mov si, 0 ; index cuvinte bucla: mov ax, variabila[si] scanare: bsf dx, ax ; determin primul bit 1 (indexul n DX) jz gata_cuv ; dac ZF=0, toi biii sunt 0 btr ax, dx ; transfer 1 din AX, din poziia DX n CF, adc bl, 0 ; iar bitul =0, sau inc bl, numr unitile jmp scanare ; se reia scanarea cuvntului curent gata_cuv: add si, 2 ; indexul cuvntului urmtor loop bucla ; decrementare contor numr de cuv. variabil ; dac nu s-a terminat variabila ia cuv. urmtor

5) Tiprirea coninutului registrului DX, n format octal: tip_car proc far ; procedura tiprete caracterul al crui cod ASCII ; l primete n registrul AL push dx ; se salveaz registrul de lucru DX mov dl, al ; se apeleaz funcia 2 din DOS care mov ah, 2 ; tiprete caracterul al crui cod int 21h ; ASCII se transmite n registrul DL pop dx ; se reface registrul salvat ret tip_car endp tip_octal proc far ; tiprete n octal valoarea, fr semn transmis n DX push cx ; se salveaz registrele de lucru push ax ; prima cifr de tiprit este doar de 1 bit rol dx, 1 ; care este rotit pe ultimul bit mov al, dl ; i dus n registrul AL and al, 1 ; se terg ceilali bii add al, 30h ; este convertit la codul ASCII call tip_car ; i se tiprete ; urmtoarele 5 cifre sunt de cte 3 bii mov cx, 5 ; contor numr de cifre de tiprit octal1: push cx ; se salveaz contorul n stiv mov cl, 3 ; contor numr de rotiri la stnga rol dx, cl ; cifra este rotit pe ultimii 3 bii mov al, dl ; i adus n AL and al, 7 ; sunt teri ceilali bii add al, 30h ; i convertit la codul ASCII call tip_car ; tiprirea cifrei pop loop pop pop ret tip_octal cx octal1 ax cx endp ; se citete valoarea contorului de cifre ; se refac registrele salvate n stiv

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

25. Operare pe iruri, instruciuni de transfer al controlului programului, de control procesor i de sistem.

Instruciuni de operare pe iruri


Exist cinci operaii de baz ce opereaz pe iruride lungime de pn la un segment (64K la 286, respectiv 4G la 386/486), i permit: mutare, comparare de iruri, scanarea unui ir pentru o valoare i transfer la/de la acumulator. Aceste operaii de baz pot fi precedate de un prefix special de un octet care are ca efect repetarea instruciunii prin hardware. Repetiia se poate termina printr-o varietate de condiii, iar o operaie repetat poate fi ntrerupt sau suspendat. O instruciune pe ir poate avea un operand surs, un operand destinaie sau pe amndoi. irul surs este n (DS) sau ntr-un alt segment, dac este prefixat peste aceast presupunere. irul destinaie se afl, ntotdeauna, n segmentul dat de registrul (ES). SI este ca offset pentru elementului curent al irului surs, iar DI este offset pentru irul destinaie. Instruciunile pe ir actualizeaz automat SI i/sau DI. DF determin dac registrele index sunt auto-incrementate-decrementate (DF=0-1), iar pas de actualizare depinde de tipul irurilor: 1 - octet, 2 - cuvnt, 4 - dublu cuvnt. Dac este prezent un prefix de repetare reg. CX este decrementat la fiecare repetiie a instruciunii pe ir; repetarea va lua sfrit cnd CX=0, sau pentru unele prefixe i n funcie de ZF. Sunt cinci mnemonici pentru dou forme de prefix octet, care controleaz repetarea unei instruciuni pe ir(uri). Prefixele de repetare nu afecteaz indicatorii. REP / REPE / REPZ / REPNE / REPNZ REP - REPeat - este utilizat mpreun cu MOVS- STOS, "repet ct timp nu este sfritul irului, adic (CX<>0)"; REPE / REPZ - REPeat while Equal / Zero - care opereaz la fel i au fizic acelai prefix octet ca REP. Sunt utilizate pentru CMPS i SCAS, i necesit, n plus fa de condiia anterioar, ca ZF s fie setat nainte de efectuarea urmtoarei repetiii; REPNE / REPNZ - REPeat while Not Equal / Zero - este asemntor cu cele anterioare, cu deosebirea c ZF trebuie pus pe 0, sau repetiia se termin.

MOVS <sir_dest>, <sir_sursa> (MOVe data from String to string) MOVSB / MOVSW / MOVSD Se transfer un element (octet/cuvnt/dublu cuvnt) de la surs (SI) la destinaie (DI), i actualizeaz SI/DI Utilizat mpreun cu prefixul REP realizeaz un transfer de bloc memorie-memorie. CMPS <sir_dest>, <sir_sursa> (COMPare String operands) CMPSB / CMPSW / CMPSD Aceast instruciune scade operandul destinaie (referit de DI) din cel surs (referit de SI), modific indicatorii de stare, dar nu altereaz nici unul dintre operanzi, dup care actualizeaz SI/DI. Trebuie reinut c spre deosebire de instr. CMP care scade sursa din destinaie, CMPS realizeaz scderea invers: surs - destinaie. Dac CMPS are prefixul REPE sau REPZ operaia este interpretat "compar ct timp nu este sfrit irul (CX<>0) i irurile sunt egale (ZF=1)"; determina prima pereche de elemente diferite.

Dac CMPS este precedat de REPNE/REPNZ "compar ct timp nu este sfrit de ir (CX<>0), i elementele irurilor nu sunt egale (ZF=0)"; determina prima pereche de elemente egale. SCAS <sir_dest> (SCAn String data) SCASB / SCASW / SCASD Instruciunea scade elem. ir dest. (octet/ cuvnt/ dublu cuvnt) adresat de DI, din AL, AX sau EAX, i actualizeaz indicatorii, dar fr a modifica irul destinaie sau acumulatorul. Dac SCAS este prefixat de REPE/REPZ "scaneaz ct timp nu este sfritul irului (CX<>0) i valoarea scanat este egal cu elementele irului (ZF=1)"; determina abaterea fa de o valoare. Dac SCAS este prefixat de REPNE/REPNZ "scaneaz ct timp nu este sfritul irului (CX<>0) i valoarea scanat este diferit de elementele irului (ZF=0)"; localizeaz o valoare ntr-un ir. LODS <sir_sursa> (LOaD String operand) LODSB / LODSW / LODSD Transfer elementul irului surs adresat de SI, n AL, AX sau EAX, i actualizeaz SI. Instruciunea se utilizeaz n bucle soft. STOS <sir_dest> (STOre String data) STOSB / STOSW / STOSD Transfer un element din acumulator (AL, AX, EAX) n irul destinaie, i actualizeaz DI, pentru a referi urmtorul element. Instruciunea poate fi precedat de prefixul REP, i astfel se poate iniializa un ir cu o constant. 1) Copierea unui ir de octei dintr-o zon de memorie ntr-alta. date_sir segment word public 'data' sir1 db 1000 dup (7,0f0h) ; irul surs lung1 equ $ - sir ; lungimea irului surs sir2 db 1000 dup (2 dup (?)) ; rezervare pt. ir dest. ptr_sir1 dd sir1 ; pointer sir1 ptr_sir2 dd sir2 ; pointer sir2 date_sir ends cod segment word public 'code' assume cs:cod, ds:date_sir, es:date_sir start: mov ax, date_sir ; iniializare registru segment DS mov ds, ax ; i apoi adresele celor dou iruri mov es, ax ; sau: les di,ptr_sir2 lea di, sir2 ; lds si,ptr_sir1 lea si, sir1 mov cx, lung1 ; contorul transferului = lungimea sursei cld ; direcia de parcurgere a irului (df=0) repeta: lodsb stosb ; sau: movs sir2,sir1 , sau movsb loop repeta ; sau: rep movsb mov ax, 4c00h ; revenire DOS

cod end

int ends start

21h

2) Copierea informaiei dintr-un buffer din memorie n memoria ecran. n modul text pentru fiecare caracter de pe ecran se rezerv doi octei: unul reprezint atributele de afiare (afiare continu / intermitent - 1 bit, culoare fond - 3 bii, culoare caracter - 4 bii), iar cel de-al doilea este codul ASCII al caracterului afiat. .model small .data mem_ecran dd 0B8000000h ; adresa memoriei ecran dimensiune equ 2000 buffer dw dimensiune dup (3a33h); se va afia acelai caracter ptr_buf dd buffer .code start: mov ax, @data ; iniializare DS mov ds, ax mov ah, 0 ; selecie mod de lucru mov al, 0 ; alfanumeric 40*25 alb/negru, pt. 80*25 al=2 int 10h les di, mem_ecran lds si, ptr_buf mov cx, dimensiune cld ; direcia de parcurgere rep movsw ; transfer buffer n mem_ecran mov ax, 4c00h ; revenire DOS int 21h .stack 10h end start 3) Determinarea poziiei unui anumit caracter (sau a unui ir de caractere) ntr-un fiier surs de pe disc. .model small .stack 10h .data car equ 'A ; caracterul de identificat (sau irul) lung equ 2048 ; dimensiunea maxim a fiierului-4 sectoare buffer db lung dup (?); spaiu de mem. pentru fiier nume_fis db 'fisier.asm', 0 ; nume fii.- ASCIIZ, adic dup ; numele poate fi precedat i de calea de acces pozitie dw ? ; poziia caracterului n fiier nr_logic dw ? ; numrul logic atribuit fiierului contor dw ? ; numrul efectiv de caractere citite mes_lipsa db 'nu exista fisier cu acest nume$' mes_err_cit db 'eroare de citire de pe disc$' mes_car_lipsa db 'caracterul cautat nu este in fisier$'

.code start: mov ax, @data ; iniializare DS mov ds, ax mov ah, 3dh ; apel DOS pentru deschidere de fiier mov al, 0 ; n modul "citete" (1-scrie,2-citire/scriere) lea dx, nume_fis ; adresa numelui fiierului int 21h ; apel funcie 'deschide fiier' jc lipsa_fis mov nr_logic, ax ; se depune numrul sectorului mov bx, ax ; i n BX, pentru funcia de citire mov cx, lung ; contor numr maxim de caractere citite lea dx, buffer ; adresa unde se vor depune caracterele mov ah, 3fh ; funcia de citire din fiier int 21h jc err_cit ; dac a aprut eroare al citire mov contor, ax ; la 'contor' se depune numrul de car. mov cx, ax ; contor de cutare 'car' push ds ; se ncarc n ES adresa de segment pop es ; a 'buffer'-ului lea di, buffer ; i n registrul (DI) offsetul acestuia mov al, car ; caracterul de cutat cld ; stabilire direcie de parcurgere, (DF)=0 repne scasb ; continu scanarea pn-l gsete je gasit ; dac nu s-a gsit nu se face saltul lea dx, mes_car_lipsa ; i se tiprete mesajul mov ah, 9 ; mesajul: 'caracterul cautat nu este in fisier' int 21h jmp gata gasit: dec di ; poziia caracterului cutat, (DI)-1 mov pozitie, di ; deoarece (DI) a fost actualizat dup jmp ; scanare lipsa_fis: lea dx, mes_lipsa ; nu s-a gsit fiierul cu mov ah, 9 ; numele specificat int 21h jmp gata err_cit: lea dx, mes_err_cit ; eroare la citirea fiierului mov ah, 9 int 21h gata: mov ah, 3eh ; nchiderea fiierului deschis mov bx, nr_logic int 21h mov ax, 4c00h ; revenire DOS int 21h end start

gata

Determinarea poziiei unui ir de caractere ntr-un fiier: sir_cardb 'asamblare' lung_sir dw $-sir_car ptr_sir dd sir_car ptr_buf dd buffer pozitie dw ? ; poziia irului de caractere ................... les di, ptr_buf lds si, ptr_sir mov cx, contor ; dimensiune buffer sub cx, lung_sir ; cutarea se va face ncepnd de la 0 inc cx ; pn la (contor) - (lung_sir) cld ; direcia de parcurgere (DF=0) reia: push si; se salveaz adresa irului cutat push di ; se salveaz adresa irului n care se cut push cx; se salveaz contorul numrului maxim de cutri mov cx, lung_sir ; contorul de comparaii repe cmps buffer, sir_car ; se compar ct timp sunt egale pop cx ; reface resurse salvate n stiv: contorul pop di ; i adrese iruri: destinaie - irul n care se pop si ; caut, surs (sub)irul care se caut je gasit ; salt dac s-a gsit sir_car n buffer inc di ; cutarea se va relua de la urmtorul caracter loop reia ; din buffer, dac (contor) <> 0 ; -> irul de caractere nu este n fiierul dat (respectiv n buffer) jmp nu_gasit gasit: mov pozitie, di ; valoarea salvat pentru (DI) ................... nu_gasit: ; tiprire mesaj: Nu s-a gasit sirul de caractere

Instruciuni de transfer al controlului programului


Instruciunile de transfer al controlului programului opereaz asupra lui IP i CS. La apariia unui astfel de transfer, coada de instruciuni nu mai conine instruciunea urmtoare i EU va transmite noua adres la BU, care va obine instruciunea urmtoare direct din memorie, utiliznd noile valori pentru CS:IP; instruciunea va fi transferat ctre IU i EU, pentru execuie, i BU apoi ncepe reumplerea cozii de la noua locaie. Exist patru tipuri de instruciuni de transfer control: - instruciuni de transfer necondiionat; - instruciuni de transfer condiionat; - instruciuni de ciclare; - instruciuni de ntrerupere; Dintre acestea numai instruciunile de ntrerupere afecteaz indicatorii.

Instruciuni de transfer control, necondiionat Transferul controlului se poate face la o locaie (int) n segmentul de cod curent (transfer intrasegment/NEAR) sau la un segment de cod diferit (transfer intersegment/FAR). CALL <nume_procedur> Aceast instruciune activeaz o procedur, salvnd adresa de revenire, n stiv, pentru a permite unei instruciuni RET (return), din procedur, s transfere controlul napoi la instruciunea urmtoare lui CALL. Asamblorul genereaz tipuri diferite de instruciuni main pentru CALL, dup modul cum programatorul a definit numele procedurii, cu atributul NEAR sau FAR. Pentru returnarea corect a controlului, tipul instruciunii CALL trebuie s fie potrivit cu tipul instruciunii RET. Diferitele forme ale instruciunii CALL permit ca adresa procedurii int s fie obinut direct din instruciune (direct), sau de la o locaie de memorie sau dintr-un registru referit de instruciune (indirect). a) - CALL direct intrasegment: (SP) (SP) - 2 ((SP)+1:(SP)) (IP) (IP) (IP) + deplasament La 386/486 deplasamentul poate avea i 32 bii, deci adunarea se va face modulo 4G. call near_etich call near_proc b) - CALL direct intersegment: (SP) (SP) - 2 ((SP)+1:(SP)) (CS) (CS) al 2-lea cuvnt din instr. (adresa de segment) (SP) (SP) - 2 ((SP)+1:(SP)) (IP) (IP) primul cuvnt din instr. (adresa de offset) call far_etich; call far_proc c) - CALL indirect intrasegment: (SP) (SP) - 2 ((SP)+1:(SP)) (IP) (IP) registru / memorie; Exemple: call cx; call word ptr nume_var call word ptr [bx][si]; call mem_word d) - CALL indirect intersegment, poate fi fcut numai prin memorie: (SP) (SP) - 2 ((SP)+1:(SP)) (CS) (CS) al 2-lea cuvnt mem. referit de instruciune (SP) (SP) - 2 ((SP)+1:(SP)) (IP) (IP) primul cuvnt mem. referit de instruciune call dword ptr [bx]; call dword ptr nume_var[bp][si]

Cnd se utilizeaz apeluri indirecte trebuie asigurat c tipul lui CALL este potrivit cu tipul instruciunii de revenire RET->erori. RET [val_pop] (RETurn from procedure) Asamblorul genereaz 2 tipuri de instr. main: RET intrasegment dac procedura a fost definit NEAR, i RET intersegment, dac procedura este de tip FAR. Valoarea val_pop, care este opional, este prevzut pentru a descrca parametrii din stiv. (IP) ((SP)+1:(SP)) (SP) (SP) + 2 if inter_segment then (CS) ((SP)+1:(SP)) (SP) (SP) + 2 if val_pop <> 0 then (SP) (SP) + val_pop Tipul instruciunii RET trebuie s se potriveasc cu tipul lui CALL: call word ptr [bx] ; pentru o procedur de tip FAR. - se va salva n stiv doar offsetul de revenire (IP), iar la execuia instruciunii RET, din procedura de tip FAR, se va reface din stiv, pe lng IP i CS, cu urmtorul cuvnt din stiv (i se va pierde controlul asupra calculatorului). call dword ptr [bp][si] ; pentru o procedur de tip NEAR. - se vor salva n stiv adresele de revenire pentru CS:IP, dar la terminarea procedurii se va reface din stiv numai IP, rmnnd n stiv un cuvnt, care n final va duce la pierderea controlului. JMP <int> Spre deosebire de CALL, JMP nu salveaz n stiva nici o informaie. a) JMP direct intrasegment, modific IP prin adunarea deplasamentului relativ al intei, coninut n instruciune la valoarea, actualizat, a lui IP. Auto-relative (relocabile dinamic). jmp near_etich ; salt direct intrasegment jmp short near_etich; salt de tip short b) - JMP direct intersegment (instr. are 5 octei/286, sau 5/7 la 386): jmp far_etich ; salt n alt segment jmp far ptr etich ; 'etich' poate fi i n acelai segment c) - JMP indirect intrasegment: jmp ax jmp tabela[bx] jmp si jmp word ptr [bp][di] d) - JMP indirect intersegment, poate fi fcut numai prin memorie: jmp etich_dword jmp dword ptr [bx][si] Programul urmtor execut diferite secvene de program, n funcie de opiunea utilizatorului, introdus de la tastatur. .model small .data executie db 0Dh, 0Ah, 'Executa secventa (1,2,3 sau 4=stop):$' mes_secv1 db 'S-a executat secventa 1',0dh,0ah,'$' mes_secv2 db 'S-a executat secventa 2',0dh,0ah,'$' mes_secv3 db 'S-a executat secventa 3',0dh,0ah,'$'

tab_secv

label dw dw dw dw

word secv1 secv2 secv3 gata

.code start: mov ax, @data ; iniializare adresa de segment mov ds, ax iar: lea dx, executie ; solicit secvena dorit, utilizatorului mov ah, 9 ; se tiprete mesajul de selecie secven int 21h ; apel funcia 9, tiprire mesaj mov ah, 1 ; apel funcia 1, citire caracter int 21h ; caracter returnat n AL sub al, 31h ; intervalul '1''4' -> 03 i verific dac jc iar ; este n intervalul 03: dac nu, cere cmp al, 4 ; o valoare, n acest interval, fr a executa jnc iar ; vreuna dintre secvene cbw ; extensie pe 16 bii mov bx, ax shl bx, 1 ; *2, pentru a obine adresa relativ jmp word ptr tab_secv[bx] ; n tabela cu adr. secvene secv1: lea dx, mes_secv1; se execut prima secven mov ah, 9 int 21h jmp short iar secv2: lea dx, mes_secv2; se execut a doua secven mov ah, 9 int 21h jmp short iar secv3: lea dx, mes_secv3; se execut a treia secven mov ah, 9 int 21h jmp short iar gata: mov ax, 4c00h ; revenire DOS int 21h .stack 20h end Instruciuni de transfer control, condiionat Jcond <int> Toate salturile condiionate sunt de tip SHORT, adic inta trebuie s fie n segmentul de cod curent, n intervalul de [-128, +127] octei fa de instruciunea de transfer (de ex. JMP 00, realizeaz saltul la primul octet al urmtoarei instruciuni). La 386/486 aceste instruciuni permit i realizarea unui salt de tip NEAR, adic n cadrul aceluiai segment (64K sau 4G, depinde de

atributul de dimensiune adres). Deoarece adresa de salt este determinat prin adunarea deplasamentului relativ al intei, la IP-ul actualizat, toate salturile condiionate sunt autorelative. n cazul cnd se dorete un salt condiionat pe o distan mai mare de 128 octei, la 286, sau un salt ntr-un alt segment, atunci trebuie s se utilizeze dou instruciuni de salt: un salt condiionat (pentru condiia negat, adic, de exemplu JE, pentru JNE), n intervalul [-128,+127], iar, imediat dup instruciunea de salt condiionat, o instruciune de salt, necondiionat, pe distana dorit. JZ / JE ZF = 1, dac este egalitate (d) = (s) JNZ / JNE ZF = 0, dac nu este egalitate (d) <> (s) JL / JNGE SF <> OF, dac (d) < (s), pentru numere cu semn JLE / JNG SF <> OF sau ZF = 1, (d)<=(s), numere cu semn JNL / JGE SF = OF, dac (d) >= (s), pentru numere cu semn JNLE / JG SF = OF i ZF = 0, (d) > (s), pentru numere cu semn JB /JNAE /JC CF = 1, dac (d) < (s), numere fr semn JBE / JNA CF = 1 sau ZF = 1, (d)<=(s), numere fr semn JNB /JAE /JNC CF = 0, dac (d) >= (s), numere fr semn JNBE / JA CF = 0 i ZF = 0, (d) > (s), pentru numere fr semn JP / JPE PF = 1, dac numrul are paritate par JNP / JPO PF = 0, dac numrul are paritate impar JO/JNO OF = 1/0, dac este/ nu este depire de reprezentare JS /JNS SF = 1/0, dac numrul este negativ/ pozitiv J(E)CXZ (E)CX = 0, test asupra registrului ECX sau CX condiie ZF CF d>s 0 0 d=s 1 0 d<s 0 1 pentru numere fr semn salt pentru d=s d <> s d<s d>s d <= s d >= s numere fr semn JE / JZ JNE / JNZ JB / JNAE / JC JA / JNBE JBE / JNA JAE / JNB / JNC condiie OF SF d > s 0/1 0/1 d=s 0 0 d < s 0/1 1/0 pentru numere cu semn numere cu semn JE / JZ JNE / JNZ JL / JNGE JG / JNLE JLE / JNG JGE / JNL ZF 0 1 0

Determinarea valorii maxime dintr-un ir de valori (cu semn). .model small .stack 10h .data sir db 10,20,-30,100,-100,200 lung dw $-sir maxim db ? mes_sir_vid db 'sir vid de valori$'

.code ; contor numr de valori din ir ; dac irul este vid se tiprete mesaj ; index elemente din ir ; direcia de parcurgere bl, [si] ; se iniializeaz valoarea maxim din ir si ; actualizare index elemente cx ; actualizare contor gata ; dac a fost un singur element s-a terminat iar: ; citete element curent din ir bl, al ; se compar cu maximul curent urm ; dac max > val. curent trece la elem. urmtor ; pentru numere fr semn se nlocuiete jge cu jnc mov bl, al ; altfel se actualizeaz valoarea maxim urm: loop iar ; se reia ciclul dac mai sunt elem. n ir gata: mov maxim, bl ; se depune valoarea maxim iesire: mov ax, 4c00h ; revenire DOS int 21h sir_vid: lea dx, mes_sir_vid ; se tiprete mesajul mov ah, 9 ; 'sir vid de valori' int 21h jmp iesire ; revenire DOS end Instruciuni de ciclare Aceste instruciuni pot fi folosite pentru a controla repetiia unor cicluri soft. Ele permit o programare uoar a structurilor de control de tip ciclu cu test la sfrit. Ele utilizeaz drept contor, al ciclului, registrul CX. Instruciunile de ciclare sunt auto-relative, i pot transfera controlul la o locaie (int) aflat n intervalul [-128,+127] de octei fa de ele, deci realizeaz numai transferuri de tip SHORT (att pentru 286 ct i pentru 386/486). Aceste instruciuni nu modific nici un indicator. LOOP <short_etich> (LOOP control with CX counter) (CX) (CX) - 1 if (CX) <> 0 then (IP) (IP) + deplasament (short_etich); 1) Calculul sumei elementelor unui ir de tip cuvnt. mov cx, lung_sir ; contor numr de elemente mov ax, 0 ; suma va fi pe dou cuvinte mov bx, ax ; i se iniializeaz cu 0 mov si, ax ; index pentru adresarea elementelor aduna: mov mov mov jcxz lea cld mov inc dec jcxz lodsb cmp jge ax, @data ds, ax cx, lung sir_vid si, sir ; iniializare registru segment

add adc add loop mov mov

ax, sir[si] bx, 0 ; transporturile se acumuleaz n BX si, type sir ; actualizare index aduna ; dac nu e gata se reia adunarea suma, ax ; se depune rezultatul, ncepnd cu suma[2], bx ; cu cuvntul mai puin semnificativ

2) Determinarea primelor N numere din irul lui Fibonacci. mov ax, 1 ; se iniializeaz primele dou valori:0,1 mov bx, 0 ; formula este: fib(n)=fib(n-1)+fib(n-2) mov cx, N ; numrul de valori calculate mov di, bx ; indexul adresei unde se depun numerele urm: mov si, ax ; se salveaz fib(n-1), care va fi fib(n-2) add ax, bx ; se calculeaz fib(n), care va fi fib(n-1) mov bx, si ; se actualizeaz fib(n-2) mov fibonacci[di], ax ; se depune fib(n) add di, type fibonacci ; actualizare index loop urm ; se reia dac nu s-au calculat N numereLOOPE / LOOPZ <short_etich> (LOOP while Equal/Zero, with CX counter) (CX) (CX) - 1 if ((CX) <> 0) and (ZF=1) then (IP) (IP) + deplasament (short_etich); Determinarea primului element diferit de 0, dintr-un ir. mov cx, lung_sir ; contorul irului mov si, -1 ; iniializare SI reia: inc si cmp sir[si], 0 ; se compar cu 0 loope reia ; dac este 0 se reia comparaia jz sir_zero ; dac ZF=1, tot irul conine numai 0 aici: ; s-a determinat primul element <> 0, la adresa SI LOOPNE / LOOPNZ <short_etich> (LOOP while Not Equal/Zero, with CX counter) (CX) (CX) - 1 if ((CX) <> 0) and (ZF=0) then (IP) (IP) + deplasament (short_etich); 1) Determinarea ultimului element dintr-o list nlnuit. Ultimul element dintr-o list va conine valoarea zero n cmpul de adres. lea bx, offset cap_lista ; adresa de nceput a listei mov cx, N ; dimensiunea maxim a listei urm: mov bx, [bx + lung_info] ; adresa elementului urmtor cmp bx, 0 ; se compar cu 0 loopne urm ; se reia dac nu s-a gsit je gasit ; s-a gsit ultimul element din list, adr. n BX

; dac nu se execut saltul

nu s-a gsit ultimul element printre cele N elemente

2) Determinarea primei valori egal cu zero, dintr-un ir de valori. mov cx, lung_sir ; contorul irului mov si, -1 ; iniializare SI, pentru a nu afecta reia: inc si ; indicatorii, naintea instruciunii LOOP cmp sir[si], 0 ; se compar cu 0 loopne reia ; dac nu este 0 se reia comparaia jnz sir_zero ; dac ZF=0, tot irul conine numai valori <> 0 aici: ; s-a determinat primul element = 0, la adresa SI Instruciuni de ntrerupere Aceste instruciuni permit rutinelor de servire a ntreruperilor s fie activate prin program la fel ca la apariia unei ntreruperi hardware externe. Singura instruciune ce altereaz indicatorii este IRET. INT <tip_ntrerupere> (call to INTerrupt procedure) (SP) (SP) -2 ((SP)+1:(SP)) indicatori (tf), (if) 0 (SP) (SP) - 2 ((SP)+1:(SP)) (CS) (CS) (n * 4 + 2) (SP) (SP) - 2 ((SP)+1:(SP)) (IP) (IP) (n * 4 ) (INTerrupt on Overflow) Aceast instruciune genereaz ntrerupere dac OF=1.

INTO

BOUND <dest_reg>, <sursa_mem> (check array index against BOUNDs) Determin dac valoarea, cu semn, coninut n registrul destinaie (16/32 bii), specificat de instruciune, se afl ntre limitele specificate de operandul surs, care trebuie s fie operand din memorie (16/32 bii). Se compar operandul destinaie cu dou cuvinte (sau cuvinte duble), aflate n memorie de la adresa specificat de cel de-al doilea operand. Dac valoarea destinaiei nu este ntre cele dou limite (la locaii succesive), specificate de surs, din memorie, se genereaz ntrerupere pe nivelul 5 (INT 5). IRET / IRETD (Interrupt RETurn) Transfer controlul napoi la punctul de ntrerupere, prin refacerea IP, CS i a indicatorilor, din stiv. Astfel instruciunea IRET afecteaz toi indicatorii, prin restaurarea lor, la valorile anterior salvate. mprirea unui numr de 32 bii (A1,A0) la un numr de 16 bii (B). Rezultatul, ctul, poate avea, cel mult, 32 de bii (Q1,Q0), iar restul 16 bii (R0).

Se va ncerca mai nti o mprire obinuit, i dac ctul este de 16 bii, operaia este terminat. Dac nu, deci dac ctul este de 32 de bii atunci se va face mprirea n modul urmtor: A1 * 216 + A0 = (Q1 * 216 + Q0) * B + R0 unde Q1 = [ A1 / B ] i deci A1 = Q1 * B + R1 nlocuind A1 n prima relaie rezult: R1 * 216 + A0 = Q0 * B + R0 Deci ordinea operaiilor va fi: - se mparte A1 la B i rezult: Q1 i R1; - se mparte (R1 * 216 + A0) la B i rezult: Q0 i R0. ; procedura de mprire, primete: ; (DX, AX) - demprit (32 bii) ; (BX) - mpritor (16 bii) ; i va returna: ; (BX, AX) - ctul ; (DX) - restul pdiv proc cmp bx, 0 ; mpritor = 0 ? jnz cdiv ; dac nu se continu mprirea, altfel int 0 ; se apeleaz procedura de eroare la mprire jmp eroare cdiv: push es ; se salveaz registrele de lucru push di push cx mov di, 0 mov es, di ; ES:DI=0:0, adresa ntrerupere nivel 0 push es:[di] ; se salveaz adresa de tratare ntrerupere push es:[di+2] ; nivel 0 (eroare la mprire) n stiv ; se nlocuiete adresa salvat (proc. de eroare la mprire) cu ; adresa procedurii prezentate anterior lea cx, int_0 ; offset procedura de mprire mov es:[di], cx ; se depune n locul proc. de eroare mov cx, cs ; adresa de segment a noii proceduri mov es:[di+2], cx ; se pune n locul celei de eroare ; se ncearc mprirea normal div bx ; dac ctul are 16 bii s-a terminat i BX = 0 ; dac nu, deci dac ctul are 32 bii, se va genera ntrerupere ; pe nivelul 0, care a fost nlocuit cu procedura de mprire xor bx, bx ; BX = 0, ctul este doar n AX revenire: pop es:[di+2] ; se reface adresa procedurii pop es:[di] ; de ntrerupere, nivel 0, eroare mprire pop cx ; se refac registrele salvate n stiv pop di pop es ret ; procedura propriu-zis de mprire, care a fost pus n locul

; procedurii de tratare eroare la mprire (nivel 0) int_0: push bp ; salvare BP, pentru a accesa stiva mov bp, sp ; se va nlocui adresa salvat, a instr. ; urmtoare mpririi cu cea a instruciunii de 'revenire' mov word ptr [bp+2], offset revenire ; sau, ntruct instr. xor bx, bx are doi octei. ; se poate utiliza i: add word ptr [bp+2], 2 push ax ; se salveaz A0 mov ax, dx ; (AX) A1 sub dx, dx ; pregtire demprit (DX=0) ; se realizeaz mprirea A1/B -> (R1,Q1) = (DX,AX) div bx pop cx ; CX = A0 push ax ; se salveaz Q1 mov ax, cx ; (DX,AX) = (R1,A0) ; se realizeaz mprirea (R1,A0)/B -> (R0,Q0) = (DX,AX) div bx ; (DX,AX) = (R0,Q0) pop bx ; se reface ctul: (BX) = Q1 pop bp iret eroare: . . . . . ret pdiv endp Instruciuni de control procesor Aceste instruciuni permit programelor s controleze diferite funciuni ale procesorului. Un grup de instruciuni actualizeaz indicatorii, altul este utilizat pentru sincronizarea microprocesorului cu evenimente externe, i mai exist o instruciune care nu realizeaz nimic (NOP). Instruciuni pentru poziionarea indicatorilor CLC (CLear Carry flag) CF 0 STC (SeT Carry flag) CF 1 CMC (CoMplement Carry flag) CF not (CF) Aceste instruciuni de poziionare a lui CF se utilizeaz la operaiile de rotaie, deplasare sau la adunri/scderi de numere reprezentate pe mai muli octei/cuvinte etc. CLD (CLear Direction flag) DF 0 STD (SeT Direction flag) DF 1 Acest indicator va determina direcia de parcurgere a irurilor. CLI (CLear Interrupt enable flag) IF 0 STI (SeT Interrupt enable flag)

IF 1 Indicatorul IF dezactiveaz sau activeaz, prin poziionare pe 0, respectiv 1, ntreruperile externe, ce apar pe linia INTR. Sunt dezactivate numai ntreruperile mascabile (INTR), nu i ntreruperea nemascabil NMI, care este servit, indiferent de poziia lui IF. La activarea sistemului de ntreruperi (STI), ntreruperea, pe linia INTR, este recunoscut dup execuia instruciunii urmtoare lui STI. Instruciuni de sincronizare cu evenimente externe HLT (HaLT) Determin intrarea proc. n starea 'halt', din care iese doar dac: - se activeaz linia RESET; - se transmite semnal de ntrerupere pe linia NMI; - se transmite semnal de ntrerupere pe linia INTR, dac ntreruperile nu au fost dezactivate. Aceast instruciune se poate folosi la sfritul unei bucle soft, n situaia n care programul trebuie s atepte un eveniment extern (ntrerupere de la un dispozitiv extern). n acest caz se va salva n stiv adresa instruciunii urmtoare lui HLT. WAIT (WAIT) Determin intrarea proc. n starea 'wait', ct timp linia BUSY\ este activ. Procesorul intr ntr-o stare 'idle', i repet testarea liniei BUSY\, ciclic la intervale de ase perioade de ceas. Cnd linia BUSY\ devine inactiv, se continu execuia programului cu instruciunea urmtoare lui WAIT. Aceast stare poate fi ntrerupt, printr-un semnal de ntrerupere, dar dup tratarea ntreruperii se reintr n aceast stare, ntruct se salveaz n stiv adresa acestei instruciuni. ESC <Cod_Op>,<sursa> (ESCape) Aceast instruciune este specific coprocesorului matematic, i ea este identificat prin primii cinci bii ai codului de operare care sunt 11011; ceilali bii din cmpul codului operaiei identific tipul operaiei coprocesorului. De fapt coprocesorul urmrete magistrala sistemului, i cnd identific execuia acestei instruciuni, el o captureaz; dac operandul surs este un registru procesorul nu face nimic cu el, iar dac este un operand din memorie, l citete dar l ignor. n schimb coprocesorul poate captura acest operand cnd este citit din memorie. Cnd ESC se utilizeaz n conjuncie cu WAIT, se poate iniia o operaie care se execut concurent pe coprocesor, ca n figura urmtoare.

LOCK (assert LOCK# signal prefix) Acesta este un prefix, de un octet, care determin activarea semnalului de magistral LOCK, ct timp se execut instruciunea precedat de acest prefix. ntr-un sistem multiprocesor, acest semnal poate fi utilizat pentru a asigura procesorului acces exclusiv la utilizarea magistralei, i deci a unei resurse (memorii) partajate. mov al, 1 astept: lock xchg al, semafor ; citire i setare semafor test al, al ; testare semafor = 0 ?, jnz astept ; dac nu, resursa este ocupat ; i se ateapt eliberarea ei .... . ; utilizare exclusiv a resursei mov semafor, 0 ; eliberare resurs NOP (No OPeration) Dup cum spune i numele acestei instruciuni, ea nu realizeaz nici o prelucrare; nu afecteaz nici un indicator. Ea dureaz trei perioade de ceas, i are codul main al instruciunii XCHG AX,AX, sau XCHG EAX,EAX.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

26. Exemple de programe pentru fiecare tip de instruciuni.

Instruciuni de transfer date.


Exemplu: s inversm, ntre ei, octeii dintr-un ir de cuvinte. .model small .data mesajdw 'Ex','em','pl','u ','pr','og','ra','m ','2$' lung_mesaj equ ($-mesaj)/2 linie_noua db 0dh,0ah,'$' .code start: mov ax,@data ; iniializare registru segment DS mov ds,ax ; cu adresa segmentului de date lea dx,mesaj ; tiprim mesajul sub forma iniial mov ah,9 ; utiliznd funcia 9, din DOS : int 21h ; "xEmelp urpgora m" lea dx,linie_noua ; se trece pe o linie noua mov ah,9 int 21h ; pentru a aduce mesajul la forma dorit trebuie inversai ; octeii, fiecrui cuvnt ntre ei lea si,mesaj mov cx,lung_mesaj mov ax,[si] ; se ia cte un cuvnt xchg al,ah ; i se inverseaz octeii mov [si],ax ; se depune la aceeai adres add si,type mesaj ; se actualizeaz adresa curent loop iar ; i se continu pentru tot irul ; se tiprete mesajul astfel obinut lea dx,mesaj mov ah,9 ; se va tipri mesajul: int 21h ; 'Exemplu program 2' mov ax,4c00h ; revenire DOS int 21h start

iar:

end

Instruciuni de transfer specifice acumulatorului Programul citete de la tastatur codul ASCII al unei taste i afieaz acest cod (sub forma a dou cifre hexa). seg_date segment tab_conv db '0123456789ABCDEF' mesaj db '-are codul ASCII-' tasta db 2 dup (?), 0dh,0ah,'$' seg_date ends seg_cod segment

assume cs : seg_cod, ds : seg_date start: mov ax,seg_date mov ds,ax mov ah,1 ; citire cu ecou a unei taste int 21h ; fr ecou este funcia 8 mov ah,al ; salvare cod tast lea bx,tab_conv ; iniializare BX, pentru XLAT and al,0fh ; se reine doar a doua tetrad xlat tab_conv ; codul ASCII al acestei tetrade mov tasta+1,al ; este cea de-a doua cifr a codului mov al,ah ; codul iniial al tastei mov cl,4 ; contor numr de deplasri la dreapta shr al,cl ; deplasare logic la dreapta cu 4 bii xlat tab_conv ; conversia primei tetrade mov tasta,al ; codul ASCII al primei tetrade lea dx,mesaj mov ah,9 ; se tiprete codul tastei int 21h mov ax,4c00h ; revenire DOS int 21h seg_cod ends end start

Instruciuni Aritmetice
Programul adun dou numere, fr semn, reprezentate pe mai multe cuvinte (octei), dar de lungimi diferite, iar rezultatul se va depune peste numrul mai lung. add_data_2 segment primul dw 0a8adh, 7fe2h, 0a876h,0 lung_1 dw ($ - primul)/2 al_doilea dw 0fedch, 0abcdh, 0cdefh, 52deh, 5678h, 0 lung_2 dw ($ - al_doilea)/2 add_data_2 ends multi_add_2 segment assume cs: multi_add_2, ds: add_data_2 start: mov ax,add_data_2 mov ds,ax ; se determin cel mai mare numr, unde se pune rezultatul ; vom considera c (BX)= adresa numrului mai lung ; (DX)= dimensiunea numrului mai lung ; (BP)= adresa numrului mai scurt ; (CX)= dimensiunea acestuia ; numrul de octei ai numrului mai mic va controla bucla_1

; n care ambele numere au cuvinte ce trebuie adunate ; diferena dimensiunilor celor dou numere va controla bucla_2 ; necesar dac apare transport, pentru propagarea acestuia mov dx,lung_2 ; presupun, iniial numrul al lea bx,al_doilea ; doilea mai mare mov cx,lung_1 lea bp,primul cmp dx,cx ; verific presupunerea fcut jge num2_mai_mare ; dac e respectat se continu xchg bx,bp ; dac nu se schimb ntre ele coninutul xchg cx,dx ; perechilor de registre, respective num2_mai_mare: sub dx,cx ; determin diferena dintre lungimile lor clc ; (CF)=0 mov si,0 ; se iniializeaz indexul elementelor bucla_1: mov ax,ds:[bp][si] adc [bx][si],ax inc si ; actualizare index inc si loop bucla_1 ; (CX)=contor pentru adunare mov cx,dx ; contor pentru propagarea transportului bucla_2: jnc gata ; dac nu mai este transport de propagat adc word ptr [bx][si],0 inc si inc si loop bucla_2 ; trebuie testat (CF), i dac avem transport, adic se ; depete dimensiunea iniial a numrului mai lung, ; transportul trebuie memorat la adresa urmtoare, ; dac s-a rezervat spaiu, sau semnalat depirea: jc eroare . . . gata: mov ax,4c00h int 21h multi_add_2 ends end start ; (DI) = va conine extensia de semn a numrului mai scurt num2_mai_mare: push cx ; salvare lungime numr mai scurt mov di,0 ; extensie de semn pentru numr pozitiv mov si,bp ; adresa de nceput a numrului mai scurt shl cx,1 ; lungimea * 2 = numr octei ai numrului add si,cx ; se poziioneaz pe primul element sub si,2 ; care conine bitul de semn mov ax,[si] ; i i testm bitul de semn cmp ax,0 ; dac este pozitiv se continu cu valoarea

jp cont ; iniial pentru (di)=0 mov di,0ffffh ; altfel (di)=ffffh, extensie semn numr negativ cont: pop cx ; refacerea contorului sub dx,cx ; determin diferena dintre lungimile lor clc ; (CF)=0 mov si,0 ; se iniializeaz indexul elementelor bucla_1: mov ax,ds:[bp][si] adc [bx][si],ax inc si ; actualizare index inc si loop bucla_1 ; (CX)=contor pentru adunare mov cx,dx ; contor pentru propagarea transportului bucla_2: adc word ptr [bx][si],di ; i a semnului numrului mai scurt inc si inc si loop bucla_2 ; n acest punct se testeaz OF pentru a detecta o depire ; a dimensiunii iniiale a numrului mai lung Instruciunile de nmulire / mprire Afiarea n zecimal a coninutului registrului AX: ; (AX) conine o valoare care este n intervalul 065535 ; dac se mparte numrul la 100 se obine ca prim rest ; o valoare ce conine ultimele dou cifre (zeci, uniti) ; dac se mparte ctul anterior din nou la 100 se va obine ; o valoare ce conine urmtoarele dou cifre (mii, sute) ; iar acest ultim rest va avea valoarea primei cifre ; a zecilor de mii, care este n intervalul: 0 - 6. mov bx,100 ; mpritor mov dx,0 ; extensie semn demprit pozitiv div bx ; dx = ultimele 2 cifre (zeci, uniti) mov cx,dx ; ax = primele 3 cifre, cx = ultimele 2 cifre mov dx,0 ; extensie semn demprit pozitiv div bx ; dx = cifrele: mii, sute; ax = zeci de mii push dx ; se salveaz dx deoarece va fi modificat add al,30h ; se tiprete cifra zecilor de mii(06) mov dl,al ; caracterul de tiprit n DL mov ah,2 ; se apeleaz funcia 2 din DOS int 21h ; care tiprete caracterul din (DL) pop ax ; se iau din stiva valoarea pt. mii, sute aam ; conversie la format zecimal nempachetat add ax,3030h ; conversie la cod ASCII mov dx,ax ; se salveaz cele dou cifre xchg dh,dl ; se tiprete cifra miilor

mov int xchg mov int mov aam add mov xchg mov int xchg mov int

ah,2 21h dh,dl ah,2 21h ax,cx ax,3030h dx,ax dh,dl ah,2 21h dh,dl ah,2 21h

; se tiprete cifra sutelor ; ultimele dou cifre: zeci, uniti ; conversie la format zecimal nempachetat ; conversie la cod ASCII ; se salveaz cele dou cifre ; se tiprete cifra zecilor ; se tiprete cifra unitilor

Instruciuni de prelucrare la nivel de bit


Determinarea numrului de bii egali cu 1 dintr-o variabil. .model small .stack 100h .data lung_var equ 8 variabila dw lung_var dup (0acfh) nr_unitati db ? .code assume cs: @code, ds: @data start: mov ax, @data mov ds, ax mov si, 0 ; indexul curent al cuvintelor din variabila mov dl, lung_var ; contor numr de cuvinte mov bl, 0 ; contor numr de uniti gsite bucla2: mov cx, 16 ; contorul de bii pentru un cuvnt mov ax, variabila[si] ; se citete cuvntul curent bucla1: rcl ax, 1 ; o rotaie pentru a deplasa un bit adc bl, 0 ; se contorizeaz numrul de uniti loop bucla1 ; pentru un cuvnt add si, type variabila ; se actualizeaz indexul dec dl ; se testeaz dac mai sunt cuvinte jnz bucla2 ; dac da se reia citirea cuvintelor mov nr_unitati, bl ; dac nu se depune rezultatul mov ax, 4C00h ; revenire DOS int 21h end Aceeai problem poate fi rezolvat utiliznd instruciunile BSF i BTR, astfel:

mov cx, lung_var ; contor dimensiune variabil mov bl, 0 ; contor uniti mov si, 0 ; index cuvinte bucla: mov ax, variabila[si] scanare: bsf dx, ax ; determin primul bit 1 (indexul n DX) jz gata_cuv ; dac ZF=0, toi biii sunt 0 btr ax, dx ; transfer 1 din AX, din poziia DX n CF, adc bl, 0 ; iar bitul =0, sau inc bl, numr unitile jmp scanare ; se reia scanarea cuvntului curent gata_cuv: add si, 2 ; indexul cuvntului urmtor loop bucla ; decrementare contor numr de cuv. variabil ; dac nu s-a terminat variabila ia cuv. urmtor Tiprirea coninutului registrului DX, n format octal: tip_car proc far ; procedura tiprete caracterul al crui cod ASCII ; l primete n registrul AL push dx ; se salveaz registrul de lucru DX mov dl, al ; se apeleaz funcia 2 din DOS care mov ah, 2 ; tiprete caracterul al crui cod int 21h ; ASCII se transmite n registrul DL pop dx ; se reface registrul salvat ret tip_car endp tip_octal proc far ; tiprete n octal valoarea, fr semn transmis n DX push cx ; se salveaz registrele de lucru push ax ; prima cifr de tiprit este doar de 1 bit rol dx, 1 ; care este rotit pe ultimul bit mov al, dl ; i dus n registrul AL and al, 1 ; se terg ceilali bii add al, 30h ; este convertit la codul ASCII call tip_car ; i se tiprete ; urmtoarele 5 cifre sunt de cte 3 bii mov cx, 5 ; contor numr de cifre de tiprit octal1: push cx ; se salveaz contorul n stiv mov cl, 3 ; contor numr de rotiri la stnga rol dx, cl ; cifra este rotit pe ultimii 3 bii mov al, dl ; i adus n AL and al, 7 ; sunt teri ceilali bii add al, 30h ; i convertit la codul ASCII call tip_car ; tiprirea cifrei

pop loop pop pop ret tip_octal

cx octal1 ax cx endp

; se citete valoarea contorului de cifre ; se refac registrele salvate n stiv

Instruciuni de operare pe iruri


Copierea unui ir de octei dintr-o zon de memorie ntr-alta. date_sir segment word public 'data' sir1 db 1000 dup (7,0f0h) ; irul surs lung1 equ $ - sir ; lungimea irului surs sir2 db 1000 dup (2 dup (?)) ; rezervare pt. ir dest. ptr_sir1 dd sir1 ; pointer sir1 ptr_sir2 dd sir2 ; pointer sir2 date_sir ends cod segment word public 'code' assume cs:cod, ds:date_sir, es:date_sir start: mov ax, date_sir ; iniializare registru segment DS mov ds, ax ; i apoi adresele celor dou iruri mov es, ax ; sau: les di,ptr_sir2 lea di, sir2 ; lds si,ptr_sir1 lea si, sir1 mov cx, lung1 ; contorul transferului = lungimea sursei cld ; direcia de parcurgere a irului (df=0) repeta: lodsb stosb ; sau: movs sir2,sir1 , sau movsb loop repeta ; sau: rep movsb mov ax, 4c00h ; revenire DOS int 21h cod ends end start Determinarea poziiei unui anumit caracter (sau a unui ir de caractere) ntr-un fiier surs de pe disc. .model small .stack 10h .data car equ 'A ; caracterul de identificat (sau irul) lung equ 2048 ; dimensiunea maxim a fiierului-4 sectoare buffer db lung dup (?); spaiu de mem. pentru fiier nume_fis db 'fisier.asm', 0 ; nume fii.- ASCIIZ, adic dup ; numele poate fi precedat i de calea de acces

pozitie dw ? ; poziia caracterului n fiier nr_logic dw ? ; numrul logic atribuit fiierului contor dw ? ; numrul efectiv de caractere citite mes_lipsa db 'nu exista fisier cu acest nume$' mes_err_cit db 'eroare de citire de pe disc$' mes_car_lipsa db 'caracterul cautat nu este in fisier$' .code start: mov ax, @data ; iniializare DS mov ds, ax mov ah, 3dh ; apel DOS pentru deschidere de fiier mov al, 0 ; n modul "citete" (1-scrie,2-citire/scriere) lea dx, nume_fis ; adresa numelui fiierului int 21h ; apel funcie 'deschide fiier' jc lipsa_fis mov nr_logic, ax ; se depune numrul sectorului mov bx, ax ; i n BX, pentru funcia de citire mov cx, lung ; contor numr maxim de caractere citite lea dx, buffer ; adresa unde se vor depune caracterele mov ah, 3fh ; funcia de citire din fiier int 21h jc err_cit ; dac a aprut eroare al citire mov contor, ax ; la 'contor' se depune numrul de car. mov cx, ax ; contor de cutare 'car' push ds ; se ncarc n ES adresa de segment pop es ; a 'buffer'-ului lea di, buffer ; i n registrul (DI) offsetul acestuia mov al, car ; caracterul de cutat cld ; stabilire direcie de parcurgere, (DF)=0 repne scasb ; continu scanarea pn-l gsete je gasit ; dac nu s-a gsit nu se face saltul lea dx, mes_car_lipsa ; i se tiprete mesajul mov ah, 9 ; mesajul: 'caracterul cautat nu este in fisier' int 21h jmp gata gasit: dec di ; poziia caracterului cutat, (DI)-1 mov pozitie, di ; deoarece (DI) a fost actualizat dup jmp ; scanare lipsa_fis: lea dx, mes_lipsa ; nu s-a gsit fiierul cu mov ah, 9 ; numele specificat int 21h jmp gata err_cit: lea dx, mes_err_cit ; eroare la citirea fiierului mov ah, 9 int 21h

gata

gata: mov ah, 3eh ; nchiderea fiierului deschis mov bx, nr_logic int 21h mov ax, 4c00h ; revenire DOS int 21h end start Determinarea poziiei unui ir de caractere ntr-un fiier: sir_cardb 'asamblare' lung_sir dw $-sir_car ptr_sir dd sir_car ptr_buf dd buffer pozitie dw ? ; poziia irului de caractere ................... les di, ptr_buf lds si, ptr_sir mov cx, contor ; dimensiune buffer sub cx, lung_sir ; cutarea se va face ncepnd de la 0 inc cx ; pn la (contor) - (lung_sir) cld ; direcia de parcurgere (DF=0) reia: push si; se salveaz adresa irului cutat push di ; se salveaz adresa irului n care se cut push cx; se salveaz contorul numrului maxim de cutri mov cx, lung_sir ; contorul de comparaii repe cmps buffer, sir_car ; se compar ct timp sunt egale pop cx ; reface resurse salvate n stiv: contorul pop di ; i adrese iruri: destinaie - irul n care se pop si ; caut, surs (sub)irul care se caut je gasit ; salt dac s-a gsit sir_car n buffer inc di ; cutarea se va relua de la urmtorul caracter loop reia ; din buffer, dac (contor) <> 0 ; -> irul de caractere nu este n fiierul dat (respectiv n buffer) jmp nu_gasit gasit: mov pozitie, di ; valoarea salvat pentru (DI) ................... nu_gasit: ; tiprire mesaj: Nu s-a gasit sirul de caractere

Instruciuni de transfer al controlului programului


Programul urmtor execut diferite secvene de program, n funcie de opiunea utilizatorului, introdus de la tastatur. .model small .data executie db 0Dh, 0Ah, 'Executa secventa (1,2,3 sau 4=stop):$' mes_secv1 db 'S-a executat secventa 1',0dh,0ah,'$' mes_secv2 db 'S-a executat secventa 2',0dh,0ah,'$'

mes_secv3 tab_secv

db label dw dw dw dw

'S-a executat secventa 3',0dh,0ah,'$' word secv1 secv2 secv3 gata

.code start: mov ax, @data ; iniializare adresa de segment mov ds, ax iar: lea dx, executie ; solicit secvena dorit, utilizatorului mov ah, 9 ; se tiprete mesajul de selecie secven int 21h ; apel funcia 9, tiprire mesaj mov ah, 1 ; apel funcia 1, citire caracter int 21h ; caracter returnat n AL sub al, 31h ; intervalul '1''4' -> 03 i verific dac jc iar ; este n intervalul 03: dac nu, cere cmp al, 4 ; o valoare, n acest interval, fr a executa jnc iar ; vreuna dintre secvene cbw ; extensie pe 16 bii mov bx, ax shl bx, 1 ; *2, pentru a obine adresa relativ jmp word ptr tab_secv[bx] ; n tabela cu adr. secvene secv1: lea dx, mes_secv1; se execut prima secven mov ah, 9 int 21h jmp short iar secv2: lea dx, mes_secv2; se execut a doua secven mov ah, 9 int 21h jmp short iar secv3: lea dx, mes_secv3; se execut a treia secven mov ah, 9 int 21h jmp short iar gata: mov ax, 4c00h ; revenire DOS int 21h .stack 20h end Instruciuni de transfer control, condiionat Determinarea valorii maxime dintr-un ir de valori (cu semn). .model small .stack 10h .data sir db 10,20,-30,100,-100,200

lung dw $-sir maxim db ? mes_sir_vid db .code mov mov mov jcxz lea cld mov inc dec jcxz lodsb cmp jge ax, @data ds, ax cx, lung sir_vid si, sir

'sir vid de valori$' ; iniializare registru segment

; contor numr de valori din ir ; dac irul este vid se tiprete mesaj ; index elemente din ir ; direcia de parcurgere bl, [si] ; se iniializeaz valoarea maxim din ir si ; actualizare index elemente cx ; actualizare contor gata ; dac a fost un singur element s-a terminat iar: ; citete element curent din ir bl, al ; se compar cu maximul curent urm ; dac max > val. curent trece la elem. urmtor ; pentru numere fr semn se nlocuiete jge cu jnc mov bl, al ; altfel se actualizeaz valoarea maxim urm: loop iar ; se reia ciclul dac mai sunt elem. n ir gata: mov maxim, bl ; se depune valoarea maxim iesire: mov ax, 4c00h ; revenire DOS int 21h sir_vid: lea dx, mes_sir_vid ; se tiprete mesajul mov ah, 9 ; 'sir vid de valori' int 21h jmp iesire ; revenire DOS end Instruciuni de ciclare Calculul sumei elementelor unui ir de tip cuvnt. mov cx, lung_sir ; contor numr de elemente mov ax, 0 ; suma va fi pe dou cuvinte mov bx, ax ; i se iniializeaz cu 0 mov si, ax ; index pentru adresarea elementelor aduna: add ax, sir[si] adc bx, 0 ; transporturile se acumuleaz n BX add si, type sir ; actualizare index loop aduna ; dac nu e gata se reia adunarea mov suma, ax ; se depune rezultatul, ncepnd cu mov suma[2], bx ; cu cuvntul mai puin semnificativ Determinarea primului element diferit de 0, dintr-un ir. mov cx, lung_sir ; contorul irului

mov si, -1 ; iniializare SI reia: inc si cmp sir[si], 0 ; se compar cu 0 loope reia ; dac este 0 se reia comparaia jz sir_zero ; dac ZF=1, tot irul conine numai 0 aici: ; s-a determinat primul element <> 0, la adresa SI Determinarea ultimului element dintr-o list nlnuit. Ultimul element dintr-o list va conine valoarea zero n cmpul de adres. lea bx, offset cap_lista ; adresa de nceput a listei mov cx, N ; dimensiunea maxim a listei urm: mov bx, [bx + lung_info] ; adresa elementului urmtor cmp bx, 0 ; se compar cu 0 loopne urm ; se reia dac nu s-a gsit je gasit ; s-a gsit ultimul element din list, adr. n BX ; dac nu se execut saltul nu s-a gsit ultimul element printre cele N elemente

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

27. Definirea i utilizarea procedurilor.

Definirea i utilizarea procedurilor


O procedur este constituit dintr-o secven de instruciuni, care poate fi apelat ori de cte ori este nevoie, i se declar folosind urmtoarea sintax: nume_procedura proc . < corpul procedurii > . ret endp [ near / far ]

nume_procedura

Parametrii (datele de intrare) pot fi transmii n diferite moduri:


prin registre; aceast modalitate poate avea, ns, urmtoarele dezavantaje: neconvenabil, dac se transmit un numr mare de parametri, caz n care numrul registrelor poate fi insuficient, sau neeconomic sub aspectul timpului de execuie, necesitnd frecvente salvri i refaceri de registre. prin memorie, care presupune rezervarea de memorie pentru aceti parametri, deci poate fi neeconomic din punct de vedere al spaiului de memorie ocupat (pentru structuri mari de date), mai ales dac astfel de date sunt necesare doar temporar; prin stiv, care este metoda cea mai avantajoas, ntruct permite accesul uor la informaie (cu instruciunile PUSH, respectiv POP), iar dup utilizare memoria alocat n acest scop este eliberat, deci zona respectiv de memorie devine disponibil. n cazul transmiterii parametrilor prin stiv, aceasta trebuie manipulat cu atenie de ctre procedur, astfel nct, n final, n vrful stivei s se gseasc adresa de revenire, pentru a se executa corect ultima instruciune din procedur: RET.

n ceea ce privete parametrii transmii prin stiv, acetia pot fi:


valoare, se transmite valoarea parametrului; adres, se transmite adresa parametrului, deci operaiile descrise de procedur se vor efectua direct asupra parametrului respectiv; n acest caz, procedura nu mai trebuie s returneze programului apelant parametrul respectiv.

n ceea ce privete returnarea parametrilor, aceast operaie se poate realiza utiliznd una din metodele folosite pentru transmiterea parametrilor ctre procedur, descrise anterior (registre, memorie sau stiv). n general, pentru definirea unei proceduri se parcurg urmtoarele etape:
stabilirea prelucrrilor efectuate de procedur; definirea datelor de intrare/ieire, precum i a modului de transmitere a parametrilor (registre, memorie sau stiv); definirea tipului procedurii (NEAR/FAR), mai ales dac parametrii se transmit prin stiv, situaie n care trebuie determinat poziia acestora n stiv; pentru directivele simplificate de segmentare nu este necesar precizarea tipului procedurii,

deoarece tipul este determinat de asamblor, din directiva MODEL; dac n procedur se utilizeaz nume simbolice, pentru a obine n mod corect accesul la acestea trebuie salvat DS n stiv, dup care se ncarc noua valoare i se folosete directiva ASSUME pentru a preciza asocierea segmentului la DS, iar la sfrit se reface registrul DS cu valoarea din stiv. nainte de orice prelucrare trebuie salvate n stiv registrele utilizate de procedur, iar nainte de revenirea n programul apelant, acestea trebuie restaurate. 1) Programul adun cte dou numere de la adrese succesive, i depune suma la locaiile imediat urmtoare. valori segment lista1 db 25 db 37 db ? lista2 db 27 db 35 db ? ........ valori ends stiva segment dw 4 dup (?) varf_stiva label word stiva ends adunare segment assume cs:adunare, ds:valori, ss:stiva mov ax, valori mov ds, ax mov ax, stiva mov ss, ax mov sp ,offset varf_stiva lea si, lista1 call aduna ; se adun elementele din prima list jc depasire ; dac apare transport se semnaleaz ....... lea si, lista2 call aduna ; se adun elementele din lista2 jc depasire ...... depasire: . . . . . ; tiprire mesaj de depire mov ax, 4c00h int 21h aduna proc push ax mov al, [si] ; primul element din list add al, [si+1] ; se adun cu urmtorul mov [si+2], al ; i se depune rezultatul n continuare pop ax

ret aduna endp adunare ends end 2) Adunarea elementelor unui vector, de orice lungime, cu pstrarea rezultatului n acumulator. Procedura primete n BX - adresa vectorului, iar n CX - lungimea sa, returneaz suma n AX. date_vectori segment vector1 db 6, 63, 100, 123, -134, 112, 77 contor1 equ $ - vector1 rezultat1 dw ? ....... date_vectori ends dv equ <date_vectori> pg equ <procedura_generala> procedura_generala segment assume cs:pg, ds:dv aduna proc push si ; se salveaz registrul de adresare vector mov ax, 0 ; se iniializeaz suma cu 0 mov si, 0 ; iniializare index componente vector reia: add al, [bx][si] ; adunare element curent adc ah, 0 ; se contorizeaz transporturile jc gata ; dac apare depire se termin procedura inc si ; actualizare index vector loop reia ; dac nu s-a terminat vectorul, se reia gata: pop si ; se reface registrul salvat ret aduna endp start: mov ax, dv mov ds, ax mov cx, contor1 ; contorul pentru primul vector lea bx, vector1 ; adresa de start a vectorului call aduna ; apel procedura de adunare mov rezultat1, ax ; se depune rezultatul jc depasire ; pt. depire se afieaz mesaj ....... depasire: . . . . . . ; afiare mes. de depire dim. rez. mov ax, 4c00h int 21h procedura_generala ends end start 3) Se va rescrie exemplul anterior utiliznd, n acest caz, pentru transmiterea parametrilor, stiva. Deci prin stiv se va transmite: adresa rezultatului, adresa vectorului i lungimea acestuia. date segment

vector1 db 6, 63, 100, 123, -134, 112, 77 contor1 equ $ - vector1 rezultat1 dw ? vector2 db 16, 163, 101, 232, -144, 26, -79 contor2 equ $ - vector2 rezultat2 dw ? ....... mes_depasire db eroare-depasire dimensiune rezultat, 0dh, $ date ends stiva segment stack 'stack' dw 20 dup (?) stiva ends utilizare_stiva segment assume cs:utilizare_stiva, ds:date, ss:stiva aduna proc far push bp ; se salveaz valoarea lui BP, pentru acces mov bp, sp ; la parametrii din stiv push bx ; se salveaz registrele de lucru push cx mov cx, [bp+6] ; CX = lungime vector mov bx, [bp+8] ; BX = adresa de nceput a vectorului mov ax, 0 ; iniializare sum reia: add al, [bx] ; adun elementul curent adc ah, 0 ; actualizare transport jc iesire ; dac apare depire se termin procedura inc bx ; actualizare index vector loop reia ; dac mai sunt elemente se reia adunarea mov bx, [bp+10] ; se citete adresa rezultatului, din stiv mov [bx], ax ; i se depune rezultatul la aceast adres iesire: ; Adrese mici pop cx ; CX - salvat pop bx ; BX - salvat pop bp ; BP - salvat [BP] ; IP - revenire ; CS - revenire ; contor1 [BP+6] ; offset vector1 [BP+8] ; offset rezultat1 [BP+10] ; Adrese mari ret 6 ; descrcarea stivei de parametrii (cei 6 octei) aduna endp utilizare_stiva endsaduna_date segment assume cs:aduna_date, ds:date, ss:stiva start: mov ax, date mov ds, ax

0ah,

lea ax, rezultat1 ; adresa rezultatului se push ax ; depune n stiv lea ax, vector1 ; adresa de nceput a vectorului push ax ; se depune n stiv mov ax, contor1 ; lungimea vectorului se push ax ; se depune n stiv call aduna ; se adun elementele primului vector jc eroare_add ; depire dim. rezultat (de tip cuvnt) ...... lea ax, rezultat2 ; adresa rezultatului se push ax ; depune n stiv lea ax, vector2 ; adresa de nceput a vectorului push ax ; se depune n stiv mov ax, contor2 ; lungimea vectorului se push ax ; se depune n stiv call aduna ; se adun cel de-al doilea vector jc eroare_add ; depire dim. rezultat (de tip cuvnt) ...... eroare_add: ; se va tipri un mesaj de eroare lea dx, mes_depasire mov ah, 9 int 21h mov ax, 4c00h int 21h aduna_date ends end start 4) Procedur pentru citirea unui numr zecimal ntreg, caractere ASCII, i convertirea numrului la o valoare ntreag, pe 16 bii. ; conversie zecimal (ASCII) binar (16 bii), rez. n AX. ; numrul este citit cifr cu cifr, termin citirea cu un caracter ; care nu este cifra ASCII, adic nu este n intervalul '0''9', ; sau dac s-au citit 5 cifre (val. maxim pe 16 bii ; este 65535); se citete un numr de forma: cncn-1...c1c0 ; valoarea sa n orice baz este: cn*bn+cn-1*bn-1+...+c1*b+c0 ; care se poate scrie: (...((cn*b+cn-1)*b+cn-2)*b+...+c1)*b +c0 ; deci relaia de calcul este val = val * baza + cifra zecbin proc far push bx ; se salveaz registrele de lucru push cx push dx mov cx, 5 ; numrul maxim de cifre ale numrului xor dx, dx ; iniial val = 0 mov bx, 10 ; baza n care se citete numrul reia_cit: mov ah, 1 ; citire cu ecou de la tastatur int 21h

sub al, 30h ; domeniul '0''9' se transform n 09 jb gata_cit ; dac nu este n intervalul 09 cmp al, 9 ; s-a terminat citirea cifrelor ja gata_cit mov ah, 0 ; extensie semn '+' pt. cifra citit push ax ; salvare ultima cifr citit mov ax, dx ; (AX) = val mul bx ; (DX,AX) = val * baza pop dx ; ultima cifr (valoare) citit jc gata ; dac apare depire, CF=1, i se termin add dx, ax ; val = val * baza + cifra jc gata ; eroare, (CF=1), depire rez. (65535) loop reia_cit ; nu s-au citit 5 cifre, continu citirea gata_cit: clc ; ieire normal, fr eroare, (CF=0) mov ax, dx ; depunerea rezultatului n (AX) gata: pop dx ; refacere registre salvate pop cx pop bx ret zecbin endp Programul care apeleaz procedura va testa starea indicatorului CF; dac (CF) = 1, eroare ; dac (CF) = 0, rezultatul conversiei n AX.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

28. Transferul parametrilor pentru proceduri n limbaj de asamblare.

Transferul parametrilor pentru proceduri


Parametrii (datele de intrare) pot fi transmii n diferite moduri: prin registre; aceast modalitate poate avea, ns, urmtoarele dezavantaje: neconvenabil, dac se transmit un numr mare de parametri, caz n care numrul registrelor poate fi insuficient, sau neeconomic sub aspectul timpului de execuie, necesitnd frecvente salvri i refaceri de registre. prin memorie, care presupune rezervarea de memorie pentru aceti parametri, deci poate fi neeconomic din punct de vedere al spaiului de memorie ocupat (pentru structuri mari de date), mai ales dac astfel de date sunt necesare doar temporar; prin stiv, care este metoda cea mai avantajoas, ntruct permite accesul uor la informaie (cu instruciunile PUSH, respectiv POP), iar dup utilizare memoria alocat n acest scop este eliberat, deci zona respectiv de memorie devine disponibil. n cazul transmiterii parametrilor prin stiv, aceasta trebuie manipulat cu atenie de ctre procedur, astfel nct, n final, n vrful stivei s se gseasc adresa de revenire, pentru a se executa corect ultima instruciune din procedur: RET. n ceea ce privete parametrii transmii prin stiv, acetia pot fi: valoare, se transmite valoarea parametrului; adres, se transmite adresa parametrului, deci operaiile descrise de procedur se vor efectua direct asupra parametrului respectiv; n acest caz, procedura nu mai trebuie s returneze programului apelant parametrul respectiv. n ceea ce privete returnarea parametrilor, aceast operaie se poate realiza utiliznd una din metodele folosite pentru transmiterea parametrilor ctre procedur, descrise anterior (registre, memorie sau stiv). n general, pentru definirea unei proceduri se parcurg urmtoarele etape: stabilirea prelucrrilor efectuate de procedur; definirea datelor de intrare/ieire, precum i a modului de transmitere a parametrilor (registre, memorie sau stiv); definirea tipului procedurii (NEAR/FAR), mai ales dac parametrii se transmit prin stiv, situaie n care trebuie determinat poziia acestora n stiv; pentru directivele simplificate de segmentare nu este necesar precizarea tipului procedurii, deoarece tipul este determinat de asamblor, din directiva MODEL; dac n procedur se utilizeaz nume simbolice, pentru a obine n mod corect accesul la acestea trebuie salvat DS n stiv, dup care se ncarc noua valoare i se folosete directiva ASSUME pentru a preciza asocierea segmentului la DS, iar la sfrit se reface registrul DS cu valoarea din stiv. nainte de orice prelucrare trebuie salvate n stiv registrele utilizate de procedur, iar nainte de revenirea n programul apelant, acestea trebuie restaurate.

n ceea ce privete programele scrise n limbaje de nivel nalt, acestea folosesc anumite convenii pentru transmiterea parametrilor ctre subprograme. Compilatorul translateaz o instruciune de apel a unui subprogram astfel: depune n stiv (push) argumentele subprogramului i apeleaz apoi subprogramul cu o instruciune de apel (call). n funcie de compilator, argumentele sunt puse n stiv ntr-o anumit ordine. n cazul n care se leag o procedur scris n limbaj de asamblare cu un program scris ntr-un limbaj de nivel nalt, trebuie cunoscut modul de

transmitere a parametrilor i conveniile stabilite de limbajul respectiv pentru apel de subprogram (nume externe, valori returnate). Parametrii pot fi transmii la subprograme prin valoare sau prin referin: la transmiterea prin valoare se va depune n stiv o copie a argumentelor; modificrile efectuate asupra acestor valori nu se vor regsi n parametrii efectivi din procedura apelat. Rezultatele vor fi cunoscute doar dac vor fi comunicate; la transmiterea prin referin, se depune n stiv adresa (pointerul) argumentului (de tip NEAR sau FAR, dup locul n care se afl procedura apelat). n acest caz, modificrile se vor efectua direct asupra argumentelor ce aparin programului apelant. n Pascal i n C se cunosc ambele mecanisme de transmitere a parametrilor. Limbajele de nivel nalt folosesc urmtoarele registre pentru returnarea de valori ctre programul apelant: (AL) valori de un octet; (AX) valori de doi octei sau adres de tip NEAR; (EAX) valori de 4 octei sau adres de tip NEAR la 386/486; (DX,AX) valori de 4 octei sau pointer FAR, pentru 286; (EDX,EAX) valori de 8 octei sau pointer FAR, pentru 386/486; Pentru valori mai mari de 4 octei, limbajul C consider c valoarea este returnat n zona de memorie alocat pentru segmentul de date i ntoarce n (DX:AX) pointerul ctre acea zon. Limbajul PASCAL rezerv o zon de date n stiv: zona rezervat n stiv i offsetul ctre aceasta se realizeaz de ctre programul apelant; procedura returneaz n (DX:AX) pointerul ctre aceast zon. Descrcarea stivei se face n programul apelant, procedura terminndu-se cu RET; la descrcarea unor argumente, se poate termina cu RET numr_argumentedimensiune. Deci, n principiu, programul apelant realizeaz operaiile: depune argumentele n stiv; apeleaz procedura; descarc stiva. Variabilele locale ntr-o procedur se folosesc pentru a economisi spaiu de memorie (cu meniunea c valorile lor nu se transmit n afara procedurii). Spaiul de memorie necesar pentru variabilele locale se rezerv n stiv i este eliberat la terminarea execuiei procedurii. Alocarea de spaiu pentru variabilele locale se realizeaz cu o secven de forma: Salvare registre de lucru Variabile locale Salvare (BP) Adresa de revenire n program Argumente transmise procedurii unde n = numr de octei alocai. Pentru accesul la variabilele locale se vor utiliza adresri de forma [BP 2], [BP 6] etc. iar pentru argumente, de forma: [ BP + 2 ], [ BP + 4 ], etc. push bp mov bp,sp sub sp,n

Iat un exemplu de adresare la un argument transmis prin stiv i la o variabil local, ntr-o procedur de tip FAR: argument var_loc p1 equ equ proc push mov sub .......... mov add .......... mov pop ret <[bp+6]> <[bp-2]> far bp bp,sp sp,2 ax,argument var_loc,ax sp,bp bp endp ; salvare valoare BP ; initializare cu varful curent al stivei ; rezervare spatiu pentru var_loc, 2 octeti ; se ia argumentul transmis prin stiva ; utilizarea variabilei locale ; eliberarea spatiului rezervat var_loc ; refacerea valorii lui BP ; sau ret 2, daca se descarca stiva in procedura

p1

Dac descrcarea stivei nu se face n procedur, atunci n programul apelant trebuie descrcat stiva cu add sp,2.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

29. Transferul parametrilor pentru proceduri n limbajele de nivel nalt.

Transferul parametrilor pentru proceduri n limbaje de nivel nalt


n cazul limbajului PASCAL, depunerea parametrilor n stiv se face n ordinea n care acetia apar n lista de parametri efectivi, la apelul procedurii (adic ordinea n care au fost specificai parametrii formali la definirea procedurii, deci de la stnga la dreapta). Revenirea din procedur se face cu o instruciune de forma RET n, pentru a descrca stiva, unde n este numrul de octei ocupai de argumentele din stiv. S considerm o procedur definit n PASCAL: procedure begin ...... end; iar apelul de forma: modul (x, y); Pentru aceast procedur se va genera secvena: push bp mov bp,sp ...... mov ax,[bp+8];(AX) x ...... les di,[bp+4] ;(ES):(DI) adresa lui y ...... n final, se va descrca stiva: pop bp ret 6 modul (a : integer; var b : real);

BP salvare BP +2 +4 +6 +8 adresa de revenire adr_off var. b adr_seg var. b valoarea var. a

Pentru apelul acestei proceduri, se va genera secvena urmtoare: mov push mov push push call ax,x ax di,offset y ds di modul

; se depune in stiva valoarea parametrului x ; se depune adresa de segment a parametrului y ; se depune offsetul parametrului y ; apelul procedurii

Spre deosebire de PASCAL, n limbajul C argumentele sunt puse n ordine invers fa de ordinea n care apar n lista de apel (adic de la dreapta la stnga). Adresele de revenire pot fi

de tip NEAR, ca n exemplul anterior, sau de tip FAR, n funcie de modul de definire al procedurii. Pointerii salvai n stiv ca referin de parametru sau ca adres de revenire respect definiia modelului de memorie stabilit n directiva model. De exemplu, aspectul pentru un singur argument este urmtorul: modelul medium push bp mov bp,sp mov di,[bp+6] mov ax,[di] ; acces argument ; tip cuvnt
modelul large

SP, BP salvare bp + 2 adresa revenire - offset adresa revenire - segment + 6 adresa argument

push bp mov bp,sp les di,[bp+6] mov ax,es:[di]; acces argument ; tip cuvnt

SP, BP salvare bp + 2 adresa revenire - offset adresa revenire - segment + 6 adresa argument offset adresa argument segment

Pentru a nu modifica prea multe linii, n funcie de modelul utilizat se pot folosi directivele de asamblare condiionat; de exemplu, pentru cazul anterior se poate defini o constant, astfel: Ptr_FAR equ 1 ........ ........ push bp mov bp,sp ........ ifdef Ptr_FAR les di,[bp+6] mov ax,es:[di] else mov di,[bp+6] mov ax,[di] endif care, dac este definit, va considera modelul large, iar dac nu este definit va considera modelul medium.

Transferul parametrilor pentru subprograme n PASCAL i C


S scriem, pentru exemplificare, un program simplu n Pascal, care citete doi vectori, de aceeai lungime i schimb ntre ei i apoi i afieaz. Vom scrie procedura care schimb ntre ei cei doi vectori n limbaj de asamblare.

program schimba_vectori; type tip_vector = array [1..20] of real; var vector1, vector2 : tipsir; n,i : integer; {$F+} {$L SCHIMB.OBJ} procedure InterSchimb (var v1, v2 : tipsir; lung: word); External; begin { se citesc : dimensiunea si cei doi vectori } InterSchimb (vector1, vector2, sizeof(vector1)); { se afiseaza cei doi vectori dupa interschimbare } end. Directiva de compilare {$F+} Force FAR calls precizeaz c n cadrul codului generat pentru apeluri de proceduri i funcii se folosete modelul FAR (utiliznd acest tip, o procedur poate fi apelat de oriunde din memorie). Dac directiva este dezactivat {$F-}, compilatorul determin automat codul care trebuie generat pentru o instruciune de apel, n funcie de tipul apelului, n interiorul sau n afara segmentului curent. Compilatorul, utiliznd opiunea {$F+}, presupune c rutina se gsete n al t segment, i c orice parametru variabil utilizat de rutin este menionat prin adresele de segment i offset. Directiva {$L nume_fiier} Link object file impune ca pentru un fiier s fie editate legturile mpreun cu programul compilat. Fiierul pentru care se editeaz legturile trebuie s fie n format .OBJ; extensia de nume este implicit. irul de caractere care specific fiierul poate conine i directoarele (calea) de acces ctre fiier. Procedura Interschimb, care se afl n fiierul SCHIMB.OBJ, este urmtoarea: .model TPascal model large,Pascal .code public InterShimb InterSchimb proc far stiva struc val_BP dw IP_rev dw CS_rev dw ? lung dw ? offs_sir1 dw ? seg_sir1 dw ? offs_sir2 dw ? seg_sir2 dw ? stiva ends ; sau

? ?

; sau adr_rev

dd

; sau adr_sir1 ; sau adr_sir2

dd dd

? ?

push mov push push push push push push mov mov mov mov mov iar: mov xchg mov inc inc loop pop pop pop pop pop pop ret InterSchimb end

bp bp, sp ds ; se salveaza registrele de lucru si es di ax cx ; urmeaza initializarile de adrese si contor es, [bp].seg_sir1 ; sau les di, [bp].adr_sir1, sau di, [bp].offs_sir1 ; les di, [bp+8] ds, [bp].seg_sir2 ; sau lds si, [bp].adr_sir2, sau si, [bp].offs_sir2 ; lds si, [bp+12] cx, [bp].lung ; sau mov cx, [bp+6] al, ds:[si] al, es:[di] ds:[si], al si di iar cx ; refacerea registrelor salvate in stiva ax di es si ds 10 ; se descarca stiva de cei 10 octeti endp

Linia de declarare a procedurii poate fi i de forma: InterSchimb proc far Ad_sir1:dword,Ad_sir2:dword,lung:word iar n acest caz, preluarea parametrilor se poate face i mai simplu: les lds mov di,Ad_sir2 si,Ad_sir1 cx,lung

pentru care asamblorul va genera o secven asemntoare celei prezentate n procedur. Modalitatea de definire i utilizare a unei structuri este definit n paragraful urmtor. Vom prezenta n continuare i modul de definire i utilizare a unei funcii n Pascal; funcia prezentat va nsuma elementele unui ir de tip word (integer), fr a lua n considerare eventualul transport; dac dorim, putem s reprezentm rezultatul pe un format dublu (longint),

contoriznd n registrul DX eventualele transporturi, iar rezultatul poate fi returnat n perechea DX,AX, n loc de AX. Vom utiliza i o variabil local, cu toate c n acest caz este inutil, doar pentru a prezenta modul de definire i utilizare a acesteia n programul principal, la fel ca n exemplul anterior. Funcia va fi definit astfel: function Suma (sir: tip_vector; n:word):integer;External; .model large, Pascal public Suma .code Suma proc far adr_sir equ <[bp+8]> n equ <[bp+6]> s equ <[bp-2]> ; variabila locala pentru suma push bp mov bp, sp sub sp, 2 ; rezervare spatiu pentru variabila locala s push ds ; salvarea registrelor de lucru push si push cx lds si, adr_sir ; initializare adresa, contor si suma mov cx, n mov ax, 0 mov s, ax cld ; directia de parcurgere a sirului jcxz gata ; in cazul n care contorul a fost 0, s-a terminat adun: lodsw add s, ax loop adun gata: mov ax, s pop cx pop si pop ds mov sp, bp ; eliberarea spatiului alocat variabilei locale s pop bp ret 6 ; descarcarea stivei de parametri Suma endp end S considerm, acum, i cazul limbajului C. Vom rescrie funcia anterioar, suma(), care va fi apelat din funcia main(). ntruct codul generat de compilatorul C transform denumirile parametrilor funciei suma(), adugnd caracterul _ la nceput, codul modulului apelat cu numele suma() se va numi de fapt _suma(); acelai lucru se ntmpl i pentru ceilali parametri utilizai n ambele module, n sensul c parametrii din C utilizai i n modulul scris n limbaj de asamblare vor fi precedai, n limbaj de asamblare, de caracterul _. Modulul n limbaj de

asamblare trebuie s salveze, la nceputul su, i s refac, la sfrit, valorile coninute de registrele BP, SP, CS, DS, SS, DI i SI, dac programul utilizeaz aceste registre. .model small, C public _suma .code public _suma _suma proc push bp mov bp, sp push cx push ds push si mov cx, [bp+8] lds si, [bp+4] mov ax, 0 ; initializarea sumei cu 0 aduna: add ax, [si] add si, 2 loop aduna pop si pop ds pop cx pop bp ret _suma endp end #include <stdio.h> int suma (int vect[], int dim); void main(void) { int i, dim, vect[100]; printf(Numarul de elemente din vector:); scanf(%d, &dim); printf(Elementele vectorului:\n); for (i=0; i<dim; i++) { printf(vect[%d]=, i+1); scanf(%d, &vect[i]); } printf(Suma elementelor vectorului este: %d\n, suma(vect, dim)); }

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

30. Proceduri recursive.

Proceduri recursive (reentrante)


O procedur care se apeleaz pe ea nsi (direct sau indirect) se numete procedur recursiv (sau reentrant). Pentru ca apelul s fie corect este necesar ca procedura: s salveze n stiv indicatorii de condiii i registrele utilizate; datele referite s fie n registre sau n stiv, dar nu n memorie; s conin o condiie de oprire a apelului recursiv. Recursivitatea este utilizat cnd fie algoritmul, fie datele sunt descrise recursiv. 1) Procedura citete un ir de caractere (o linie de text) pe care, apoi, le tiprete n ordine invers: proc_scrie_inv proc mov ah, 1 ; citete un caracter int 21h cmp al, 0dh ; se compar cu sfrit de linie jnz citeste ; dac nu e sfrit linie citete caracter ret ; dac e sfrit linie procedura s-a terminat citeste: push ax ; se depune caracterul n stiv call proc_scrie_inv ; se apeleaz recursiv pop ax ; la revenire din apel se ia car. din stiv push dx ; salvare registru folosit pentru tiprire mov dl, al ; caracterul de tiprit se transmite n (DL) mov ah, 2 ; i se tiprete int 21h pop dx ; refacerea registrului ret proc_scrie_inv endp ((SS):(SP)) caracter-ASCII IP_rev_procedur ... caracter-ASCII IP_rev_procedur caracter-ASCII IP_rev_prog_principal Adrese mici

Adrese mari

2a) Procedur pentru calculul recursiv al factorialului. factorial proc ; procedura primete valoarea lui N n registrul AX ; rezultatul va rmne n registrul AX clc ; iniializare (CF=0), la intrarea n procedur, sau ; n prg. principal, nainte de apelul procedurii pushf ; salvare indicatori push dx ; i a registrului (DX), modificat de nmulire push bp

mov bp, sp ; iniializare (BP), pentru a lua, la revenire, K-ul cmp ax, 1 ; test de sfrit apel recursiv je gata_apel push ax ; se depune termenul curent, K, n stiv dec ax ; termenul urmtor din factorial, K-1 call factorial ; apelul recursiv jc poz_cf ; depirea de la apelul anterior se propag mul word ptr [bp-2] ; (AX) * (K-vrf_stiv) = (DX,AX) jnc cont ; dac nu a aprut depire, se continu poz_cf: or word ptr [bp+4], 1 ; poz. (CF=1, imaginea din stiv) cont: add sp, 2 ; descrcarea lui K, din vrful sivei gata_apel: pop bp ; refacerea registrelor salvate pop dx popf ; refacerea indicatorilor ret ; revenire din apel factorial endp Imaginea stivei: bp

bp bp

bp_vechi dx_vechi indicatori adr_rev_proc N-1 ... N bp_vechi dx_vechi indicatori adr_rev_prog_principal

2b) Procedur recursiv de calcul al factorialului, dar valoarea lui N se transmite prin stiv i se returneaz n registrul (AX). fact proc clc ; iniializare (CF=0), la intrarea n procedur sau ; n prog. principal, nainte de apelul procedurii pushf ; salvare indicatori i registre afectate push dx push bp mov bp, sp ; iniializare (BP), pentru a lua, la revenire, K-ul mov ax, [bp+8] ; citete valoarea lui N (K), din stiv cmp ax, 1 ; test sfrit apel recursiv je gata_apel dec ax ; se trece la elementul urmtor, N-1 (K-1)

push ax ; se depune acest termen n stiv call fact ; apelul recursiv jc poz_cf mul word ptr [bp+8] ; rez. nmulirii este n (DX,AX) jnc gata_apel poz_cf: or word ptr [bp+4], 1 ; poz. imaginii din stiv a lui (CF) gata_apel: pop bp ; refacere reg. salvate i a indicatorilor pop dx popf ret 2 fact endp Imaginea stivei pentru aceast procedur este urmtoarea: bp bp_vechi dx_vechi indicatori adr_rev_procedur 1 bp ... N-1 bp bp_vechi dx_vechi indicatori adr_rev_prog_principal N 2c) Procedura recursiv de calcul al factorialului, primete valoarea N prin stiv, i returneaz rezultatul, N!, tot prin stiv. facts proc clc ; iniializare (CF=0), la intrarea n procedur, sau ; n prog. principal, nainte de apelul procedurii pushf ; salvare indicatori push ax ; i registrele de lucru push dx ; afectat de nmulire push bp mov bp, sp ; ini. (BP), pentru a lua, la revenire, K-ul mov ax, [bp+10] ; citete valoarea lui N, din stiv cmp ax, 1 ; test sfrit apel recursiv je gata_apel dec ax ; se trece la elementul urmtor, N-1 push ax ; se depune acest termen n stiv call facts ; apelul recursiv pop ax ; extrage ultim. factorial, calculat, din stiv jc poz_cf

mul word ptr [bp+10] jnc gata_apel poz_cf: or word ptr [bp+6], 1 gata_apel: mov [bp+10], ax pop bp pop dx pop ax popf ret facts endp Imagine stiv: bp

; rezultatul nmulirii, K*f(K-1) ; este n (DX,AX) ; dep. rezultat n stiv

(N 1) <- (N-1)! bp_vechi dx_vechi ax_vechi indicatori adr_revenire_prog_principal N <- N!

3a) Proc. pentru afiarea unei valori din registrul AX n zecimal. conv_bin_zec proc ; procedura primete valoarea de convertit n registrul AX pushf ; se salveaz indicatorii i registrele de lucru push cx push dx mov cx, 10 ; mpritorul, utilizat pentru conversia xor dx, dx ; binar zecimal,(DX,AX) = demprit div cx ; resturile reprezint cifrele n zecimal mov cx, dx ; test condiie de sfrit: ctul i restul sunt 0 ? or cx, ax je gata_apel ; dac ctul i restul sunt 0, nu mai pun n stiv push dx ; depunere rest n stiv call conv_bin_zec ; dac ctul <> 0, apelez recursiv proc. pop dx ; citire rest din stiv add dl, 30h ; conversie la codul ASCII mov ah, 2 ; apel funcie 2, de tiprire caracter int 21h gata_apel: pop dx ; refacerea registrelor de lucru pop cx popf ; refacerea indicatorilor ret conv_bin_zec endp Configuraia stivei pentru acest apel este urmtoarea:

sp

adr_rev_procedur restul (DX) dx_vechi cx_vechi indicatori adr_rev_prog_principal

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

31. Programe compuse din mai multe module.

Programe compuse din mai multe module


Este posibil ns s dezvoltm un program care const dintr-un modul principal, legat (editate legturile) mpreun cu unul sau mai multe programe asamblate separat. Motivele organizrii programelor n subprograme sunt urmtoarele: - pentru a face legtura ntre diferite limbaje, pentru a combina uurina programrii n LNI cu eficiena de prelucrare a LA; - pentru a facilita dezvoltarea de proiecte mari, n care diferite echipe elaboreaz separat modulele lor; - pentru a suprapune pri ale unui program pe durata execuiei sale, datorit dimensiunii mari a programului. Programele de dimensiuni mai mari se mpart n mai multe module. Vom denumi modul, un program compus din unul sau mai multe segmente, cuprins ntr-un fiier. Fiecare modul este asamblat separat, genernd propriul su modul obiect. Editorul de legturi realizeaz apoi legarea modulelor obiect ntr-un singur modul executabil. Modulele trebuie s comunice ntre ele. n cazul simbolurilor, definite n cadrul unui modul, ce trebuie referite din alte module, acestea trebuie declarate 'PUBLIC', nmodulul unde sunt definite, i declarate 'EXTRN' : BYTE, WORD, DWORD, FWORD, QWORD, TBYTE - ptr. variabile ABS - pentru constante, NEAR, FAR, PROC - pentru etichete sau proceduri; pentru ultimul tip (PROC) asamblorul determin tipul procedurii. Deci la definire simbolurile se declar 'PUBLIC', iar la referire, din alt modul, se declar 'EXTRN. S considerm un program principal, scris ntr-un modul, care citete (cit_sir) un numr de la tastatur, n zecimal, i-l depune n memorie (sau stiv) sub forma unui ir de caractere ASCII (cel mult 5 cifre sau se va termina cu un caracter diferit de cifr), eventual i lungimea irului (sau este depus n mem. sub forma unui ir ASCIIZ). O alt procedur (conv_binar) va face conversia acestui ir de cifre la un numr binar de 16 bii, i-l returneaz n AX, sau la o locaie din segmentul de date (rezultat). Dup conversie (dac nu apare o eroare), prog. principal, va tipri valoarea n hexa apelnd o tot o proc. (tip_numar). Procedurile vor fi incluse ntr-un modul separat (PROC.ASM) de modulul programului principal (MAIN.ASM). MAIN.ASM .model small .stack 100h .data public numar_ASCII, rezultat, lungime, valoare_hexa public tab_conv tab_conv db '0123456789abcdef' lungime equ 5 numar_ASCII db lungime dup (?) ; rez. pt. coduri ASCII valoare_hexa db 4 dup (?), 0dh, 0ah, '$' ; valoarea hexa rezultat dw ?

mes_err

db

0dh, 0ah, Eroare de conversie: numar > 65535

CRLF db 0dh, 0ah, $ .code extrn conv_binar: proc, cit_sir: proc, tip_numar: proc start: mov ax, @data mov ds, ax ; iniializare DS call cit_sir ; se citete numrul call conv_binar ; se realizeaz conversia la binar jc tip_mes_err ; mesaj de err, pt. eroare la conversie lea dx, CRLF ; avans la linie noua mov ah, 9 int 21h call tip_numar ; se tiprete numrul n hexazecimal jmp gata_prg ; terminare program tip_mes_err: lea dx, mes_err ; tiprire mesaj de eroare, la conversie mov ah, 9 int 21h gata_prg: mov ax, 4c00h ; revenire DOS int 21h end start PROC.ASM .model small .data extrn numar_ASCII: byte, rezultat : word, lungime : abs extrn valoare_hexa : byte, tab_conv : byte .code public cit_sir, conv_binar, tip_numar ori10 macro ; nmulete cu 10 registrul AX push bx ; se salveaz reg. de lucru shl ax, 1 ;*2 mov bx, ax shl ax, 1 ;*4 shl ax, 1 ;*8 add ax, bx pop bx ; reface registru salvat endm cit_sir proc push ax ; salvare registre de lucru push bx push cx lea bx, numar_ASCII ; adresa unde se depun caracterele

mov cit:

cx, lungime

; dimensiunea maxim a irului

mov ah, 1 ; citirea unui caracter int 21h mov [bx], al ; se depune caracterul la numar_ASCII inc bx ; actualizarea adresei irului cmp al, '0' ; test dac caracterele sunt cifre jb gata ; dac nu sunt cifre s-a terminat citirea cmp al, '9' ja gata loop cit ; se reia citirea, pt. cel mult 5 cifre gata: pop cx ; refacerea registrelor salvate pop bx pop ax ret cit_sir endp conv_binar proc push si ; salvare registre de lucru push bp push ax push cx lea si, numar_ASCII ; adresa cifrelor ASCII mov cx, lungime ; numr maxim de cifre: 5 cld ; direcia de parcurgere a irului mov bp, 0 ; valoarea convertit/ rezultatul binar reia: mov ah, 0 ; se pune 0 pentru a extinde valoarea n AX lodsb ; se citete o cifr cmp al, '0' ; test de sfrit numr jnb cont_cmp ; daca nu, se continua comp. / conv. clc jmp gata_conv ; dac da, se termin conversia (CF=0) cont_cmp: cmp al, '9' ; test sfrit numr ja gata_conv sub al, '0' ; conversie de la cod ASCII la valoare xchg bp, ax ; (AX) = valoarea ori10 ; se nmulete valoarea cu baza jc gata_conv ; dac apare depire se termin add bp, ax ; se adun ultima cifr citit jc gata_conv ; testarea condiiei de eroare loop reia ; valoarea a rmas n BP (i n AX) gata_conv: ; dac a aprut err CF = 1, altfel CF = 0. mov rezultat, bp ; se depune rezultatul pop cx ; refacerea registrelor salvate pop ax

pop bp pop si ret conv_binar endp tip_numar proc push si ; salvare registre de lucru push ax push cx push bx push dx lea si, valoare_hexa ; adresa unde se depun cifrele hexa mov dx, rezultat ; valoarea de tiprit n hexa mov cx, 4 ; contor numr de cifre de tiprit lea bx, tab_conv ; adresa tabelei de conversie iar: push cx ; salvare contor mov cl, 4 ; contor numr de rotiri rol dx, cl ; se rotesc primii 4 bii pe ultimii 4 mov al, dl and al, 0fh ; se rein doar ultimii patru bii xlat tab_conv ; conversie binar hexa (ASCII) mov [si], al ; depunere la valoare_hexa inc si ; actualizare index pentru depunere pop cx ; contor numr de cifre hexa de tiprit loop iar ; se reia conversia pentru cele 4 cifre lea dx, valoare_hexa ; adresa cifrelor hexa, pentru mov ah, 9 ; tiprire. se utilizeaz funcia int 21h ; 9, din DOS pop dx ; refacerea registrelor salvate pop bx pop cx pop ax pop si ret tip_numar endp end ; sfritul modulului 'PROC.ASM'

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

32. Comunicarea ntre module.

Directivele PUBLIC, EXTRN, GLOBAL, COMM, INCLUDE


n locul directivelor PUBLIC i EXTRN se poate utiliza directiva GLOBAL; ea se substituie directivelor EXTRN i PUBLIC. O alt directiv des utilizat este INCLUDE: PUSH.ASM push ax push bx .... push sp push bp procedura include ..... include ret procedura POP.ASM pop bp pop sp .... pop bx pop ax proc push.asm pop.asm endp

Pentru rezervarea de spaiu de memorie la declararea unor variabile neiniializate (ce fac parte din segmentul BSS), se poate folosi directiva COMM: COMM [ NEAR/FAR ] identificator : tip_element [ : dim ] Atributul NEAR/FAR, dac lipsete se poate determina din modelul de implementare ales, pentru directive simplificate de segmentare, sau se presupune NEAR, pentru directivele complete. Dac aceeai declaraie este n mai multe module, variabila respectiv va fi alocat o singur dat. Utiliznd aceast directiv, nu mai este necesar s se defineasc variabila ca PUBLIC ntr-un modul i EXTRN n cellalt, ntruct atributele asociate de cele dou directive sunt furnizate de .COMM. Directiva va fi plasat n segmentul de date. Atributul tip_element : BYTE, WORD, DWORD, QWORD, i TBYTE, sau un numr ntreg, care specific numrul de octei. Parametrul dim indic numrul de elemente pentru variabil, implicit fiind 1. De exemplu declaraia: COMM FAR VARIABILA : BYTE : 25 definete VARIABILA de 25 de octei.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

33. Macroinstruciuni.

Definirea i utilizarea de macroinstruciuni


O macroinstruciune (MI) reprezint o secven de instruciuni creia i se asociaz un nume. Apariia macroinstruciunii n textul programului este nlocuit, automat, de ctre asamblor, cu secvena de instruciuni asociat. Ea poate s fie parametrizat, adic poate fi definit n funcie de o serie de parametrii formali, care sunt actualizai la utilizarea macroinstruciunii, fiind, deci, nlocuii cu parametrii actuali. Diferene ntre MI i procedur: codul obiect al unei proceduri apare o singur dat n program, n schimb codul obiect generat pentru o MI este repetat n program, ori de cte ori apare numele macroinstruciunii. Procedura reduce att dimensiunea programul surs, ct i pe cea a celui obiect, n timp ce MI nu reduce codul obiect, ci doar dimensiunea programului surs. MI nu modific timpul de execuie al programului, pe cnd utilizarea procedurilor crete timpul de execuie. Utilizare macroinstruciunilor: - simplificarea i reducerea secvenelor de cod ce se repet; - reducerea erorilor cauzate de codul repetitiv; - program n limbaj de asamblare mai uor de urmrit. < nume_macro > MACRO [ lista_parametri_formali ] < declaraii/ corpul macroinstruciunii > [;comentarii] ENDM aduna macro t1,t2,suma mov ax, t1 add ax, t2 mov suma, ax endm Utilizarea se poate face astfel: aduna a, b, c mov ax, a add ax, b mov c, ax sau aduna bx,cx,dx mov ax, bx add ax, cx mov dx, ax Dac n definirea unei macro, se utilizeaz etichete, acestea trebuie declarate LOCAL. De exemplu dac dorim s realizm un ciclu, o secven de forma: mov cx, durata_ciclu iar: loop iar va genera erori de multidefinire a etichetei la utilizrile ulterioare. delay macro durata LOCAL iar push cx ;; se salveaz registrul CX mov cx, durata iar: loop iar pop cx endm LOCAL < lista_etichete >

Rolul su este de a declara simbolurile din list ca locale pentru fiecare apel. Directiva se poate utiliza numai n MI, i precede instruciunile din corpul MI. Pentru aceste etichete asamblorul va genera, la expandare, nume de etichete succesive:??0000, ??0001, etc. 1) Calculul puterii ntregi a unui numr ntreg. putere macro numar, exponent local iar, gata push cx ; salvare (CX) i (BX) push bx xor dx, dx ; rezultatul este returnat n (DX, AX) mov ax, 1 ; pregtire rezultat, dac exponentul e 0 mov cx, exponent jcxz gata ; dac CX=0, puterea este 1 mov bx, numar ; nmulitorul n BX iar: mul bx jc gata ; dac apare eroare la *, se poziioneaz CF loop iar gata: pop bx ; refacerea registrelor salvate pop cx endm ; programul ce utilizeaz aceast macro, va testa ; valoarea lui CF, dac este 0 valoare corect n ; (DX,AX), dac ns CF=1, a aprut depire 2) nmulirea unei valori cu 10. ori10 macro x local gata push ax push bx mov ax, x shl ax, 1 ;*2 jc gata mov bx, ax shl ax, 1 ;*4 jc gata shl ax, 1 ;*8 jc gata add ax, bx jc gata ; dup utilizare macro ori10 se va mov x, ax ; testa indicatorul CF pentru a testa gata: pop bx ; o eventual depire pop ax endm

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

34. Macroinstruciuni de repetare.

Macroinstruciunea de repetare
REPT <expresie_contor> < corpul macroinstruciuni > ENDM 1) Alocarea unor valori consecutive la o anumit adres: alocare macro tabela, lungime, vi, pas tabela label byte valoare = vi ; valoare iniial rept lungime valoare = valoare + pas db valoare endm endm Utilizare: alocare tab1, 3, 0, 2 tab1 db alocare tab2, 10, 0, 1 tab2 db

2, 4, 6 1 , . . , 10

2) Generarea alfabetului, pentru litere mari, la o anumit adres. generare_alfabet macro nume nume label byte i=0 rept 26 db 'A' + i i=i+1 endm endm alocare macro tab, dim tab label byte i=0 rept dim if (i gt 255) exitm ;; ieire forat din macro else ;; nainte de execuia tuturor db i ;; instruciunilor secvenei endif i=i+1 endm endm

Macroinstruciuni de repetare condiionat


(Indefinite RePeat) IRP <nume>,<<lista>> < corpul macroinstruciunii > ENDM

<nume>, va fi nlocuit, n corpul MI cu valorile din <lista>. 1) irp endm dw 2) 1, 4, 9, 16, 25 val, <1, 2, 3, 4, 5> dw val*val

suma label byte irp x, <1, 3, 5, 7, 9> db x+x endm suma db 2, 6, 10, 14, 18 irp endm reg, <ax, cx, dx, bx, sp, bp, si, di> push reg

3)

IRPC (Indefinite RePeat Character) - rolul valorilor numerice din IRP este preluat de
caractere. 1) irpc endm 2) Memorarea, la o adres a unei valori n zecimal nempachetat: scrie_val macro adresa, valoare lea si, adresa irpc v, valoare mov byte ptr [si], v inc si endm endm Pentru o utilizare de forma: scrie_val adr1, 1997 se va genera secvena, de cod, care va depune 1, 9, 9, 7, n zec. Dac dorim s depunem o anumit secven de caractere ASCII, se modific doar linia: mov byte ptr [si], '&v' Utilizarea operatorilor &, % i ! Operatorul & este utilizat pentru substituirea simbolurilor, pe care le precede, cu valoarea numeric sau subirul de caractere asociat simbolului respectiv (sau, altfel spus, concateneaz valoarea asociat simbolului), n cazul utilizrii simbolurilor respective ca argumente (parametrii) ale utilizrii unei macroinstruciuni. 1) Declararea unor mesaje, iterative, n cadrul unui program: c, 12345 dw c*c

mesaj macro n msg&n db 'mesaj nr.&n' endm mesaj 5 va genera: msg5 db 'mesaj nr.5' mesaj 11 va genera: msg11 db 'mesaj nr.11 Dac MI are 2 parametri sau mai muli, atunci ea se definete astfel: meserr macro n, o err&n&o db 'eroare &n&&o' endm Utilizarea acestei macro de forma: meserr 2,2 va genera: err22 db 'eroare 22' Dublarea caracterului &, a amnat evaluarea irului &&o, pentru momentul evalurii MI IRP. 2) Compararea reg. AL cu caracterele 'a'..'f', i execuia pentru fiecare dintre ele unei anumite secvene (eticha, etichb, ..., etichf): irpc car, abcdef cmp al, '&car' jz etich&car endm 3) Definirea unei MI pentru rotirea coninutului unei destinaii, cu un numr de bii i o direcie, specificate ca parametrii: rotire macro sens, nr_rot, dest push cx ; salvare CX ; NU salv/reface CX mov cl, nr_rot ; sau rept nr_rot ro&sens dest, cl ; ro&sens dest, 1 pop cx ; refacere CX ; endm endm ; sau ro&sens dest, nr_rot Operatorul % realizeaz conversia simbolului care urmeaz, de la o valoare numeric la un ir de caractere, ce poate fi utilizat pentru a substitui un argument, pentru un apel de MI. Acest operator, de expansiune (%), foreaz evaluarea imediat a expresiei ce urmeaz i convertete rezultatul expresiei la un ir de cifre. mesaj5 macro nume,val db '&nume = &val' endm i declaraia: const1 equ <LOW> pentru a defini mesajul db 'const1 = LOW' se va utiliza MI anterioar, cu urmtorii parametrii:

mesaj5 const1, %const1 Parantezele unghiulare < > se utilizeaz pentru a specifica c textul dintre ele este un singur ir. Aceste paranteze se utilizeaz i cnd se dorete transmiterea unui parametru actual, pentru un apel intern de macro (apelul unei macro n alt macro). Generarea de mesaje multiple, care respect o anumit regul: meserr macro n err&n db 'eroare &n, 0Dh, 0Ah, $' endm diferr macro x m=0 rept x m=m+1 meserr %m endm endm Un apel al acestei macroinstruciuni, de forma: diferr 3 va genera mesajele: err1 db 'eroare 1, 0Dh, 0Ah, $' err2 db 'eroare 2, 0Dh, 0Ah, $' err3 db 'eroare 3, 0Dh, 0Ah, $' Un exemplu de utilizare pentru parantezele unghiulare: mesaj7 macro sir db '&sir',0 ;; definire ir de caractere ASCIIZ endm apelul: mesaj7 <sir caractere> va genera db 'sir caractere',0 Alt operator important pentru macroinstruciuni este operatorul literal, semnul exclamrii (!). Acest simbol comand asamblorului ignore interpretarea caracterului urmtor. Acest simbol poate fi utilizat atunci cnd este nevoie ca unul din urmtoarele caractere s fie inclus ntr-un ir de caractere, ntr-o MI: ! & > % Dac dorim s transmitem ca argument pentru o MI un ir de caractere ce conine i caracterul '>', atunci el va fi precedat de caracterul !, pentru a evita interpretarea lui '>' ca sfrit de ir. mesaj7 <a!>b> care va genera mesajul db 'a>b',0

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

35. Directive de asamblare condiionat.

Directive de asamblare condiionat


Asamblorul permite utilizatorului s realizeze asamblarea doar a unei anumite pri a liniilor care compun modulul surs. n principiu, pot exista dou motive care s necesite o asamblare condiionat: un program general trebuie adaptat pentru o anumit aplicaie, n funcie de parametrii actuali incluzndu-se anumite module, sau dimensionndu-se zone de memorie corespunztor aplicaiei; altfel, prin includerea tuturor modulelor sau prin dimensionarea la maxim a zonelor de memorie, indiferent de aplicaie, se ajunge la dimensionri neeconomice; un alt motiv ar putea fi necesitatea includerii n modulul obiect doar a unora dintre instruciunile prezente n textul surs, datorit unor diferene ntre procesoarele aceleiai familii (286, 386, 486 etc.); dac programul conine instruciuni pentru oricare dintre procesoare, pentru a fi portabil cu maximum de eficien (utilizare de instruciuni specifice unui anumit tip de procesor) fr intervenii n textul surs, aceasta se poate obine prin includerea acestor instruciuni n seciuni controlate de aceste directive de asamblare condiionat. IF [ELSE secventa 2] ENDIF Aceste directive pot fi imbricate. n mod asemntor sunt definite directivele: IFE ; daca expresia este zero, se executa secventa 1 ; altfel se executa secventa 2 IFB argument ; daca argumentul este blanc ( ) se ; executa secventa 1, altfel se executa secventa 2 IFNB <argument> ; adica argumentul <> blanc se executa secventa 1, ; altfel, argument = , executa secventa 2. IFDIF <arg1>,<arg2> ; se compara cele doua argumente caracter cu car ; (senzitiv la tipul literelor: mari si mici), si ; daca sunt diferite executa secv. 1, altfel secv.2 IFDIFI <arg1>,<arg2> ; este asemanatoare cu directiva anterioara, ; cu deosebirea ca ignora tipul literelor. IFIDN <arg1>,<arg2> ; se compara cele doua argumente caracter cu car ; (senzitiv la tipul literelor: mari si mici), si ; daca sunt identice executa secv.1, altfel secv.2 IFIDNI <arg1>,<arg2> ; este asemanatoare cu directiva anterioara, ; cu deosebirea ca ignora tipul literelor. IFDEF <argument> ; daca simbolul prezent ca argument este ; definit executa secv.1, altfel secv.2 expresie conditie secventa 1 ; conditia este o expresie ce poate ; fi evaluata, in momentul asamblarii, ; la o constanta TRUE sau FALSE

IFNDEF <argument>

; daca simbolul prezent ca argument nu ; este definit executa secv.1.

Ultimele dou directive se utilizeaz pentru a evita o nou definire a unui simbol, care a fost definit anterior, sau pentru stabilirea variantei de program dorite, ce urmeaz s se asambleze. ntruct asambloarele implic un proces n dou etape, se poate folosi urmtoarea directiv de asamblare condiionat pentru a specifica asamblorului realizarea anumitor operaii numai pe durata primei etape: IF1 secventa; evaluata, numai la prima parcurgere, la asamblare ENDIF Asemntor se definete i directiva IF2, care acioneaz asupra declaraiilor din blocul asociat numai la pasul al doilea al procesului de asamblare. De exemplu, urmtoarea declaraie: IF1 INCLUDE C:\MACRO.LIB ENDIF PURGE putere, scrie_val ; sterge macroinstructiiunile nedorite va permite accesul la biblioteca specificat (MACRO.LIB) numai pe durata primei etape a procesului de asamblare. Directiva anterioar va include toate macroinstruciunile coninute n biblioteca respectiv. Dac ns se dorete includerea numai a anumitor macroinstruciuni, atunci dup directiva anterioar trebuie plasat directiva PURGE urmat de numele macroinstruciunilor din biblioteca respectiv a cror includere nu se dorete. Exemple de utilizare a acestor directive: 1) Macroinstruciune pentru tiprirea unui caracter transmis ca parametru, dar care poate fi apelat fr nici un parametru, pentru afiarea caracterului spaiu. tip_car ifb <car> mov else mov endif mov int endm macro car dl, dl, car ah, 2 21h ; utilizare: tip_car mov mov int tip_car mov mov int x ; genereaza dl, x ah, 2 21h ; va genera dl, ah, 2 21h ; include intreaga biblioteca

2) O macroinstruciune recursiv, care depune registre n stiv; depunerea va nceta cnd n lista registrelor apare caracterul spaiu.

push_reg ifnb

macro r1, r2, r3 ; utilizare: <r1> push_reg push r1 push push_reg r2, r3 push endif push

ax, bx, cx ax bx cx

endm 3) O macroinstruciune ce genereaz diferite instruciuni n funcie de parametrul furnizat. Un utilizator poate s o apeleze cu parametrul B sau W, pentru a preciza dac s genereze instruciunea MOVSB sau MOVSW (implicit se genereaz MOVSB, dac nu se specific parametri). movt macro tip ifdn <tip>,<B> ; utilizare: ifdn B rep movsb ; sau: ifdn W exitm ; sau: ifdn endif ifdn <tip>,<W> rep movsw else rep movsb ; implicit, daca nu are parametru endif endm 4) Evitarea redefinirii unor identificatori sau definirea condiionat: var2 ..... ifdef endif 5) n ultimul exemplu, codul este asamblat condiionat i generat pentru dou procesoare diferite. procesor = 386 ; este iniializat cu 8086 numai pentru acest procesor .... if procesor eq 386 shl ax, 4 ; modific numai AX else ; trebuie s fie procesorul 8086 push cx ; salveaz CX, astfel c i aceast secven mov cl, 4 ; va modifica numai CX, precum shl ax, cl ; secvena anterioar pop cx ; reface CX endif equ var2 var3 2

ifndef var1 var1 endif

equ

equ

Directive pentru generarea condiionat a erorilor


n conjuncie cu directivele de asamblare condiionat, exist un set de directive pentru generarea de mesaje de eroare, n aceleai condiii ca primele. Asamblorul genereaz mesajul de eroare la ntlnirea unei astfel de directive, dac este ndeplinit condiia respectiv. Ele sunt utilizate, cu predilecie, n cadrul MI. .ERR - genereaz mesaj de eroare, de exemplu: if var1 lt var2 .err ; va genera mesaj dac: var1 < var2 endif .ERRE expresie .ERRNZ expresie .ERRB <argument> .ERRNB <argument .ERRDIF <arg1>,<arg2> .ERRDIFI <arg1>,<arg2>

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

36. Structuri de date n LA.

Structuri de date n limbaj de asamblare


Definirea unei structuri. Directiva STRUC O structur este o descriere care asociaz un nume i atribute (lungime, tip, etc.) la o colecie de cmpuri, de acelai tip sau de tipuri diferite (echivalent cu RECORD din Pascal sau STRUCT din C). nume_structura STRUC <declaraii i definiri de date> nume_structura ENDS [nume_variabila] nume_structura <[expresie][,exp,.....]> [nume_variabila] nume_structura expr dup (<[expr][,expr,...]>) expresie - evaluat la o constant, valoarea iniial a cmpului; expr. - reprezint numrul de duplicate ale structurii. Exemple de iniializare: <> - asociaz cmpurilor valorile definite iniial, n decl. STRUC; <5> - primul cmp al struc. va fi 5, iar celelalte, nedefinite, se vor asocia valorile definite iniial; <5,15> - se vor iniializa primele dou cmpuri, cu 5 i respectiv 15; <,,7> - cel de-al treilea cmp va lua valoarea 7, iar restul valorile definite iniial; <1,,7> - primul i cel de-al treilea vor primi valorile 1 i respectiv 7, iar celelalte vor primi valorile definite iniial, la declararea structurii. Dac iniial, la definire, nu li s-au asociat valori, cmpurile respective vor lua valoarea 0. Pentru accesul la un cmp al unei structuri se folosete sintaxa: nume_variabila.nume_cmp sau [reg_baza].nume_cmp Tip_persoana struc nume db 20 dup(' ') ; se iniializeaz cu blancuri prenume db 20 dup(' ') varsta db 0 ocupatie db 15 dup(' ') Tip_persana ends p1 Tip_persoana <'Ionescu','Ilie',63,'inginer'> p2 Tip-persoana <> ; copie a valorilor iniiale p3 Tip_persoana <,,21,'student'> ; iniializare vrst i ocupaie grupa Tip_persoana 25 dup(<,,20,'student'>) Programul urmtor construiete o list de tip coad, format din caractere introduse de la tastatur, care va fi apoi tiprit. .model small .stack 100h .data tip_coada struc next dw 0 ; lista este n cadrul aceluiai segment car db 0 ; sau info db 10 dup(0), pt. alte info tip_coada ends lung_coada equ 80 ; dimensiunea maxim a cozii coada tip_coada lung_coada dup(<>)

.code start: mov ax, @data mov ds, ax ; iniializare registru segment lea bx, coada ; iniializare adresa de nceput a cozii mov si, size tip_coada ; (SI) = numr octei / structur mov cx, lung_coada ; contor numr maxim de elemente iar: mov ah, 1 ; citirea unui caracter int 21h cmp al, 0dh ; test sfrit citire jz tiparire ; tiprirea cozii mov [bx].car, al ; se depune caracterul n coad mov ax, bx add ax, si ; actualizarea adresei urmtorului element mov [bx].next, ax ; legtura la urmtorul element al cozii mov bx, ax ; (BX) = adresa urmtorului element loop iar ; dac nu s-a atins limita max. (80), se reia mov dl, 0dh ; se revine la nceputul liniei mov ah, 2 ; se transmite caracterul la display int 21h ; pentru a tipri de la nceputul liniei tiparire: mov dl, 0ah ; se trece pe o linie nou mov ah, 2 ; funcia de tiprire a caracterului din (DL) int 21h lea bx, coada ; iniializarea cu adresa de nceput a cozii mov cx, lung_coada ; numr maxim de caractere de tiprit reia: cmp [bx].next, 0 ; test pt. ultimul element al cozii jz gata_tip ; dac cmpul next = 0, e ultimul element mov dl, [bx].car ; tiprire caracter mov ah, 2 int 21h mov bx, [bx].next ; adresa urmtorului element din coad loop reia gata_tip: mov ax, 4c00h int 21h end start

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

37. Definirea de structuri i nregistrri (directivele struc i record).

Definirea unei structuri. Directiva STRUC


O structur este o descriere care asociaz un nume i atribute (lungime, tip, etc.) la o colecie de cmpuri, de acelai tip sau de tipuri diferite (echivalent cu RECORD din Pascal sau STRUCT din C). nume_structura STRUC <declaraii i definiri de date> nume_structura ENDS [nume_variabila] nume_structura <[expresie][,exp,.....]> [nume_variabila] nume_structura expr dup (<[expr][,expr,...]>) expresie - evaluat la o constant, valoarea iniial a cmpului; expr. - reprezint numrul de duplicate ale structurii. Exemple de iniializare: <> - asociaz cmpurilor valorile definite iniial, n decl. STRUC; <5> - primul cmp al struc. va fi 5, iar celelalte, nedefinite, se vor asocia valorile definite iniial; <5,15> - se vor iniializa primele dou cmpuri, cu 5 i respectiv 15; <,,7> - cel de-al treilea cmp va lua valoarea 7, iar restul valorile definite iniial; <1,,7> - primul i cel de-al treilea vor primi valorile 1 i respectiv 7, iar celelalte vor primi valorile definite iniial, la declararea structurii. Dac iniial, la definire, nu li s-au asociat valori, cmpurile respective vor lua valoarea 0. Pentru accesul la un cmp al unei structuri se folosete sintaxa: nume_variabila.nume_cmp sau [reg_baza].nume_cmp Tip_persoana struc nume db 20 dup(' ') ; se iniializeaz cu blancuri prenume db 20 dup(' ') varsta db 0 ocupatie db 15 dup(' ') Tip_persana ends p1 Tip_persoana <'Ionescu','Ilie',63,'inginer'> p2 Tip-persoana <> ; copie a valorilor iniiale p3 Tip_persoana <,,21,'student'> ; iniializare vrst i ocupaie grupa Tip_persoana 25 dup(<,,20,'student'>)

Definirea unei nregistrri. Directiva RECORD


nregistrarea permite definirea de bii individuali sau grupuri de bii, dintr-un octet sau cuvnt. Fiecare bit sau grup de bii este denumit cmp. La aceste cmpuri ne putem referi prin numele simbolice asociate. nume_nregistrare RECORD nume_cmp : expr [=expr'][,. . .] expr = numrul de bii alocai cmpului respectiv; expr' = aceast clauz este opional i reprezint valoarea iniial asociat cmpului respectiv; dac nu se specific, va fi implicit, egal cu 0. Suma valorilor expresiilor pentru numrul de bii (expr) trebuie s fie o constant ntreag, i dac este <= 8, rezult c s-a definit o nregistrare de tip octet, dac este > 8 i <=16, rezult c s-a definit o nregistrare de tip cuvnt, etc. Dac sunt definii mai puini bii dect

dimensiunea unui octet (cuvnt, etc.), atunci cmpurile sunt aliniate la dreapta n cadrul tipului respectiv. model_rec record X:3=7, Y:4=8, Z:9=257 pentru aceast declaraie se va genera un cuvnt: 111.1000.100000001. declaraia acestui tip de date poate fi folosit pentru alocare: inregistrari model_rec 100 dup (<,15,3>) n urma acestei declaraii se aloc, ncepnd de la adresa inregistrari, 100 de cuvinte, ale cror cmpuri (X, Y, Z) vor avea valorile: X = 111, pstreaz valoarea de la definire, Y = 1111, iniializat la alocare, Z = 000000011, iniializat la alocare. Pentru astfel de date sunt definii doi operatori: MASK nume_cmp - furnizeaz o masc de bii pentru cmpul respectiv (biii cmpului respectiv sunt 1, iar toi ceilali 0); WIDTH nume_cmp - furnizeaz o constant ntreag egal cu numrul de bii ai cmpului respectiv, sau se poate specifica numele nregistrrii i va furniza numrul de bii al acesteia. Pentru o referire direct la numele cmpului, ntr-o instruciune, asamblorul va genera o valoare ntreag ce reprezint poziia n cadrul octetului (sau cuvntului, etc.). Cu alte cuvinte, reprezint numrul de deplasri la dreapta, necesare pentru a aduce cmpul respectiv n biii cei mai puin semnificativi ai nregistrrii respective. Exemple de utilizare: 1) mov dx, inregistrari [40] ; (DX) = al 21-lea cuvnt and dx, mask Y ; (DX) = 000.11111.000000000 mov cl, Y ; (CL) = 9 shr dx, cl ; se deplaseaz cmpul Y la dreapta mov ax, model <1,7,127> ; (AX) = 001.00111.001111111. dim_X equ width X ; dim_X = 3 dim_model equ width model ; dim_model = 16 2) Selectarea, dintre angajaii unei firme, a brbailor cu o vechime mai mare de cinci ani, necstorii: date_angajat record vechime:6, sex:1, stare:1 tip_angajat struc nume db 20 dup(' ') prenume db 20 dup(' ') date date_angajat < > tip_angajat ends nr_ang equ 100 angajat tip_angajat nr_ang dup (< >) ; ............ mov cx,nr_ang lea bx,angajat iar: mov al, [bx].date test al, mask sex ; 0 = femeie, 1 = brbat jz respins

test al, mask stare jz respins mov cl, vechime shr al, cl cmp al, 5 jb respins;

; 0 = cstorit, 1 = necstorit ; (AL) =0,0,vechime(6 bii) ; testare vechime mai mare de 5 ani ; cel selectat este referit de (BX) ; . . . . afiare: nume & prenume

respins: add bx, size tip_angajat loop iar ....

; se trece la urmtorul angajat

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

38. Programe rezidente (TSR).

Programe rezidente n memorie (TSR)


TSR este prescurtarea de la Terminate and Stay Resident. Deci, este vorba despre programe care rmn n memoria RAM dup ce s-a terminat execuia lor. Aceste programe pot fi invocate fie utiliznd anumite taste, fie de ctre alte programe, care lanseaz o ntrerupere software adecvat. De obicei aceste programe sunt de tip .COM. S considerm ce s-ar ntmpla dac, n timp ce un program ruleaz, el ar fi copiat adresa sa top of memory n pointerul special, ce memoreaz locaia de memorie unde DOS ncarc programele pentru execuie. n acest caz, DOS va fi pclit prin ncrcarea fiecrui program ulterior n zona de memorie situat imediat deasupra programului original. n consecin, programul original ar rmne n memorie pe durata executrii tuturor programelor ulterioare. Exact la fel se ntmpl ntr-un program TSR. Acesta nlocuiete pointerul de nceput al programului cu pointerul top of memory. Fiecare program executat dup acest program TSR este ncrcat n zona de memorie superioar acestuia i deci nu se suprapune peste memoria utilizat de programul TSR. Cnd se ncarc mai multe programe rezidente, fiecare dintre ele utilizeaz aceast tehnic. Un program TSR conine dou pri: o parte de iniializare (tranzitorie) i o parte rezident. Partea tranzitorie este responsabil de ncrcarea prii rezidente n memoria RAM i de instalare a unei rutine de ntrerupere care s determine cum este invocat (apelat) programul TSR. Dac programul TSR este invocat de o ntrerupere software, poriunea plaseaz adresa prii rezidente a codului n vectorul de ntrerupere corespunztor. Dac TSR-ul va fi invocat printr-o tast (hotkey) poriunea de iniializare trebuie s modifice manipularea ntreruperilor DOS, pentru tastatur (de fapt pentru tasta respectiv). Cnd poriunea tranzitorie este executat, la sfritul acesteia ea invoc o funcie DOS care permite ca o poriune din fiierul executabil s rmn rezident n memoria RAM dup ncheierea execuiei acestuia, de unde i expresia Termin i Stai Rezident. Poriunea de iniializare a TSR-ului cunoate dimensiunea poriunii rezidente, precum i locaia n memorie a poriunii rezidente, i transmite aceast informaie sistemului DOS. Ulterior, DOS nu va afecta blocul de memorie specificat, dar este liber s ncarce programe n zona de memorie neprotejat. Deoarece sistemul de operare DOS este un sistem monoacces, monoprogramare i nereentrant, apar o serie de restricii si limitri privind operaiile ce pot fi efectuate de codul rezident al programelor din aceast categorie. De aceea este necesar s cunoatem structura sistemului de operare, anumite module care afecteaz un program rezident, precum i modul de lucru al unor dispozitive (ca de exemplu tastatura). Programele TSR pot fi de dou tipuri, dup modul de activare: active i pasive. Un program TSR pasiv se execut ca parte normal a fluxului unui program; el este executat n urma unui apel explicit dintr-o alt aplicaie. TSR-urile pasive sunt aproape ntotdeauna rutine de servire a ntreruperii sau extind apeluri DOS sau BIOS. Un program TSR activ este executat constant, la anumite intervale de timp, sau la apsarea unei anumite combinaii de taste care nu are semnificaie pentru aplicaia curent. Un program TSR activ, de obicei, va suspenda execuia programului curent. TSR-urile active ndeplinesc una din dou funcii: fie ndeplinesc direct o ntrerupere hardware, fie sunt activate periodic, fr un apel explicit de la o aplicaie. Un TSR poate conine att componente active, ct i componente pasive. Astfel, anumite rutine pot fi activate de o ntrerupere hardware, iar altele s fie apelate explicit de alte aplicaii. Urmtorul program este un exemplu de TSR care furnizeaz att o rutin activ (MyInt9h), ct i una pasiv (MyInt16h). Programul utilizeaz vectorii de ntrerupere ai tastaturii:

09h i 16h. De cte ori apare o ntrerupere pentru tastatur, rutina MyInt9h, activ pe acest nivel (INT 09h), va incrementa un contor. Deoarece tastatura genereaz, de obicei, dou ntreruperi la o tastare (una la apsarea i alta la revenirea tastei), valoarea va fi mprit la 2, pentru a aproxima numrul de apsri ale tastelor. Rutina pasiv pe nivelul 16h, MyInt16h, returneaz numrul de apsri ale tastelor ctre programul apelant. Codul urmtor furnizeaz cele dou programe, TSR-ul (tsr_tast.asm) i aplicaia (tsr_tapl.asm) care afieaz numrul de taste apsate de cnd s-a lansat TSR-ul. .model tiny ; tsr_tast.asm - TSR activ, numr ntr. tastatur, dup activare ; pt. a det. nr. de taste apsate ntre dou apeluri succesive ; prog. permite i dezinstalarea lui, la cererea utilizatorului ; Se va genera program de tipul .COM: tlink/t tsr_tast .code org 100h start: jmp test_Instalare ID_tsr db 'TSR_numara_taste_apasate_INT_9h_&_16h' lung_ID equ $-ID_tsr KeyCont dw 0 ; contor ntreruperi de la tastatur OldInt9h dd ? ; salvarea vechilor vectori de ntrerupere OldInt16h dd ? MyInt9h proc far ; comp. activa, rutina de ntr. tastatur, apelat de sistem la ; fiecare apsare de tast, incrementeaz contorul KeyCont, i ; transfer controlul la ntreruperea original, Int 9. inc cs:KeyCont ; incr. contor de ntreruperi tastatur jmp cs:OldInt9h ; apelul vechii ntr., salvat la OldInt9h MyInt9h endp MyInt16h proc far ; componenta pasiv a TSR-ului apelat prin apelul INT 16h. ; Dac registrul AH=0FFh, ntoarce nr-ul de ntreruperi ; de la tastatur, n AX. Dac AH conine alt valoare, atunci ; rutina transmite controlul la ntreruperea original INT 16h. cmp ah, 0FFh ; se solicit valoarea contorului ? je ReturnCont ; dac da, se returneaz valoarea lui jmp cs:OldInt16h ; altfel apeleaz ntreruperea original ReturnCont: mov ax, cs:KeyCont mov cs:KeyCont, 0 ; reiniializare contor la fiecare apel iret MyInt16h endp test_Instalare: push es ; salvare ES, DS push ds push cs pop ds ; init. DS cu CS, i poate lipsi la .COM

mov ax, 0 mov es, ax ; init. ES cu adr. Seg. a TVI (0000H) ; se verific dac nu este deja instalat acest TSR: ; se verific dac au fost instalate cele dou ntreruperi n TVI mov ax, es:[9h*4] ; se comp. offseturile pt. vectorii din tabel cmp ax, offset MyInt9h ; dac nu sunt gsii cei doi vectori jne inst ; se vor instala mov ax, es:[16h*4] cmp ax, offset MyInt16h jne inst ; aici se tie c sunt instalai 2 noi vectori de ntrerupere ; pe nivelurile 9h i 16h, cu offseturile noastre, dar pt a fi siguri ; c sunt chiar acetia vom comp. i id. TSR-ului curent ; cu cel din memorie (din TVI) mov ax, es:[9h*4+2] mov es, ax mov si, offset cs: ID_tsr ; se compar identificatorii mov di, si ; offset celor dou nume_TSR n SI/DI mov cx, lung_ID ; lungimea numelui vectorului nou cld ; direcia de parcurgere, cresctoare repe cmpsb ; se compar cele doua nume jnz inst ; nume diferite -> se instaleaz lea dx, mes_inst ; afiare mesaj program deja instalat mov ah, 9 ; i solicitare utilizator pentru dezinstalare int 21h mov ah, 1 int 21h ; cit. rsp. utilizator, dac dorete dezinst push ax ; salvare rspuns mov ah, 9 ; avans pe linie nou pe ecran lea dx, CRLF int 21h pop ax ; refacere rspuns utilizator and al, 0DFH ; se transform caracterul n liter mare cmp al, 'D' ; se compar cu caracterul 'D' je dezinst ; daca este 'D' se va dezinstala programul pop es ; refacere ES, DS pop ds mov ax, 4c00h ; dac nu, revine n DOS, fr instalarea int 21h ; codului, care este deja instalat (rezident) dezinst: xor ax, ax ; se refac vectorii iniiali salvai n codul mov ds, ax ; rezident; se pun n TVI (adr. seg. 0) mov es, ds:[9*4+2] ; ES = adr. seg. prg. TSR, ncrcat ant., mov ax, word ptr es:[OldInt9h] ; difer de cel actual (TVI) mov ds:[9*4], ax ; reface vectorul 9: offsetul mov ax, word ptr es:[OldInt9h+2]

mov ds:[9*4+2], ax ; i adresa de segment mov ax, word ptr es:[OldInt16h] ; reface vectorul 16h: mov ds:[16h*4], ax ; offsetul mov ax, word ptr es:[OldInt16h+2] mov ds:[16h*4+2], ax ; i adresa de segment pop ds ; refacere ES, DS pop es push cs ; dezinstalarea se face complet, cu pop es ; eliberarea spaiului de memorie mov ah, 49h ; alocat programului TSR int 21h push cs pop ds lea dx, mes_dezi ; afiare mesaj 'Program Dezinstalat' mov ah, 9 int 21h mov ax, 4C00h int 21h ; se memoreaz vechile valori pentru ntr. INT 9 i INT 16 ; direct n variabilele OldInt9h, i respectiv OldInt16h inst: cli ; dezactivare ntreruperi ; seciune critic: modificare vect. ntr. mov ax, es:[9*4] ; citire offset rutin pentru Int 9h i mov word ptr OldInt9h, ax ; salvare la OldInt9h mov ax, es:[9*4 + 2] ; cit. Seg. rutin pentru Int9h i mov word ptr OldInt9h[2], ax ; salvare la OldInt9h+2 mov word ptr es:[9*4], offset MyInt9h ; nlocuire vector mov word ptr es:[9*4+2], cs ; vechi cu cel nou mov ax, es:[16h*4] ; aceleai operaii pentru Int 16h mov word ptr OldInt16h, ax mov ax, es:[16h*4 + 2] mov word ptr OldInt16h[2], ax mov word ptr es:[16h*4], offset MyInt16h mov word ptr es:[16h*4+2], cs sti ; reactivare ntreruperi ; se termin partea de instalare cu lsarea rezident a codului mov ah, 9 ; tiprire mesaj de instalare cod TSR lea dx, mesaj int 21h pop ds ; refacere DS, ES pop es mov dx, offset test_instalare + 15 ; calcul spaiul de memorie push cx ; salvare CX mov cl, 4 ; ocupat de codul rezident, ca nr paragrafe shr dx, cl

pop cx ; refacere CX mov ax, 3100h ; apeleaz funcia ce las rezident codul int 21h ; din seg. curent, pn la 'test_instalare mesaj db 'S-a instalat programul ce numara ''Numarul de taste'' apasate.' CRLF db 0Dh, 0Ah, '$' mes_inst db 'Programul este deja instalat in memorie!!!', 0Dh, 0Ah db 'Doriti dezinstalarea lui (D/d-DA, orice alta tasta pentru NU): $' mes_dezi db 'Programul a fost dezinstalat !!!', 0Dh, 0Ah, '$' end start Pe lng problemele legate de apeluri reentrante ale TSR-ului ctre DOS/ BIOS, se poate ca apelurile DOS ale TSR-ului s afecteze structuri de date utilizate de alte aplicaii curente: stiva aplicaiei, zona DTA, etc. Cnd se execut un TSR el opereaz n contextul (mediul de lucru) al aplicaiei principale. De ex., adresa returnat de TSR i orice valori, pe care TSR -ul le salveaz pe stiv, sunt puse pe stiva aplicaiei. Dac TSR folosete intens stiva, datorit unor apeluri recursive, sau alocrii de spaiu pe stiv pentru variabile locale, atunci TSR-ul trebuie s salveze stiva aplicaiei (adic SS i SP) i s comute pe o stiv local (proprie). Dac TSR-ul execut apelul funciei DOS ce returneaz adresa PSP, se va returna adresa PSP-ului aplicaiei principale, i nu cel al TSR-ului. Dac nu se comut de la PSP-ul aplicaiei principale la cel al TSR-ului, i apare o excepie (manipulare disc, sau ctrl-break), atunci se va executa manipulatorul asociat cu aplicaia principal (n locul celui asociat TSR-ului). De aceea, cnd se execut un apel DOS, care poate rezulta ntr-una din acele condiii, trebuie comutat PSPul. Astfel cnd TSR-ul returneaz controlul la aplicaia principal, trebuie refcut PSP -ul. Funcia 50h iniializeaz adresa PSP a programului curent la valoarea din registrul BX, iar funcia 51h determin adresa PSP a programului curent i o returneaz n registrul BX.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

39. Componentele unui program TSR (partea tranzitorie, de instalare i cea rezident).

Componentele unui program TSR


Programele TSR utilizeaz, dup cum am artat, n general, ntreruperile de la tastatur sau de la ceasul de timp real; ele nu trebuie s interfereze cu ntreruperile hardware care aparin de domeniul driverelor de dispozitiv, excepie fcnd ntreruperile de la tastatur i de la circuitul de ceas. Circuitul de ceas genereaz ntreruperi hardware la fiecare 1/18,2 secunde (acest interval este dat de faptul c, pe durata unei ore, un registru contor ajunge la valoarea maxim 65535); aceste ntreruperi periodice permit actualizarea orei sistemului. Pentru ceasul de timp real exist doi vectori de ntrerupere, i anume 08h, respectiv 1Ch. ntreruperea de pe nivelul 08h, INT 08h, actualizeaz ora i data sistemului, dup care execut instruciunea INT 1Ch; aceast rutin const dintr-o singur instruciune IRET, tocmai pentru a permite utilizatorului s-i insereze aici rutina de tratare a ntreruperii, i nu pe nivelul 08h, tocmai pentru a nu afecta actualizrile de sistem. ntreruperile de la tastatur, generate att la apsarea unei taste, ct i la eliberarea ei, au fost descrise anterior. ntreruperea de la tastatur se afl pe nivelul 09h, INT 09h; aceast rutin de tratare a ntreruperii citete codul generat de tastatur i n funcie de starea tastelor de tip shift (CTRL, SHIFT, ALT)- memorat ntr-un octet de stare la adresa 40h:17h- genereaz codul tastei apsate respective. De asemenea, aceast procedur verific i anumite combinaii de taste cu semnificaie deosebit, cum ar fi: CTRL-ALT-DEL (reiniializare), CTRL-BREAK (suspendare), pentru care se execut instruciunile INT 19h, respectiv INT 1Bh. Caracterele de la tastatur sunt depuse ntr-un buffer circular, de 16 cuvinte; bufferul tastaturii se afl la adresa 40h:1Ah i conine un pointer (deplasament) pentru extragere, un pointer (tot de tip cuvnt) pentru introducere i zona de 16 cuvinte unde se depun codurile tastelor. Aplicaiile utilizator vor folosi instruciunea INT 16h pentru accesul la bufferul tastaturii, care permite citirea caracterelor din buffer i verificarea strii tastaturii. Componenta mai simpl a unui program rezident este tocmai cea de iniializare, care l las rezident. n locul terminrii normale, ca pn acum, a programului cu funcia 4Ch, INT 21h, programul se va termina cu funcia 31h, cea care pstreaz programul n memorie. Cnd se va executa rutina de iniializare, sistemul va rezerva blocul de memorie unde este rezident programul i va ncrca programele urmtoare n memoria rmas disponibil dup programul rezident. Componenta mai delicat din elaborarea unui program rezident este cea care realizeaz activarea programului dup ce acesta a devenit rezident, deoarece nu este un program intern, de sistem, cum sunt de exemplu CLS, COPY, DIR etc. Metoda cea mai utilizat pentru activare este cea de modificare a tabelei vectorilor de ntrerupere, astfel nct programul rezident ntrerupe toate tastrile, acionnd la o anumit tast sau combinaie de taste. Partea rezident conine: una sau mai multe proceduri, dintre care una este noua rutin de tratare a ntreruperii (RTI), care apeleaz i vechea ntrerupere; la apariia unei ntreruperi corespunztoare acestei ntreruperi, se va activa RTI din partea rezident. o zon de date, care conine i spaiul alocat n care se salveaz vectorii de ntrerupere ce sunt modificai de programul rezident. Un program rezident obinuit const din urmtoarele componente: 1. O component care redefinete locaiile din tabela vectorilor de ntrerupere, adic instalarea unui nou vector de ntrerupere. 2. O component de iniializare, care se execut doar la prima rulare a programului i care realizeaz: nlocuirea adresei din vectorul de ntrerupere cu propria sa adres (a codului rezident);

determin dimensiunea prii rezidente a programului (la nivel de paragrafe, 16 octei); utilizeaz o ntrerupere (31h) care specific sistemului s termine execuia programului curent i s lase rezident n memorie poriunea specificat de program. 3. Componenta (procedura) care rmne rezident i care va fi activat fie printr-o combinaie specific de taste, fie de ceasul de timp real al sistemului.

Ca efect, rutina de iniializare stabilete toate condiiile pentru a lsa rezident programul i apoi permite ca ea nsi s fie tears. Organizarea memoriei, acum, apare astfel: Memoria disponibil Poriunea de iniializare a programului TSR (peste care se poate suprapune urmtorul program) Programul rezident (TSR) COMMAND.COM IO.SYS i MSDOS.SYS Tabela vectorilor de ntrerupere Un program rezident poate utiliza dou funcii DOS, INT 21h, 35h i respectiv 25h, pentru accesul la tabela vectorilor de ntreruperi, deoarece nu exist nici o garanie c adresa acestei tabele va ncepe ntotdeauna de la adresa 0000H. Aceste funcii primesc ca parametru nivelul ntreruperii pe care se dorete instalarea activrii codului rezident sau salvarea vechiului vector, deci nu trebuie cunoscut adresa fizic a acestuia.

Instalarea unui nou vector de ntrerupere


Partea de instalare a unui program TSR trebuie s realizeze urmtoarele operaii: s verifice, n primul rnd, dac nu cumva a fost deja instalat n memorie codul su rezident; dac programul a fost deja instalat, nu l va mai instala i programul se va termina cu funcia 4C00h, INT 21h. s captureze un vector de ntrerupere pe care l nlocuiete cu unul nou. nainte de a modifica vectorul de ntrerupere, programul rezident (cel ce se instaleaz), salveaz n partea sa de iniializare vectorul curent i apoi l nscrie pe cel nou, care reprezint adresa, de tip FAR a procedurii, pentru tratarea ntreruperii definite n partea rezident; s calculeze dimensiunea memoriei necesare pentru codul rezident i s apeleze funcia DOS 31h, care las codul prii rezidente n memorie i termin programul. Prin capturarea unui vector de ntrerupere se nelege nlocuirea vectorului existent, cu unul nou, care conine adresa noii rutine de tratare a ntreruperii, definit n programul TSR. De obicei, noua rutin apeleaz vechea rutin de tratare a ntreruperii. nlocuirea unui vector de ntrerupere, care const n salvarea celui vechi i nscrierea unuia nou, se poate implementa direct de utilizator, utiliznd instruciuni de transfer (mov), dar este mult mai comod utilizarea funciilor DOS (INT 21h) 35h i 25h. Funcia DOS 35h returneaz n ES:BX vechiul vector de ntrerupere, cel care se dorete a fi nlocuit, al crui numr a fost transmis n registrul AL, astfel:

mov ah, 35h ; funcia DOS de salvare a vechiului vector mov al, nr_int ; nr. ntr. pe nivelul creia se pune TSR-ul int 21h mov Vechea_Int, bx ; salv. vechiului vector de ntrerupere mov Vechea_Int[2], es ; din ES:BX, n zona TSR-rezident Funcia 25h scrie noul vector de ntrerupere, transmis n registrele DS:DX, n tabela vectorilor de ntrerupere, n locul vectorului al crui numr (index din tabel) este specificat n registrul AL: mov ah, 25h ; funcia DOS de instalare a noului vector mov al, nr_int ; nr. ntr. pe nivelul creia se pune TSR-ul lea dx, Noua_Int; offsetul RTI, adr. seg. este n DS, ntruct ; toate reg. seg., la programele .COM ; sunt iniializate cu segmentul PSP int 21h ; deci nu mai trebuie reiniializat cu ;seg Noua_Int Ca efect, la apariia unei ntreruperi pe nivelul specificat n AL, se va executa noua procedur rezident (TSR), n locul celei vechi. Salvarea vechiului vector i instalarea celui nou se poate face i fr funciile DOS, direct n tabela vectorilor de ntrerupere (TVI); secvena aceasta trebuie ns executat cu ntreruperile dezactivate. Pentru a evita reinstalarea aceluiai program TSR, se verific dac exist deja o copie n memorie a codului rezident, deci dac acesta a fost deja instalat, prin compararea offset-ului noii rutine cu offset-ul vectorului de ntrerupere utilizat. n cazul n care cele dou offset-uri sunt diferite, nseamn c programul nu este rezident i, deci, poate fi instalat. Dac, ns, cele dou offseturi sunt identice, ntruct se poate ntmpla ca programe diferite s utilizeze acelai vector de ntrerupere i s aib acelai offset, se vor compara identificatorii celor dou programe TSR. Dou TSR-uri diferite pot avea acelai offset al adresei de lansare dac zona de date ce precede nceputul codului TSR are aceeai dimensiune. Din acest motiv trebuie nscris n codul rezident un ir de caractere care s identifice n mod unic acel program; acest identificator de program TSR se plaseaz naintea programului TSR propriu-zis. Pentru a lsa rezident n memorie numai partea rezident a programului TSR se va utiliza funcia 31h, care are ca parametru de intrare dimensiunea de memorie ocupat de partea rezident, exprimat n paragrafe (1 paragraf = 16 octei), transmis n registrul DX (adresa de segment este cea coninut n DS, care are acelai coninut cu toate celelalte registre segment n cazul programelor .COM). Funcia va lsa rezident n memorie codul de lungime specificat i realizeaz ieirea din program, n DOS. Memoria ocupat de partea de iniializare a programului va fi eliberat de DOS. Deci un program TSR are urmtoarea structur: cod_TSR segment ; partea rezident assume cs: cod_TSR org 100H intrare: jmp start_init ; exe. la prima intrare nume_TSR db 'prog_TSR_1' ; ID cod rezident lung_nume equ $ - nume_TSR ; lungime ID

vect_vechi dd ? ; spaiu pt salvarea vechiului vector nr_vect equ ... ; vectorul pe care se instaleaz TSR ; definirea noii proceduri de tratare a ntreruperii vect_nou proc far ; noua proc. poate apela i vechea p. push resurse ; salv. resurse utilizate de TSR ......... ; noile prelucrri, descrise de noua ......... ; procedur de tratare a ntreruperii pop resurse ; refacerea resurselor utiliz. de TSR jmp cs: vect_vechi ; vechea ntr., fie cu salt fie ca apel: ; pushf ; apel de tip ntrerupere pentru vechea ; call cs:vect_vechi ; procedur de tratare ntrerupere ; iret ; revenire n programul ntrerupt vect_nou endp ; partea de iniializare a codului rezident start_init: mov al, nr_vect ; numrul vechiului vector de ntrerupere, mov ah, 35h ; cel nlocuit. Salvare vector vechi. int 21h ; (ES:BX) = vect vechi. Comp. offseturile cmp bx, offset vect_nou ; celor doi vectori: vechi nou jnz instalare ; Este deja rezident ? Dac nu, se instaleaz mov si, offset cs: nume_TSR ; Se compar identificatorii mov di, si ; offseturile celor dou nume_TSR n SI/DI mov ax, cs ; adresa de segment pentru numele noului mov ds, ax ; vector mov cx, lung_nume ; lungimea numelui vectorului nou cld ; direcia de parcurgere, cresctoare repe cmpsb ; se compar cele dou nume jnz instalare ; nume diferite -> se instaleaz lea dx, mes_deja_inst ; afiare: Program deja instalat mov ah, 9 int 21h ; aici se poate insera secvena de dezinstalare a TSR-ului ; se ntreab utilizatorul dac dorete dezinstalare: lea dx, mes_dezinst mov ah, 9 int 21h mov ah, 1 ; citire rspuns utilizator int 21h cmp al, D ; dac nu este DA se termin fr dezinst. jnz iesire xor ax, ax ; se reface vectorul din TVI, vect_vechi mov ds, ax ; n codul rezident; se pun n TVI (seg. 0) cli mov es, ds:[nr_int*4+2] ; ES=adr. seg. TSR, deja ncrcat, mov ax, word ptr es:vect_vechi ; care difer de cea actual, mov ds:[nr_int*4], ax ; (se reface n TVI) reface vectorul

mov ax, word ptr es:vect_vechi[2] ; nr_int: offsetul mov ds:[nr_int*4+2], ax ; i adresa de segment sti push cs ; dezinstalarea se face complet, cu pop es ; eliberarea spaiului de memorie mov ah, 49h ; alocat programului TSR int 21h push cs pop ds lea dx, mes_dezi ; afiare mesaj 'Program Dezinstalat' mov ah, 9 int 21h iesire: mov ax, 4c00h int 21h instalare: cli ; dezactivare sistem ntreruperi (INTR) mov word ptr vect_vechi, bx ; se salveaz vechiul mov word ptr vect_vechi[2], es ; vector mov ah, 25h ; funcia DOS de instalare a noului mov al, nr_vect ; vector lea dx, vect_nou ; DS a fost iniializat anterior int 21h ; secvena care las codul vect_nou rezident ; 'start_init' - eticheta de nceput a prii de iniializare, ; reprezint i eticheta de sfrit a codului rezident lea dx, start_init ; adr. de sfrit a prii rezidente, care este add dx, 15 ; rotunjit la paragraful urmtor mov cl, 4 ; pentru a determina shr dx, cl ; dimensiunea n paragrafe mov ah, 31h ; funcia DOS, care l las rezident sti ; reactivare sistem de ntreruperi int 21h mes_deja_inst db 0Ah, 0Dh, TSR-ul este deja instalat !!! db 0Ah, 0Dh, $ mes_dezinst db Doriti dezinstalare (D pentru DA, orice db alta tasta pentru NU): $ mes_dezi db 0Dh, 0Ah, 'Programul a fost dezinstalat !!!' db 0Dh, 0Ah, '$' cod_TSR ends end intrare 'nr_vect' este numrul vectorului de ntrerupere ce se nlocuiete, de exemplu 1Ch vectorul ceasului de timp real, sau 09h pentru tastatur. Partea de iniializare nu va rmne n memorie, ci numai codul rezident (vect_nou), primele (DX) paragrafe, pn la eticheta 'start_init'. ; se revine n DOS, fr instalarea ; codului, care este deja rezident

Spaiul de memorie ocupat de partea de iniializare a programului TSR, va fi eliberat de DOS.

Partea rezident a programului TSR


Partea rezident definete o zon de date i prelucrrile respective, reprezentate de una sau mai multe proceduri. Procedurile dintr-un program rezident devin active ca rspuns la un apel direct al unui alt program sau la apariia unei ntreruperi hardware. Dup lansare un lucru nu poate fi ateptat pentru codul apelant: s iniializeze corespunztor registrele segment. Singurul registru segment cu semnificaie pentru codul rezident este registrul CS. Pentru acces la variabilele locale -> rutinele vor iniializa DS sau alte registre segment. De ex. o rutin care numr de cte ori alte programe o apeleaz, dup ce a devenit rezident. Ea ar conine o singur instruciune inc contor, dar s-ar incrementa variabila de la offsetul contor n segmentul referit de DS, i deci nu va incrementa variabila contor. Dou soluii la aceast problem: 1. toate variabilele n segmentul de cod, i s se utilizeze prefixul segment (inc cs:contor); utilizat doar cnd avem puine variabile. 2. salvare registrul segment de date, DS, la intrarea n TSR, iniializarea lui cu noua valoare, iar nainte de ieire din TSR s fie refcut la valoarea avut. Activarea unui program TSR presupune ntreruperea celui curent executat. n cazul n care codul rezident folosete funcii de sistem, el trebuie s testeze, la activarea sa, dac programul ntrerupt executa o funcie DOS/BIOS. Codul rezident nu poate reactiva o funcie de sistem, n timp ce se execut o alt funcie DOS/BIOS, deoarece DOS-ul nu este un sistem de operare reentrant (accesul la disc: 13h, 25h, 26h, nu poate fi ntrerupt). Aceast problem este doar pentru TSR-uri active, ntruct cele pasive sunt apelate i se vor executa n cadrul programului apelant, care nu poate executa simultan dou apeluri. Pentru a evita astfel de operaii sistemul de operare utilizeaz dou variabile: 'eroare critic' i 'seciune sau stare critic', pe care le activeaz corespunztor strii n care se afl. Cele dou variabile pot fi testate de codul rezident, n momentul n care se utilizeaz funcii DOS. Adresele celor dou variabile, i deci starea lor, sunt returnate de funciile 34h (numit indicator seciune critic sau indicator inDOS) i respectiv, 50D6h (eroare critic), n registrele ES:BX. Cele dou adrese pot fi memorate n zona de date a prii rezidente, de ctre partea de iniializare a programului TSR, pentru a le testa direct. ntreruperea multiplexat, INT 2FH Cnd se instaleaz un program TSR care are i componente pasive, trebuie ales un vector de ntrerupere pe care s fie instalat, astfel ca alte programe s poat comunica cu rutinele sale, pasive. Se poate alege un vector aproape la ntmplare dar aceasta poate conduce la anumite probleme de compatibilitate. Ce se ntmpl dac altcineva utilizeaz deja acest vector de ntrerupere ? n multe situaii alegerea este clar, cum ar fi n situaia n care codul pasiv al TSR -ului extinde anumite servicii (tastatur, video). n celelalte situaii, cum ar fi crearea unui nou driver pentru un nou dispozitiv, care s nu interfere funciile furnizate pentru acest dispozitiv, cu alte ntreruperi, alegerea la ntmplare a unui vector de ntrerupere este riscant. Pentru a rezolva aceste situaii DOS-ul furnizeaz soluia utilizrii unei ntreruperi multiplexate, INT 2FH, care permite instalarea, testarea prezenei i a comunicrii cu un program TSR.

Pentru a utiliza aceast ntrerupere, o aplicaie plaseaz o valoare de identificare n AH i un numr de funcie n AL, i apoi execut INT 2FH. Fiecare TSR din lanul INT 2FH va compara valoarea din AH cu propria sa valoare unic de identificare. Dac valoarea sa coincide cu cea din AH, atunci TSR-ul respectiv va prelucra comanda specificat de valoarea din registrul AL. Dac nu se identific, prin valoarea din AH, atunci TSR-ul respectiv transmite controlul la urmtorul manipulator din lanul INT 2FH. Aceasta simplific cumva problema, dar nu o elimin. De obicei, trebuie ales numrul ntreruperii nainte de proiectarea TSR-ului. Cum, ns, o aplicaie va ti ce valoare s ncarce n AH, dac se asigneaz dinamic aceast valoare, cnd TSR-ul este rezident ? Se permite oricrei aplicaii interesate s determine identificatorul (ID) TSR-ului. Prin convenie, funcia zero (AL=0) este un apel ce determin prezena TSR-ului. Acest apel se va realiza nainte de solicitarea oricrui serviciu TSR, pentru a determina dac programul TSR este prezent n memorie. Dezinstalarea unui program TSR La dezinstalarea unui TSR trebuie fcute trei lucruri: - oprirea/ suspendarea oricror activiti nerezolvate sau n ateptare (adic, un TSR poate avea anumii indicatori iniializai pentru a lansa anumite activiti ulterioare); - refacerea tuturor vectorilor de ntrerupere la valorile lor iniiale; - eliberarea spaiului de memorie ocupat, adic cedarea spaiului de memorie rezervat napoi ctre DOS, astfel ca alte aplicaii s-l poat utiliza; Dac dezinstalarea TSR-ului const doar n refacerea valorilor vectorilor de ntrerupere, se va crea o problem, dac exist alte TSR-uri care utilizeaz aceeai vectori de ntrerupere. S presupunem c avem urmtorul lan de TSR-uri, pe un anumit nivel de ntrerupere:

Aceasta va dezactiva efectiv TSR-urile nlnuite din program, iar aceste TSR-uri vor avea efecte neateptate, n aceste condiii. O soluie ar fi tiprirea unui mesaj de eroare, care s informeze utilizatorul c nu se poate dezinstala acest TSR, pn nu se dezinstaleaz toate TSR urile instalate anterior acestuia. Problema va fi n a determina TSR-urile nlnuite n ntrerupere. Pentru aceasta tim c vectorii de ntrerupere ar trebui nc s refere rutina noastr, dac acesta este ultimul TSR care se execut. Atunci, trebuie s comparm vectorii de ntrerupere instalai cu adresele rutinelor de servire a ntreruperii respective. Dac toate acestea se potrivesc, atunci se poate elimina n siguran TSR-ul din memorie. Dac, ns, doar unul dintre ei nu se potrivete, atunci nu putem elimina TSR-ul din memorie.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

40. Instalarea, activarea i dezinstalarea acestor programe.

Instalarea unui nou vector de ntrerupere


Partea de instalare a unui program TSR trebuie s realizeze urmtoarele operaii: s verifice, n primul rnd, dac nu cumva a fost deja instalat n memorie codul su rezident; dac programul a fost deja instalat, nu l va mai instala i programul se va termina cu funcia 4C00h, INT 21h. s captureze un vector de ntrerupere pe care l nlocuiete cu unul nou. nainte de a modifica vectorul de ntrerupere, programul rezident (cel ce se instaleaz), salveaz n partea sa de iniializare vectorul curent i apoi l nscrie pe cel nou, care reprezint adresa, de tip FAR a procedurii, pentru tratarea ntreruperii definite n partea rezident; s calculeze dimensiunea memoriei necesare pentru codul rezident i s apeleze funcia DOS 31h, care las codul prii rezidente n memorie i termin programul. Prin capturarea unui vector de ntrerupere se nelege nlocuirea vectorului existent, cu unul nou, care conine adresa noii rutine de tratare a ntreruperii, definit n programul TSR. De obicei, noua rutin apeleaz vechea rutin de tratare a ntreruperii. nlocuirea unui vector de ntrerupere, care const n salvarea celui vechi i nscrierea unuia nou, se poate implementa direct de utilizator, utiliznd instruciuni de transfer (mov), dar este mult mai comod utilizarea funciilor DOS (INT 21h) 35h i 25h. Funcia DOS 35h returneaz n ES:BX vechiul vector de ntrerupere, cel care se dorete a fi nlocuit, al crui numr a fost transmis n registrul AL, astfel: mov ah, 35h ; funcia DOS de salvare a vechiului vector mov al, nr_int ; nr. ntr. pe nivelul creia se pune TSR-ul int 21h mov Vechea_Int, bx ; salv. vechiului vector de ntrerupere mov Vechea_Int[2], es ; din ES:BX, n zona TSR-rezident Funcia 25h scrie noul vector de ntrerupere, transmis n registrele DS:DX, n tabela vectorilor de ntrerupere, n locul vectorului al crui numr (index din tabel) este specificat n registrul AL: mov ah, 25h ; funcia DOS de instalare a noului vector mov al, nr_int ; nr. ntr. pe nivelul creia se pune TSR-ul lea dx, Noua_Int; offsetul RTI, adr. seg. este n DS, ntruct ; toate reg. seg., la programele .COM ; sunt iniializate cu segmentul PSP int 21h ; deci nu mai trebuie reiniializat cu ;seg Noua_Int Ca efect, la apariia unei ntreruperi pe nivelul specificat n AL, se va executa noua procedur rezident (TSR), n locul celei vechi. Salvarea vechiului vector i instalarea celui nou se poate face i fr funciile DOS, direct n tabela vectorilor de ntrerupere (TVI); secvena aceasta trebuie ns executat cu ntreruperile dezactivate. Pentru a evita reinstalarea aceluiai program TSR, se verific dac exist deja o copie n memorie a codului rezident, deci dac acesta a fost deja instalat, prin compararea offset-ului noii rutine cu offset-ul vectorului de ntrerupere utilizat. n cazul n care cele dou offset-uri sunt diferite, nseamn c programul nu este rezident i, deci, poate fi instalat. Dac, ns, cele dou

offseturi sunt identice, ntruct se poate ntmpla ca programe diferite s utilizeze acelai vector de ntrerupere i s aib acelai offset, se vor compara identificatorii celor dou programe TSR. Dou TSR-uri diferite pot avea acelai offset al adresei de lansare dac zona de date ce precede nceputul codului TSR are aceeai dimensiune. Din acest motiv trebuie nscris n codul rezident un ir de caractere care s identifice n mod unic acel program; acest identificator de program TSR se plaseaz naintea programului TSR propriu-zis. Pentru a lsa rezident n memorie numai partea rezident a programului TSR se va utiliza funcia 31h, care are ca parametru de intrare dimensiunea de memorie ocupat de partea rezident, exprimat n paragrafe (1 paragraf = 16 octei), transmis n registrul DX (adresa de segment este cea coninut n DS, care are acelai coninut cu toate celelalte registre segment n cazul programelor .COM). Funcia va lsa rezident n memorie codul de lungime specificat i realizeaz ieirea din program, n DOS. Memoria ocupat de partea de iniializare a programului va fi eliberat de DOS.

Activarea unui program TSR


Partea rezident definete o zon de date i prelucrrile respective, reprezentate de una sau mai multe proceduri. Procedurile dintr-un program rezident devin active ca rspuns la un apel direct al unui alt program sau la apariia unei ntreruperi hardware. Dup lansare un lucru nu poate fi ateptat pentru codul apelant: s iniializeze corespunztor registrele segment. Singurul registru segment cu semnificaie pentru codul rezident este registrul CS. Pentru acces la variabilele locale -> rutinele vor iniializa DS sau alte registre segment. De ex. o rutin care numr de cte ori alte programe o apeleaz, dup ce a devenit rezident. Ea ar conine o singur instruciune inc contor, dar s-ar incrementa variabila de la offsetul contor n segmentul referit de DS, i deci nu va incrementa variabila contor. Dou soluii la aceast problem: 1. toate variabilele n segmentul de cod, i s se utilizeze prefixul segment (inc cs:contor); utilizat doar cnd avem puine variabile. 2. salvare registrul segment de date, DS, la intrarea n TSR, iniializarea lui cu noua valoare, iar nainte de ieire din TSR s fie refcut la valoarea avut. Activarea unui program TSR presupune ntreruperea celui curent executat. n cazul n care codul rezident folosete funcii de sistem, el trebuie s testeze, la activarea sa, dac programul ntrerupt executa o funcie DOS/BIOS. Codul rezident nu poate reactiva o funcie de sistem, n timp ce se execut o alt funcie DOS/BIOS, deoarece DOS-ul nu este un sistem de operare reentrant (accesul la disc: 13h, 25h, 26h, nu poate fi ntrerupt). Aceast problem este doar pentru TSR-uri active, ntruct cele pasive sunt apelate i se vor executa n cadrul programului apelant, care nu poate executa simultan dou apeluri. Pentru a evita astfel de operaii sistemul de operare utilizeaz dou variabile: 'eroare critic' i 'seciune sau stare critic', pe care le activeaz corespunztor strii n care se afl. Cele dou variabile pot fi testate de codul rezident, n momentul n care se utilizeaz funcii DOS. Adresele celor dou variabile, i deci starea lor, sunt returnate de funciile 34h (numit indicator seciune critic sau indicator inDOS) i respectiv, 50D6h (eroare critic), n registrele ES:BX. Cele dou adrese pot fi memorate n zona de date a prii rezidente, de ctre partea de iniializare a programului TSR, pentru a le testa direct.

ntreruperea multiplexat, INT 2FH Cnd se instaleaz un program TSR care are i componente pasive, trebuie ales un vector de ntrerupere pe care s fie instalat, astfel ca alte programe s poat comunica cu rutinele sale, pasive. Se poate alege un vector aproape la ntmplare dar aceasta poate conduce la anumite probleme de compatibilitate. Ce se ntmpl dac altcineva utilizeaz deja acest vector de ntrerupere ? n multe situaii alegerea este clar, cum ar fi n situaia n care codul pasiv al TSR -ului extinde anumite servicii (tastatur, video). n celelalte situaii, cum ar fi crearea unui nou driver pentru un nou dispozitiv, care s nu interfere funciile furnizate pentru acest dispozitiv, cu alte ntreruperi, alegerea la ntmplare a unui vector de ntrerupere este riscant. Pentru a rezolva aceste situaii DOS-ul furnizeaz soluia utilizrii unei ntreruperi multiplexate, INT 2FH, care permite instalarea, testarea prezenei i a comunicrii cu un program TSR. Pentru a utiliza aceast ntrerupere, o aplicaie plaseaz o valoare de identificare n AH i un numr de funcie n AL, i apoi execut INT 2FH. Fiecare TSR din lanul INT 2FH va compara valoarea din AH cu propria sa valoare unic de identificare. Dac valoarea sa coincide cu cea din AH, atunci TSR-ul respectiv va prelucra comanda specificat de valoarea din registrul AL. Dac nu se identific, prin valoarea din AH, atunci TSR-ul respectiv transmite controlul la urmtorul manipulator din lanul INT 2FH. Aceasta simplific cumva problema, dar nu o elimin. De obicei, trebuie ales numrul ntreruperii nainte de proiectarea TSR-ului. Cum, ns, o aplicaie va ti ce valoare s ncarce n AH, dac se asigneaz dinamic aceast valoare, cnd TSR-ul este rezident ? Se permite oricrei aplicaii interesate s determine identificatorul (ID) TSR-ului. Prin convenie, funcia zero (AL=0) este un apel ce determin prezena TSR-ului. Acest apel se va realiza nainte de solicitarea oricrui serviciu TSR, pentru a determina dac programul TSR este prezent n memorie.

Dezinstalarea unui program TSR


La dezinstalarea unui TSR trebuie fcute trei lucruri: - oprirea/ suspendarea oricror activiti nerezolvate sau n ateptare (adic, un TSR poate avea anumii indicatori iniializai pentru a lansa anumite activiti ulterioare); - refacerea tuturor vectorilor de ntrerupere la valorile lor iniiale; - eliberarea spaiului de memorie ocupat, adic cedarea spaiului de memorie rezervat napoi ctre DOS, astfel ca alte aplicaii s-l poat utiliza; Dac dezinstalarea TSR-ului const doar n refacerea valorilor vectorilor de ntrerupere, se va crea o problem, dac exist alte TSR-uri care utilizeaz aceeai vectori de ntrerupere. S presupunem c avem urmtorul lan de TSR-uri, pe un anumit nivel de ntrerupere:

Aceasta va dezactiva efectiv TSR-urile nlnuite din program, iar aceste TSR-uri vor avea efecte neateptate, n aceste condiii. O soluie ar fi tiprirea unui mesaj de eroare, care s informeze utilizatorul c nu se poate dezinstala acest TSR, pn nu se dezinstaleaz toate TSR urile instalate anterior acestuia. Problema va fi n a determina TSR-urile nlnuite n ntrerupere. Pentru aceasta tim c vectorii de ntrerupere ar trebui nc s refere rutina noastr, dac acesta este ultimul TSR care se execut. Atunci, trebuie s comparm vectorii de ntrerupere instalai cu adresele rutinelor de servire a ntreruperii respective. Dac toate acestea se potrivesc, atunci se poate elimina n siguran TSR-ul din memorie. Dac, ns, doar unul dintre ei nu se potrivete, atunci nu putem elimina TSR-ul din memorie.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

41. Etapele realizarii unui program n limbaj de asamblare (LA).

Operaia de asamblare se realizeaz n dou etape:


1. La primul pas se genereaz o tabel de simboluri, ce va conine toate numele simbolice din program, exceptnd numele simbolice externe (definite n alte module), instruciuni i directive de asamblare. n aceast etap, asamblorul contorizeaz instruciunile i datele i asociaz numelor simbolice o poziie relativ (deplasament) fa de nceputul programului, ca i cum programul ar ncepe de la adresa zero. n realitate, programul nu se ncarc n memoria RAM de la adresa zero, care este o zon folosit de sistemul de operare, ci de la o adres furnizat de sistemul de operare, n funcie de spaiul de memorie disponibil; din acest motiv, programul furnizat de asamblor este relocabil. 2. La pasul al doilea se obine programul obiect, translatnd programul instruciune cu instruciune i nlocuind n instruciunile respective numele simbolice cu valorile numerice asociate n tabela de simboluri. Programul executabil se obine n urma etapei de editare de leg turi (linkeditare), care permite legarea mai multor module relocabile ntr-un fiier executabil, rezolvndu-se toate referinele ncruciate care au fost folosite n alte module.

n concluzie, etapele care trebuie parcurse pentru realizarea i execuia unui program n limbaj de asamblare sunt descrise schematic n figura urmtoare. Prima etap este cea de editare a programului surs, ce are extensia .ASM, i care poate fi realizat cu orice editor (WS- opiunea NonDocument, NC, editoarele din TPascal sau TC etc.). Dup aceasta urmeaz asamblarea, care furnizeaz programul obiect, cu extensia .OBJ; dac apar erori n faza de asamblare, se reia editarea programului, corectnd erorile respective. La editarea de legturi, pe lng programul curent, pot fi utilizate i alte programe obiect, eventual din bibliotec. Fiierul executabil astfel obinut, poate fi testat i depanat utiliznd una din utilitarele TurboDebugger (TD) sau Debug(ger). Pentru a nu relua de fiecare dat secvena de comenzi, se poate edita un fiier de comenzi (batch), ASM.BAT, pentru asamblarea, editarea de legturi, i eventual tergerea fiierului neutilizat (.OBJ), de forma:
@echo off tasm tlink del % 1.asm % 1.obj % 1.obj

Comanda va fi utilizat astfel:


>ASM nume_fisier.asm

Dac se dorete i obinerea fiierului listing, atunci comanda de asamblare trebuie utilizat cu opiunea /l.

Editare program

Editoare de text: Notepad, editoare NC, C/C++, etc.

fiier surs

nume_fiier.asm

Asamblare

TASM (Borland) MASM (MicroSoft) fiier listing nume_fiier.lst fiier referine nume_fiier.crf

fiier obiect alte programe obiect

nume_fiier.obj

module din bibliotec

Editare de legturi fiier executabil

TLINK LINK

nume_fiier.exe sau nume_fiier.com Debug TD (TurboDebugger)

Depanare

Testare

Erori nume_fii er.com

Editare

Execuie

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

42. Utilizare Debug i TurboDebugger pentru realizare de programe simple i depanarea lor.

Utilitarele Debug i Turbo Debugger


Debug Aceast utilitar este un program de depanare care furnizeaz un mediu de testare controlat pentru fiiere obiect binare i executabile; elimin nevoia de reasamblare a programului pentru a vedea dac o problem a fost rezolvat printr-o modificare minor. El permite s se modifice coninutul unui fiier sau coninutul registrelor CPU, i apoi imediat, s se reexecute un program pentru a verifica validitatea modificrilor fcute. Toate comenzile debug pot fi abandonate n orice moment prin tastarea Ctrl-C. Secvena Ctrl-S suspend afiarea, astfel ca s poat fi citita imaginea de pe ecran, nainte de a se continua defilarea liniilor pe ecran. Afiarea se reia cu orice tast, n afar de Ctrl-C sau Ctrl-S. Sunt dou moduri n care poate fi lansat programul de depanare debug : - primul permite toate comenzile ca rspuns la promtul sau; - cel de-al doilea permite, n plus, specificarea unor comenzi i n linia de comand, utilizat pentru a lansa debug. Metoda 1: >debug Se va lansa n execuie programul debug, care va rspunde cu promptul (-), semnalnd c este gata de a primi comenzi. Se poate lucra n memoria curent, sectoare de disc sau fiiere de pe disc. Dac se primeste mesajul Program terminated normally nu relansai un program; trebuie rencrcat programul cu comenzile N (Name) sau L (Load) pentru o execuie adecvat. Metoda 2: >debug [ nume_fisier [ lista_argumente ]] de exemplu : >debug fisier.exe n urma acestei comenzi se va ncrca n memorie, pe lng utilitara de depanare - debug, i fisier.exe, ncepnd de la adresa 100h, n segmentul disponibil, cel mai de jos. n registrele BX:CX se ncarc numrul de octei (n hexazecimal) ocupai n memorie de programul ncrcat (fisier.exe). Cmpul lista_arumente - reprezint restul liniei de comand utilizat de ctre debug, cnd apeleaz i ncarc fiierul n memorie. Cnd se depaneaz un fiier .exe sau .com nu trebuie modificat coninutul memoriei mai jos de adresa 5Ch sau, altfel, programul de depanare se va termina. Fiecare comand const dintr-o singur liter urmat de unul sau mai muli parametrii. Iat, enumerate, aceste comenzi: A [ adres ] - asamblare de la 'adresa' sau 100h; C domeniu adres - compar dou zone de memorie; D [ domeniu ] - afieaz coninutul unei zone de memorie; E adres [ list ] - introduce 'lista' de octei de la adresa specificat;

F domeniu list - umple zona de memorie cu 'lista' de octei; G [ = adres [ adres ... ] ] - lanseaz n execuie o secven de program de la adresa de dup =, pn la una din adresele urmtoare; H valoare valoare - calculeaz suma i diferena hexazecimal a celor doi parametrii; I valoare - citete de la portul de intrare specificat; L [ adres [ disc : nregistrare nregistrare ] ] - ncarc un fiier sau nregistrri de pe disc; M domeniu adres - mut coninutul unei zone de memorie la adresa specificat; N nume_fisier [ nume_fisier ] - specific numele unui fiier ce va fi invocat de o comand L sau W, ulterioar; O valoare octet - scrie octetul specificat la portul respectiv; Q - sfrit sesiune de lucru Debug, revenire n MS-DOS; R [ nume_registru ] - permite afiarea i modificarea registrelor; S domeniu list - caut 'lista' n domeniul specificat; T [ = adres ] [ valoare ] - execuie pas cu pas a unui program, cu afiarea registrelor, indicatorilor i a instruciunii ce urmeaz sa se execute; U [ domeniu ] - dezasambleaza zona de memorie specificat; W [ adres [ disc : nregistrare nregistrare ] ] - scrie pe disc un fiier sau nregistrri; Parametrii din aceste comenzi sunt desprii ntre ei de spaii libere sau de virgule i au urmtoarea form: disc: octet: nregistrare: indic discul de pe care se citete sau pe care se scrie: 0 = A: , 1 = B: , 2 = C: , 3 = D: ; valoare de tip octet (dou cifre hexazecimale); valoare de 1-3 cifre hexa care indic numrul nregistrrii logice de pe disc i numrul de sectoare de pe disc ce vor fi scrise / citite. nregistrrile logice corespund sectoarelor; o valoare hexa, de cel mult 4 cifre hexa;

valoare: adres:

reprezinta o destinaie, format din dou pri, coninnd fie numele unui registru de segment sau o adres de segment de cel mult 4 cifre hexa, plus o valoare de deplasament (offset), desprit de prima prin dou puncte. Dac se omite numele sau valoarea registrului segment se consider implicit registrul segment DS pentru toate comenzile, cu excepia comenzilor G , L , T , U i W, pentru care se consider registrul CS. De exemplu: CS:0200 04BA:0300 domeniu: conine dou adrese sau 'adresa L valoare', n care valoare reprezint numrul de linii pentru care se d comanda. Exemplu : CS:100 1B00 200:200 L 20 Pentru cea de-a doua adres se poate omite adresa de segment, ntruct se consider egal cu prima adres de segment, specificat. list: o serie de valori de tip octet sau un ir de caractere (string); de exemplu :

f cs:100 42 45 52 54 41 Parantezele drepte [,] utilizate n descrierea comenzilor nu trebuie tastate, deoarece ele specific doar faptul c parametrii respectivi sunt opionali; acolo unde aceste paranteze lipsesc nseamn c parametrii respectivi sunt obligatorii. Dac se introduce o comand eronat (eroare de sintax), Debug nu o ignor i afieaz promptul - ateptnd introducerea de noi comenzi, corecte. Sintaxa comenzilor Debug A [ adres ] Permite editarea unui program n limbaj de asamblare, cu anumite restricii (nu se pot utiliza nume simbolice, deci toate adresele sunt absolute, iar toate constantele sunt specificate prin valori absolute, n hexazecimal, fr a fi urmate de litera h corespunztoare acestei convenii din limbajele de asamblare). Editarea se va ncepe de la adresa specificat sau, n caz contrar, de la adresa 100h n cadrul segmentului disponibil, cel mai de jos; pentru operatorii de conversie de tip: word ptr, byte ptr se pot utiliza formele prescurtate: wo i respectiv by. La nceputul fiecrei linii se afieaz adresa curent din memorie (segment : offset), i se ateapt introducerea de instruciuni, n limbaj de asamblare, terminate cu Enter (CR), dup care se reia editarea cu o linie nou. Pentru linia anterioar el genereaz codul main respectiv i indexeaz, n mod corespunztor, adresa urmtoarei instruciuni. Dac trebuie s se specifice un cmp al unei instruciuni (ca n cazul unei instruciuni de salt la o adres ulterioar), care nu este cunoscut n momentul introducerii liniei respective, se vor completa octeii corespunztori cu zero (sau alt valoare), iar dup editarea celorlalte linii, cnd cmpurile respective devin cunoscute, se poate reedita (reasambla), integral, numai instruciunea respectiv, prin specificarea adresei instruciunii. Dac se introduce o instruciune greit (eroare sinctactic), editorul nu asambleaz linia respectiv i afieaz aceeai adres pe o linie nou, ateptnd introducerea de noi instruciuni, corecte. Revenirea n modul comand, din modul de editare, se realizeaz tastnd Enter (CR), cnd se afieaz pe o linie o nou adres, fr a mai edita nimic pe linia respectiv. Dac comanda nu este urmat de parametru 'adresa', se va continua asamblarea (editarea) de la adresa la care rmsese editarea anterioar. Exemplu : -A 5A2C:200 (CR) 5A2C:0200 _ C domeniu adres Compar zona de memorie specificat de 'domeniu' cu o zon, de aceeai dimensiune, ncepnd de la adresa specificat. Dac cele dou zone de memorie sunt identice nu se afieaz nimic, i se revine n modul comand din Debug. Dac exist diferene ntre cele dou zone de memorie se afieaz octeii diferii i adresele corespunztoare, din cele dou zone, n formatul: adresa_zona_1 octet_zona_1 octet_zona_2 adresa_zona_2 Exemplu : -C 3AB2:100 200 300

- va compara coninutul zonei de memorie cuprins ntre adresele relative 100h i 200h, n segmentul care ncepe la adresa 3A2Bh, cu coninutul unei zone de aceeai lungime care ncepe de la adresa 300h, n acelai segment de memorie. D [ domeniu ] Afieaz coninutul zonei de memorie specificat prin 'domeniu'. Dac comanda nu este urmat de parametrul 'domeniu', atunci se afieaz 128 de octei, ncepnd de la afiarea anterioar. Afiarea se face n dou cmpuri: hexazecimal i ASCII. Pentru caracterele netipribile se afieaz '.'. Se afieaz pe fiecare linie adresa, coninutul hexa pentru 16 octei ncepnd de la adresa respectiv, separai n dou grupe prin -, iar dup aceea caracterele ASCII corespunztoare codurilor hexa, respective. Exemplu : -D 100 10f 3AB2:0100 30 41 42 43 44 45 46 47 - 38 39 4a 4b 4c 4d 4e 4f 0ABCDEFG89JKLMNO E adres [ list ] Comanda permite introducerea n memorie a unor valori de tip octet, ncepnd de la adresa specificat. Dac 'lista' nu este specificat se pot introduce valori octet cu octet. Debug afieaz adresa specificat i vechiul coninut i ateapt: - introducerea unei noi valori, dup care trece la adresa urmtoare, afind din nou vechiul coninut al acesteia; - dac se tasteaz spaiu (blanc), atunci se trece la urmtoarea locaie de memorie, fr modificarea celei curente; - dac se tasteaz - se revine la octetul anterior, pe care l tiprete pe o linie nou, precedat de adresa sa; - dac se tasteaz Enter (CR), se ncheie comanda E. F domeniu list Comanda permite umplerea unei zone de memorie cu valorile din 'lista'. Dac domeniul este mai mare dect lungimea listei, aceasta va fi depusa repetat n memorie pn se umple domeniul specificat. Dac lista este mai lung, valorile suplimentare din list sunt ignorate. G [ = adres [ adres adres ... ] ] Aceast comand permite execuia unui program; programul ncepe de la adresa specificat dup semnul =, care face deosebirea ntre adresa de start i celelalte adrese care reprezint puncte de breakpoint (de suspendare a execuiei programului n momentul n care sunt atinse). n cazul n care se ntlnete o astfel de adres, specificat n comand, se ntrerupe execuia programului i se afieaz adresa la care s-a ajuns, instruciunea executat, coninutul registrelor i a indicatorilor. Se pot specifica pna la 10 de astfel de adrese de breakpoint, dar numai la adrese ce conin primul octet al unei instruciuni. De fapt la adresele de beakpoint se plaseaz codul ntreruperii 3 (INT 3), care trateaz ntreruperea; n stiv trebuie sa fie disponibili cel puin 6 octei, deoarece se salveaz registrul indicatorilor, registrele segment i IP. Lansarea n continuare a programului se poate face doar cu comanda G, fr nici un parametru. Se evit, de obicei, acest mod de lansare n execuie deoarece se poate pierde controlul asupra calculatorului, dac programul nu este bine pus la punct. H valoare valoare

Comanda furnizeaz suma i diferena, fr transport (mprumut), a celor doi parametri. Exemplu : -H 1234 ABCD BE01 6667 I valoare Citete i afieaz un octet de la portul specificat (valoare). L [ adresa [ disc nregistrare nregistrare ]] Comanda fr parametrii ncarc n memorie, de la adresa CS:0100, un fiier al crui nume a fost specificat ntr-o comand N , anterioar; se va depune n BX:CX numrul de octei ncrci. Dac se specific adresa, fiierul va fi ncrcat, n memorie, de la adresa specificat. Dac se utilizeaz comanda cu toi parametrii se vor ncrca, de pe disc, sectoare absolute n locul unui fiier. Unitatea de disc de la care se face citirea este specificat de cmpul 'disc'. Se va ncrca prima nregistrare specificat i se continu cu urmtoarele, pn cnd numrul de sectoare este egal cu cel de-al doilea parametru din comand. De exemplu: -L04BA:100 2 0F 6D se vor ncrca 109 (6Dh) nregistrri, ncepnd cu nregistrarea logic numrul 15 (0Fh), n memorie ncepnd cu adresa 04BA:0100. Parametrul adres este ignorat pentru fiierele .exe. Dac comanda L conine 'adresa', Debug o va aduna la adresa gasit n fiierul .exe, pentru a determina adresa de start la care se ncarc fiierul. M domeniu adres Comanda permite mutarea unui bloc de memorie, specificat de 'domeniu', ncepnd de la adresa specifcat. Mutarea suprapus este fr pierdere de date, deoarece octetul de la adresa ce ar putea fi pierdut prin scriere peste el, este salvat primul. Adresele trebuie sa fie n ordine cresctoare. N nume_fisier Aceast comand realizeaz dou funcii : - asigneaz un nume de fiier pentru o comand L sau W, ulterioar. Dac s-a lansat Debug fr a se specifica numele unui fiier, atunci trebuie utilizat aceast comand nainte de ncrcarea sau scrierea unui fiier; - asigneaz parametrii nume_fisier la fiierul n depanare. O valoare octet Transmite la portul de ieire specificat (valoare), octetul. Q Sfrit sesiune de lucru Debug; revenire MS-DOS.

R [ nume_registru ] Aceast comand, fr nici un parametru, afieaz coninutul tuturor registrelor i starea indicatorilor de condiii. Dac comanda este urmat de numele unui registru, se afieaz coninutul curent al acestuia i se poate modifica coninutul su. Starea indicatorilor de condiii este afiat astfel :

Indicator OF DF IF SF ZF AF PF CF

Set(1) OV DN EI NG ZR AC PE CY

Clear(0) NV UP DI PL NZ NA PO NC

Indicatorii pot fi afiai separat, deci numai ei, prin comanda RF, i se pot modifica prin precizarea mnemonicii dorite a indicatorului respectiv. S domeniu list Se caut n 'domeniul' specificat 'lista' de octei. Lista poate conine unul sau mai muli octei, separai prin spaiu sau virgul. Comanda returneaz adresele la care este gsit lista de octei. T [ = adres ] [ valoare ] Aceast comand execut instruciune cu instruciune ncepnd de la adresa specificat dup semnul =, i afieaz coninutul tuturor registrelor, indicatorilor i urmtoarea instruciune de executat; dac parametrul 'valoare' lipsete, se va executa o singur instruciune, altfel se vor executa cte instruciuni specific acest parametru (hexazecimal). Dac comanda nu are nici un parametru se execut o singur instruciune, de la adresa curent din CS. De exemplu : -T=11A 10 va executa 16 instruciuni ncepnd de la adresa CS:011A. U [ adres ] Comanda dezasambleaz octei i afieaz declaraiile surs ce le corespund, mpreun cu adresele i valorile octeilor. Dac comanda nu este urmat de parametru sunt dezasamblai 32 octei, de la prima adres dup cea afiat de comanda U anterioar. W [ adres [ disc nregistrare nregistrare ] ] Scrie fiierul n depanare ntr-un fiier de pe disc, al crui nume a fost precizat ntr-o comand N, anterioar. n rest comanda este asemntoare, din punct de vedere al parametrilor i al semnificaiei acestora, cu comanda L. n registrele BX:CX trebuie s se specifice numrul de octei de transferat pe disc. Mesaje de eroare bf = s-au tastat caractere greite pentru indicatorii de condiii (bad flag); bp = s-au specificat prea multe puncte de breakpoint ntr-o comand G (too many breakpoints); br = nume gresit de registru (bad register); df = s-au specificat dou valori diferite pentru acelai indicator (double flag).

Turbo Debugger Se poate utiliza Turbo Debugger (TD) pentru a depana orice program scris n C, Pascal sau limbaj de asamblare. El permite s se gseasc eroarea i cauza acesteia; permite execuia parial a programului (executnd instruciune cu instruciune), astfel c se poate examina starea programului. TD permite execuia pas cu pas, linie cu linie, puncte de ntrerupere, vizualizarea variabilelor, registrelor, coninutul stivei, inspectarea, modificarea i urmrirea programului. De asemenea permite depanarea de programe orientate obiect Pascal i C++. n schimb TD nu permite: - editarea programului; el nu conine un editor ncorporat, i, deci nu permite modificarea codului surs. Pentru modificarea acestuia se reediteaz i recompileaz; - recompilarea programului; el nu poate recompila programul, care se realizeaz cu programul original. Meniuri i casete de dialog TD are un meniu global convenabil accesibil, tot timpul, dintr-o 'bar' de meniuri, afiat n partea de sus a ecranului, prin intermediul unui cursor. Sistemul de meniuri are o organizare ierarhic; pentru fiecare meniu se deschide un submeniu (pull-down menu), care permite execuia unei comenzi , sau care permite deschiderea unui nou submeniu (pop-up menu), pentru acele elemente urmate de o iconi meniu (R), sau a unei casete de dialog, pentru acele elemente urmate de o iconi de dialog (...). Sunt patru moduri n care se poate deschide un meniu : - tasta F10, urmat de sgeile de deplasare, stnga respectiv dreapta, pn la poziionarea pe meniul dorit, i apoi tasta Enter (CR), va deschide meniul selectat; - F10, i apoi prima liter a meniului dorit ( spaiu, F , V , R , B , R , O , W , H ); - Alt + prima liter a meniului dorit ( spaiu, F , V , R , B , R , O , W , H ); - cu mouse-ul se deplaseaz pe nivelul dorit i se apas pe butonul din dreapta; Pentru deplasarea de la un meniu la altul se utilizeaz sgeile direcionale (stnga, dreapta), iar pentru deplasarea n cadrul unui meniu specificat, de la o comand la alta se utilizeaz sgeile de deplasare sus, jos. Pentru deplasarea la primul sau ultimul meniu se utilizeaz tastele 'Home' i 'End'. Pentru ieirea dintr-un submeniu i revenirea la meniul anterior se tasteaz 'Esc'; la fel se procedeaz ('Esc') i pentru revenirea dintr-un meniu la fereastra activ. De asemenea tastnd F10, la orice nivel de meniu se revine la fereastra activ. Unele comenzi ale meniului permit accesul rapid, prin tastarea unei anumite combinaii de taste speciale (hot key), care apar, n meniu, n dreapta acestor comenzi. n figura urmtoare se prezint meniul complet al TD. Casetele de dialog pot conine unul sau mai multe elemente de tipul: - butoane, reprezentate printr-un text umbrit (sau n video invers). Dac se alege un buton TD realizeaz imediat aciunea respectiv. Pentru a confirma alegerea fcut se selecteaz butonul 'OK' (tasta special pentru 'ok' este Alt-K), iar pentru a se anula se selecteaz 'Cancel'. Casetele de dialog conin i butonul 'Help', care ofer informaii suplimentare despre ele. - casete de listare, care conin o list de elemente dintre care se poate selecta. Parcurgerea diferitelor casete de dialog se realizeaz cu tastele Tab (nainte) i Shift-Tab (napoi). Pentru a modifica 'butoanele radio' se utilizeaz sgeile direcionale. Pentru a selecta un 'buton' se tasteaz 'Tab' i apoi 'Enter'.

TD este sensibil la context, adic el tie precis ce se caut i unde este cursorul cnd se alege o comand. El utilizeaz aceast informaie cnd rspunde la o comand. De exemplu s considerm o linie dintr-un program Pascal: variabila [ i ] := variabila [ i ] + 1; Dac se tasteaz Ctrl-I, se deschide o fereastr de inspectare (Inspector Window). Cnd cursorul este pe 'variabila', TD prezint informaii despre ntregul vector (variabila). Dac ns cursorul e poziionat (deci supraafiat) pe 'variabila [ i ] ', i apoi se tasteaz Ctrl-I, TD tie c se dorete inspectarea unui singur element i l va afia numai pe acesta. n acest mod se pot obine detalii din ce n ce mai fine asupra programului.

Meniul Turbo Debugger Meniuri Un alt aspect al dependenei de context a TD este la utilizarea meniurilor locale, specifice diferitelor ferestre sau afiri n cadrul ferestrelor. Meniurile locale sunt dependente de fereastra sau afiarea particular n care se afl utilizatorul. Nu pot fi active simultan ambele tipuri de meniuri. Meniurile globale - sunt accesibile prin tasta F10 i sgeile (stnga, dreapta), sau prin tastarea primei litere a meniului ales din bara de meniuri; - meniurile globale sunt, ntotdeauna, accesibile din bara de meniuri (afiat n partea superioar a ecranului ); - coninutul lor este fix; - unele dintre comenzile meniului au taste speciale, rapide, de activare din orice parte a TD. Meniurile locale - un meniu local poate fi activat prin Alt-F10 sau Ctrl-F10, sau prin apsarea butonului drept al mouse-ului; - plasarea i coninutul meniului depinde de fereastra sau afiajul (panoul) n care este utilizatorul, i unde este cursorul; - coninutul poate varia de la un meniu la altul; rezultatele comenzilor cu nume asemntoare, pot fi, totui, diferite, depinznd de context; - fiecare comand dintr-un meniu local are o tast speciala de activare, rapid, constnd din Ctrl + litera supraafiat a comenzii.

O alt facilitate oferit de TD este aceea ca el pastreaz o list a istoriei comenzilor introduse n casetele de intrare i afieaz textul introdus anterior ntr-o astfel de caset, ori de cte ori este apelat. Se poate utiliza aceast list, ca scurttur, pentru a tasta, prin utilizarea sgeilor i a tastei 'Enter', i a selecta orice intrare anterioar. Dac se utilizeaz o intrare nemodificat din lista istoriei, aceast intrare e copiat n vrful listei. Se pot, de asemenea, edita intrrile, prin deplasare cu sgeile pentru a insera cursorul n textul supraafiat, i apoi se editeaz textul, utiliznd 'Del' i 'Backspace'. Lista istoriei afieaz, de obicei, ultimele cinci rspunsuri; dimensiunea poate fi modificat utiliznd programul TDINST.

TD mai permite specificarea incomplet a textului unei intrri, i completarea ei automat prin specificarea corect a unei pri a numelui simbolic din program, i apoi se tasteaz Alt-N. Construirea de Macro-uri Macro-urile sunt taste speciale definite de utilizator. Se poate asigna orice serie de comenzi TD i taste la o singur tast, pentru reluarea lor ori de cte ori este cazul. Pentru a crea un macro se selecteaz OptionsMacros. n acest moment sunt disponibile patru comenzi: Create, Stop Recording, Remove, Delete all, care permit crearea, terminarea, nlocuirea sau tergerea de macrouri. Dup introducerea comenzilor se tasteaz o tast sau combinaie de taste, dorite, la care vor fi asignate acestea. Pentru a termina sesiunea de editare a unui macro, se poate alege ntre: - OptionsMacrosStop Recording; - tastai noua tast sau combinaie de taste, definite anterior; - tastati Alt-.

Ferestrele TD Meniul Sistem ( ) Repaint Desktop - reafieaz ntregul ecran; Restore Standard - reface amplasarea standard a ferestrei; About - afieaz informaii despre TD. Meniul fisier ( File ) Acest meniu afieaz coninutul unui fiier de pe disc sub forma unor linii de octei hexa sau ca text ASCII. Se poate cuta un anumit text sau secvena de octei. Comenzile acestui meniu sunt : Open - deschide un nou program pentru depanare; Change Dir - modific directorul sau discul curent; Get Info - afieaz informaii asupra programului; DOS Shell - revine n DOS pentru a primi comenzi DOS; Resident - termin TD i ramne rezident; Symbol Load - ncarc tabela de simboluri, independent de fiierul .exe, pentru a o nlocui pe cea curent; Table Relocate - seteaz segmentele de baz ale tabelei de simboluri; Quit - revenire n DOS, prsire TD. Comanda FileResident se utilizeaz la depanarea unui program TSR (Terminate and Stay Resident): se ncarc programul TSR, cu tabela de simboluri, ca la un program normal. Apoi se ruleaz programul, se termin i ramne rezident. Se poate seta orice breakpoint, i comanda pentru a face TD rezident. Pentru revenire n TD se utilizeaz tasta de 'ntrerupere' (Ctrl-Break). Meniul View Breakpoints - afieaz punctele de breakpoint; Stack - afieaz stiva pentru apeluri de funcii; Log - afieaz informaii pentru evenimente i date; Watches - afieaz variabilele care sunt monitorizate; Variables - afieaz variabilele globale i locale; Module - afieaz modulul programului surs;

File - afieaz fiier de pe disc (ASCII sau hexa); CPU - afieaz instruciuni CPU, date, stiva; Dump - afieaz date, pe linii; Register - afieaz registrele generale i indicatorii CPU; Numeric processor - afieaz dac este procesor matematic n sistem, sau este emulat; Execution History - afieaz codul de asamblare salvat, pentru reluare; Urmtoarele comenzi sunt utilizate pentru depanarea programelor orientate obiect (OOP): Hierarchy - afieaz lista tipurilor de obiecte sau clase i ierarhia lor; Another Module - realizeaz o alt fereastr 'Module'; Dump - realizeaz o alt fereastr 'Dump'; File - realizeaz o alt fereastr 'File'; Meniul Execuie program (Run) Run - execut programul ncrcat, pn la capt, deci fr opriri; Go To Cursor - execut programul pn la locaia curent a cursorului; Trace Into - execut o singur linie surs sau instruciune, dup cum este activ o fereastr 'Module' sau 'CPU'; Step Over - execut o singur linie surs sau instruciune, mai puin apelurile de proceduri sau funcii (pe care le execut integral); Execute To - execut programul pn la adresa specificat n caseta de dialog; Until Return - execut programul pn cnd se ntlnete instruciunea de revenire din funcie sau procedur; Animate - realizeaz o serie de comenzi Trace Into, actualiznd ecranul dup fiecare comand; permite rularea programului cu o vitez redus. Se poate ntrerupe prin tastarea oricrei taste; Back Trace - revine, pentru execuie, la o linie surs sau instruciune anterioar; Instruction Trace - execut o singur instruciune; Arguments - permite introducerea de noi argumente n linia de comand a programului; Program Reset - permite rencrcarea, de pe disc, a programului curent, dar utilizatorul ramne cu cursorul n poziia n care era la apelarea comenzii; Meniul Breakpoints Toggle - permite starea (poziionarea) sau tergerea unui breakpoint (punct de suspendare a execuiei programului), la adresa curent (supra-afiat) n fereastra 'Module' sau 'CPU'; At - amplasarea unui breakpoint la adresa specificat, n caseta de dialog ce se deschide pentru aceast opiune; Changed Memory Global - amplaseaz punct de breakpoint, global, care devine activ cnd o zon de memorie modific o valoare; Expression True Global - seteaz punct de breakpoint, care este activat cnd valoarea unei expresii, date de utilizator, devine adevarat; Hardware breakpoint - determin activarea unui breakpoint de un driver de dispozitiv (TDH386.SYS ), asistat hardware (placa de depanare hardware);

Delete All - terge toate punctele de breakpoint; Meniul de date (Data) Acest meniu permite examinarea i modificarea datelor programului; se poate evalua o expresie, modifica valoarea unei variabile, i deschide ferestre 'Inspector', pentru a afia coninutul variabilelor. Inspect - inspecteaz o dat obiect, i deschide o fereastr de inspectare, care afieaz coninutul unei expresii sau variabile din program; se poate introduce numele unei variabile sau o expresie complex. Evaluate/Modify - deschide o caset de dialog, care permite introducerea i evaluarea unei expresii; Add Watch - permite adugarea de variabile/expresii n fereastra 'Watches'; Function Return - afieaz ntr-o fereastr 'Inspector' valoarea de returnat a funciei curente ; Meniul Opiuni (Options) Acest meniu permite setarea sau ajustarea unor parametrii care controleaz operarea TD. Language - permite precizarea limbajului surs (C, Pascal sau Asamblare), pentru evaluarea expresiilor din caseta de dialog Evaluate/Modify; Macros - permite definirea de macro-uri , de noi taste, sau tergerea unora, deja asignate la o tast (a fost descris anterior, la construirea de macro); conine urmtoarele comenzi : Create - definete un macro, asociat la o tast; Stop recording - sfritul sesiunii de definire de macro; Removes - terge un macro; Delete All - terge toate macro-urile i restabilete semnificaia iniial a tastelor; Display Options - deschide o caset de dialog, n care se pot poziiona cteva opiuni, care comand modul de afiare; Path for Source - se precizeaz directoarele n care TD caut fiiere surs; Save Options - se deschide o caset de dialog, din care se pot salva opiunile curente (macro, formate de afiare, ferestre i toate setrile fcute n meniul 'Options') ntr-un fiier de configuraie, pe disc; Restore Options - reface opiunile de pe disc, prin selectarea fiierului de configuraie, dorit; Meniul Window Zoom - permite modificarea dimensiunii ferestrei la ntregul ecran, i invers; Next - activeaz ferestrele urmtoare; Next Pane - trece la urmtoarea caset dintr-o fereastr; Size/Move - mut sau modific dimensiunile ferestrei; Iconize/Restore - reduce fereastra la o iconi (un simbol redus) sau o reface; Close - nchide fereastra; Undo Close - redeschide ultima fereastr, care a fost nchis; Dump Pane to Log - scrie caseta curent n fereastra 'Log'; User Screen - afieaz 'ecranul utilizator' - adic afirile (ieirile) programului; Open Window list - afieaz lista ferestrelor deschise, pentru activare; Window Pick - afieaz un meniu cu meniurile deschise, dac sunt deschise mai mult de 9;

Meniul de informatii (Help) Index - acces la indexul de informaii, pentru selectarea topicii pentru care se doresc informaii; Previous Topic - se reafieaz la ultimul ecran cu informaii; Help on Help - informaii despre utilizarea acestui meniu;

Lista Comenzilor (Taste speciale) F1 = informaii despre dependena de context a TD; F2 = BreakpointsToggle; F3 = ViewModule; F4 = RunGo to Cursor; F5 = WindowZoom; F6 = WindowNext Window; F7 = RunStep Over; F8 = RunRun; F10 = acces la bara meniu; Alt-F1 = HelpPrevious Topic; Alt-F2 = BreakpointsAt; Alt-F3 = WindowsClose; Alt-F4 = RunBack Trace; Alt-F5 = WindowUser Screen; Alt-F6 = WindowUndo Close; Alt-F7 = RunInstruction Trace; Alt-F8 = RunUntil Return; Alt-F9 = RunExecute To; Alt-F10 = meniul local al ferestrei; Alt-19 = comutare ntre ferestrele numerotate de la 1 la 9; Alt-spatiu = intra n meniul Sistem; Alt-B = meniul Breakpoints; Alt-D = meniul Data; Alt-F = meniul File; Alt-H = meniul Help; Alt-O = meniul Options; Alt-R = meniul Run; Alt-V = meniul View; Alt-W = meniul Window; Alt-X = meniul FileQuit - iesire di TD, revenire n DOS; Alt-= = meniul OptionsMacrosCreate; Alt-- = meniul OptionsMacrosStop Recording; Ctrl-F2 Ctrl-F4 Ctrl-F5 Ctrl-F7 Ctrl-F8 = = = = = RunProgram Reset - sfrit sesiune de depanare i reiniializare, o nou lansare; DataEvaluate; WindowSize/Move; DataAdd Watch; BreakpointsToggle;

Ctrl-F9 = RunRun; Ctrl-F10 = meniul local al ferestrei; Ctrl = deplaseaz adresa de start, n caseta Code/ Data /Stack (CPU), cu un octet, n sus; Ctrl = deplaseaz adresa de start, n caseta Code/Data/Stack (CPU ), cu un octet, n jos; Ctrl-A = deplasare pe cuvntul anterior; Ctrl-C = defilare un ecran, n jos; Ctrl-D = deplasare cu o coloan; Ctrl-E = deplasare cu o linie, n sus; Ctrl-F = deplasare pe cuvntul urmtor; Ctrl-R = defilare un ecran, n sus; Ctrl-S = deplasare cu o coloan, la stnga; Ctrl-X = deplasare cu o linie, n jos; Shift-F1 = HeplIndex; Shift-Tab = deplasarea cursorului n caseta anterioar a ferestrei, sau n caseta de dialog; Shift = deplasarea cursorului ntre casetele Shift = unei ferestre (caseta din direcia sgeii Shift = devine caseta activa ); Esc = nchide o fereastr 'Inspector', sau ieire din meniu; Ins = selecia unui bloc de text (ce va fi supra-afiat), mpreun cu sgeile , ; Tab = WindowNextPane;

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

43. Elaboraea de programe simple i depanarea lor, utiliznd instruciuni de transfer, sub Debug/ TD.

Editarea i execuia unor programe simple n Debug.


Interschimbarea a dou locaii de memorie (3000h:200h i 3000h:300h, respectiv, de tip cuvnt). Adresele absolute propuse, 3000h:200h, pot fi modificate dac nu sunt disponibile (de fapt este vorba de modificarea adresei de segment, 3000h, cu o adres superioar) a) Utilizarea utilitarei Debug Pentru exemple simple, compuse doar din cteva instruciuni, este mult mai simplu s utilizm Debug-ul care permite att editarea ct i execuia acestor programe. Editorul este unul foarte redus i simplu, ntruct nu permite corectarea liniilor scrise, dect prin reeditarea lor; mai mult, liniile urmtoare celor eronate, care au fost reeditate trebuie rescrise i ele, ntruct pe masura editrii liniile sunt translatate n cod main i depuse n memorie peste codul anterior editat, astfel nct dup liniile corectate vor urma 'fragmente' din liniile urmtoare celor corectate, n funcie de numrul de octei ocupat de liniile reeditate. Singura situaie n care nu este necesar reeditarea liniilor urmtoare, celor corectate, este cea n care numrul de octei al instruciunilor reeditate este egal cu numrul de octei avut de aceste instruciuni, nainte de reeditare (dar probabilitatea este destul de mic). Revenind la problema propus, secvena de comenzi necesar este urmtoarea: - se lanseaz, mai nti utilitara Debug: C:\> Debug - dup care se intr n modul de comand al acesteia, i se d comanda de asamblare: - a2000:100 2000:0100

mov

ax,3000

Textul scris supraimprimat reprezint comenzile introduse de utilizator, restul (adresa, scris cursiv) reprezentnd rspunsurile utilitarei Debug. Editarea unei linii se termin prin apsarea tastei RETURN; pn atunci se pot face corecii ale textului scris, utiliznd tast ele de deplasare (sgeile) i tastele DEL, BS. n continuare, dup fiecare linie introdus, care este imediat asamblat, asamblorul afieaz locaia de memorie a urmtoarei linii, pe care pentru a nu ngreuna urmrirea programului am omis-o (dar ea este permanent afiat). deci programul propriu-zis este urmtorul: mov mov mov xchg mov mov int ax,3000 ds,ax ax,[200] ax,[300] [200],ax ax,4c00 21

Reamintim ca pentru asamblorul Debug toate datele imediate sunt interpretate implicit n hexazecimal, deci nu este nevoie s punem dup o valoare numeric tipul 'h', acesta fiind implicit; mai mult chiar dac din greeal tastai 'h'-ul asamblorul v va semnala o eroare pe linia respectiv i continu editarea de la aceeai adres, ca de altfel pentru orice alt eroare. Ct timp se afieaz adresa locaiei urmtoare suntei n modul 'editare'. Pentru a executa programul trebuie s prsii modul de editare (asamblare) i s trecei n modul comand, prin tastare RETURN pe o linie nou, urmtoarea celei ce reprezint ultima instruciune din program. Pentru execuie se poate opta pentru execuia pas cu pas, dac programul nu este prea lung i dorii s vedei ce se ntmpl dup execuia fiecrei instruciuni, sau dac dorii s depanai programul. Comanda pentru execuie pas cu pas este, n acest caz: -T2000:100 care va executa doar prima instruciune, dup care pentru execuia urmtoarelor instruciuni se va tasta, n mod repetat pentru fiecare instruciune, doar: -T Dac se dorete execuia integral a programului se va utiliza comanda G: - G = adresa de start (segment:offset), adresa de sfrit (offset-ul) adresa de sfrit = prima adres, furnizat de asamblor, dup cea a ultimei instruciuni din programul editat. Pentru vizualizarea rezultatelor i introducerea datelor se vor utiliza comenzile: D, E, F, descrise n capitolul precedent.

b) Editare utiliznd un editor de text. Pentru editare se poate folosi orice editor de text disponibil, cum ar fi editoarele din mediile C, Pascal, editorul din NC (cel mai simplu i mai direct de folosit), i altele. Programul editat, cu un astfel de editor, este urmtorul: prog start: segment word assume cs:prog mov ax,3000h mov ds,ax mov ax,[200] xchg ax,[300] mov [200],ax mov ax,4C00h int 21h ends start public 'code' ; adresa de segment unde vor fi datele introduse din Debug ; adresele relative ale celor doi operanzi

; revenire in DOS

prog end

Dup editare programul va fi salvat ntr-un fiier cu extensia 'asm': intersch.asm. Pentru obinerea fiierului obiect se va apela utilitara TASM: C:\>tasm intersch.asm care va furniza, dac nu sunt erori, fiierul obiect: intersch.obj. Urmtoarea etap este cea de editare de legturi, utiliznd utilitara TLINK: C:\>tlink intersch.obj care va furniza fiierul executabil: intersch.exe. Acesta poate fi direct executat, dar pentru a vedea efectele sale el va fi rulat sub controlul Debugger-ului: C:\>debug intersch.exe Comanda de lansare este aceeai ca n cazul anterior. Pentru a vizualiza programul se va utiliza comanda U, descris n primul capitol. Pentru exemplele urmtoare se vor prezenta doar programele, fr detaliile de editare i etapele necesare execuiei programelor, ntruct ele au fost prezentate pe larg pentru acest prim exemplu, dar i n primul capitol. Interschimbarea a dou locaii succesive de memorie (3000h:200h i 201h, respectiv, de tip octet). Pentru astfel de situaii (informaii aflate la locaii succesive de memorie) se va utiliza pentru adresare un registru index (SI sau DI) sau de baz (BX, de regul sau BP, dar acesta face referire implicit la segmentul de stiv, referit de SS) a) Utilizarea utilitarei Debug (aceasta nu permite utilizarea de comentarii). mov mov mov mov inc xchg dec mov mov int ax,3000 ds,ax si,200 al,[si] si al,[si] si [si],ax ax,4c00 21

b) Editare utiliznd un editor de text. prog start: segment word assume cs:prog mov ax,3000h mov ds,ax mov si,200h mov al,[si] inc si xchg al,[si] dec si mov [si],al mov ax,4C00h int 21h ends start public 'code' ; adresa de segment unde vor fi datele introduse din Debug ; adresa relativa a primului octet ; citirea primului octet ; pozitionare pe cel de-al doilea octet ; interschimbare (AL) <-> al doilea octet ; revenire la adresa primului octet ; depunerea celui de-al doilea octet, deci interschimbarea ; revenire in DOS

prog end

Adunarea a dou locaii succesive de memorie (3000h:200h i 202h, respectiv, i depunerea rezultatului n continuare, dup cei doi operanzi, de tip cuvnt, fr semn). a) Utilizarea utilitarei Debug. mov mov mov mov add add add mov mov int ax,3000 ds,ax si,200 ax,[si] si,2 ax,[si] si,2 [si],ax ax,4c00 21

b) Editare utiliznd un editor de text. prog start: segment word public 'code' assume cs:prog, ds:date mov ax,3000h ; adresa de segment unde vor fi datele introduse din Debug mov ds,ax mov si,200h ; adresa relativa a primului cuvant mov ax,[si] ; citirea primului cuvant add si,2 ; pozitionare pe cel de-al doilea cuvant

add jc

ax,[si] afis_mesaj

add mov rev_DOS: mov int afis_mesaj: lea mov int jmp prog ends

si,2 [si],ax ax,4C00h 21h dx,mes_err ah,9 21h rev_DOS

; (AX) = suma celor doi octeti ; aici se poate testa indicatorul (CF) pentru depasire rezultat ; (CF) = 1 ? , daca da -> mesaj depasire ; numerele sunt fara semn, deci rezultatul este > 65535 ; daca consideram numerele cu semn, atunci rezultatul va fi ; in intervalul [-32768,+32767], pentru detectarea depasirii ; limitei superioare sau inferioare in locul instructiunii 'jc' ; se va utiliza instructiunea 'jo' (Jump Overflow) ; adresa rezultatului ; depunerea celui de-al doilea octet, deci interschimbarea ; revenire in DOS

; afisarea mesajului de eroare

date segment mes_err db date ends end start

'eroare: depasire dimensiune cuvant a rezultatului'

Adunarea elementelor unui sir de valori (de tip cuvnt, cu semn). a) Utilizarea utilitarei Debug Se adun 16 cuvinte ncepnd de la adresa 3000:200, cu rezultat de lungime 16 bii, fr detectarea depirii. mov mov mov mov mov add add loop mov mov mov int ax,3000 ds,ax si,200 cx,10 ax,0 ax,[si] si,2 adresa_add_ax_si si,300 [si],ax ax,4c00 21

Programul va depune rezultatul la adresa 3000h:300h. n locul adresei 'adresa_add_ax_si' se va pune adresa fizic a instruciunii 'add ax,[si] ', furnizat de asamblor, i nu o eticht simbolic, cum este prezentat (de altfel nici nu se poate n acest asamblor).

b) Editare utiliznd un editor de text. Se adun un numr oarecare de cuvinte i se semnaleaz o eventual depire a formatului iniial de 16 de bii. date segment sir dw 0f54h, 20000, 0ff56, 8000 ; si sirul poate continua lung_sir equ ($-sir)/2 rezultatdw 2 dup (?) mes_err db 'eroare: depasire dimensiune cuvant a rezultatului' date ends end start prog segment word public 'code' assume cs:prog, ds:date start: mov ax,date ; adresa de segment pentru date mov ds,ax lea si,sir ; adresa relativa a primului cuvant mov ax,0 ; initializare rezultat mov cx,lung_sir ; contor numar de cuvinte de insumat reia_add: add ax,[si] ; adunare cuvant curent jo afis_mesaj ; (CF) = 1 ? , daca da -> mesaj depasire superioara/inferioara add si,2 ; pozitionare pe cel de-al doilea cuvant loop reia_add ; daca nu s-a terminat sirul, reia adunarea, cu urmatorul cuvant mov rezultat,ax ; memorare rezultat rev_DOS: mov ax,4C00h ; revenire in DOS int 21h afis_mesaj: lea dx,mes_err ; afisarea mesajului de eroare mov ah,9 int 21h jmp rev_DOS prog ends

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

44. Funcii DOS i BIOS.

Utilizarea funciilor BIOS


n timp ce BIOS-ul manipuleaz ntreruperile INT 00H 1FH, DOS-ul manipuleaz ntreruperile INT 20H 3FH. Principalele puncte de intrare ale BIOS-ului ce pot fi folosite de utilizator sunt urmtoarele: INT 00H = este de fapt o excepie de mprire prin zero, pentru care se afieaz un mesaj corespunztor; INT 01H = Single Step, este utilizat de programele de depanare (Debug, TD); INT 02H = ntrerupere nemascabil (NMI) care este utilizat de erori hardware severe, cum ar fi eroarea de paritate la memorie; INT 03H = este ntreruperea de breakpoint, adic cea utilizat de programele de depanare, ntruct ocup un singur octet i poate substitui uor primul octet al instruciunii unde se stabilete punctul de suspendare a execuiei programului (este descris n seciunea dedicat ntreruperilor); INT 04H = ntreruperea de depire a rezultatului operaiilor aritmetice (INTO); INT 05H = ntreruperea imprim memoria video; aceeai operaie poate fi activat extern (nu intern, cum o face instruciunea INT 05H) prin combinaia de taste CTRL+PrtSc; la adresa 50:00H din zona de date BIOS se poate citi starea acestei operaii; INT 08H = ceasul de timp real; o ntrerupere hard actualizeaz ora i data sistemului (un circuit de ceas programabil genereaz o ntrerupere la fiecare 54,9256 ms, adic de 18,2 ori pe secund); INT 09H = ntrerupere dedicat tastaturii, generat la apsarea i eliberarea unei taste; INT 0BH, INT 0CH = controleaz dispozitivele seriale, adic porturile COM1 i COM2; INT 0DH, INT 0FH = controleaz dispozitivele paralele, adic porturile LPT1 i LPT2; INT 0EH = controleaz operarea dischetei; INT 10H = utilizare terminal grafic; INT 11H = determinare configuraie sistem i returneaz valoarea la locaia BIOS 40:10H, n AX; INT 12H = determinare dimensiune memorie RAM (returneaz n AX dimensiunea memoriei de baz, exprimat n Ko); INT 13H = utilizare disc, adic operaiile de intrare/ieire, formatare etc. (numrul funciei solicitate se transmite n AH); INT 14H = utilizare interfa serial prin portul de comunicaie serial RS232; INT 15H = servicii de sistem determinate de valoarea transmis n AH, cum ar fi: POST (power-on self-testing, AH=21H), adic testrile executate de sistem la pornire; citire stare sistem (AH=43H); suport joystick (AH=84H); determinarea dimensiunii memoriei extinse (AH=88H); comutare procesor n modul protejat (AH=89H); interfaa cu mouse-ul (C2H). Dup aceast operaie trebui reactivate ntreruperile, ntruct revenirea se produce fr a le reactiva.

INT 16H = utilizare tastatur; INT 17H = utilizare imprimant; INT 18H = intrare de baz n ROM; apelat de BIOS dac sistemul este pornit fr un disc care s conin programele sistemului de operare DOS; INT 19H = ncrctorul sistemului de operare de pe disc; dac este disponibil o dischet sistem, cu sistemul de operare DOS, va citi pista 0, sectorul 1 n locaia de ncrcare n memorie la adresa 7C00H i transfer controlul la aceast locaie; dac nu exist un disc sistem, se transfer controlul la punctul de intrare din ROM, via INT 18H; INT 1AH = utilizare ceas de timp real, adic se poate citi sau iniializa ora n funcie de codul transmis n AH; INT 1BH = permite controlul asupra tastei Break; cnd se tasteaz CTRL+Break, ROM BIOS transfer controlul la adresa sa de ntrerupere, unde este iniializat un indicator.

Utilizarea terminalului grafic, INT 10H Sistemul de afiare are dou componente de baz: adaptorul video i monitorul (ecranul monocrom sau color, pe care se afieaz text sau imagini grafice). Indiferent de tipul monitorului, acesta permite afiarea unei matrice de puncte pe ecran (pixeli). Caracterele alfanumerice sunt de fapt afiate tot ca o matrice de pixeli, trimis monitorului de ctre adaptorul video. Capacitatea unor monitoare de a afia att text, ct i imagini grafice, depinde numai de adaptorul video, nu i de monitor. Informaia care se afieaz pe ecran (text i imagini grafice) la un moment dat este pstrat n memoria adaptorului video, numit memoria ecran. Aceast memorie poate fi accesibil fie utiliznd funcii BIOS (INT 10h), fie direct prin program (prin instruciuni de transfer), pentru a nscrie informaia ce dorim s se afieze. Pentru a obine acces direct la aceast memorie, trebuie s cunoatem modul de organizare a informaiei, precum i spaiul de adrese n care este plasat memoria ecran. Dei fizic memoria ecran este amplasat pe placa adaptorului video, ea este accesibil n spaiul de adrese al procesorului. Capacitatea memoriei ecran depinde de tipul adaptorului video, variind intre 64Ko si 512Ko. Modul de organizare al informaiei n memoria video este determinat de modul de lucru: text sau grafic. Terminalul video lucreaz ntr-unul din modurile de adresare a I/O: maparea I/O peste memoria calculatorului. Un text ecran de 8025 caractere este de fapt un vector bidimensional de cuvinte, fiecare cuvnt din acest vector corespunznd unui caracter de pe ecran. Acest vector este memorat imediat dup spaiul de memorie de 640K. Dac se memoreaz date n acest spaiu utiliznd instruciunile obinuite (de tipul mov) se vor afecta caracterele ce apar pe ecran. Adresa memoriei video este B800:0000H. Un exemplu de adaptor larg rspndit este VGA (Video Graphics Array), succesor al adaptorului EGA (Enhanced Graphics Adapter). Pentru modul grafic, caracteristice sunt modurile: 640 x 480 pixeli i 16 culori simultan pe ecran (din 256 culori posibile), respectiv 320 x 200 pixeli i 256 culori simultan pe ecran. Programele care obin acces direct la memoria ecran trebuie sa in cont de tipul adaptorului, deoarece n modul de lucru grafic organizarea informaiei n memoria ecran i spaiul de adrese al acesteia difer de la un tip de adaptor la altul. n modul de lucru text ns, informaia este organizat la fel. Accesul la memoria ecran se poate face fie prin intermediul rutinelor din BIOS, care ofer ns avantajul portabilitii programelor n detrimentul vitezei de

execuie, fie direct din program, ca la orice locaie de memorie, n aplicaii care necesit viteze ridicate (de exemplu animaie). Pentru a stabili tipul adaptorului video din calculator, se poate utiliza funcia BIOS 1Bh, INT 10h, care ntoarce n registrul AL o valoare corespunztoare (3adaptor EGA, 4-adaptor VGA). Terminalul grafic poate lucra n dou moduri: alfanumeric (text) i grafic. Modurile de lucru alfanumerice sunt caracterizate de numrul de linii caracter (25), numrul de coloane caracter (40 sau 80), atribute de culoare i numrul de pagini. Fiecare caracter este descris printr-un ablon de puncte. ablonul cu descrierea formei caracterului se afl ntr-o tabel din memorie. Pentru acest mod de lucru, un caracter este specificat prin codul ASCII i atributul de culoare, care conine trei elemente (culoare fond ultimii 3 bii, intensitate high 1 bit, culoare caracter urmtorii 3 bii, afiare continu sau intermitent 1 bit). Textul poate fi memorat n memoria video n pagini. O pagin memoreaz un ntreg ecran de text (date) i este numerotat ncepnd de la 0, pentru modul normal cu 80 de coloane. n acest, mod pagina 0 este implicit i ncepe n zona de memorie video de la adresa B800, pagina 1 ncepe la B900, pagina 2 la BA00, iar pagina 3 la BB00. Se poate afia o singur pagin pe ecran la un moment dat. ntruct fiecare caracter de afiat necesit doi octei de memorie (caracterul, octetul mai puin semnificativ i atributul, octetul mai semnificativ) o pagin ntreag de caractere, cu 80 de coloane i 25 de linii, va necesita 80252=4000 octei, 2000 caractere i 2000 fiind ocupai de atributele acestora. Memoria video alocat efectiv pentru fiecare pagin de memorie este de 4K, adic 4096 octei, astfel nct ultimii 96 de octei de dup fiecare pagin ecran nu sunt folosii. Adaptoarele pentru monitoarele color actuale furnizeaz 32K pentru afiri de text i permite alegerea uneia dintre cele opt afiri diferite posibile. Fiecare afiare ncepe la o adres multiplu de 4K, de la adresele B800:0H, B800:1000H, B800:2000H,..., B800 :7000H. Cele mai multe adaptoare color moderne ofer memorie de la adresa A000:0H pn la B000:FFFFH (i chiar mai mult), dar pentru modul text se utilizeaz doar cei 32K de la B800:0H pn la B800:7FFFH. Memoria video poate fi adresat exact ca i memoria RAM. n aceast memorie se pot memora totui i variabile program sau chiar cod, dar nu este recomandat. Chiar dac memorarea se realizeaz ntr-o pagin ce nu este activ, procedeul este n continuare nerecomandat, ntruct accesul la adaptorul video este foarte lent (memoria principal este de dou pn la de zece ori mai rapid). Pentru un adaptor color, formatul octetului ce reprezint atributele de afiare este urmtorul: biii 0-3 culoare caracter: 0000-negru, 0001-albastru, 0010-verde, 0011-azuriu (cyan), 0100-rou, 0101-magenta, 0110-maro, 0111-gri deschis, 1000-gri nchis, 1001-albastru deschis, 1010-verde deschis, 1011-azuriu deschis, 1100-rou deschis, 1101-magenta deschis, 1110-galben, 1111-alb; biii 4-6 culoare fundal: culorile corespunztoare combinaiilor de la 000 la 111 su nt aceleai ca i culorile anterioare din intervalul 000-0111; bitul 7: plpire (blinking), dac este 1, altfel caracterul este afiat normal. Modul de lucru grafic se caracterizeaz prin numrul de linii i coloane (de puncte de pe ecran pixeli), precum i prin culoare. ntreruperile manipuleaz ecranul transfernd datele direct n memoria video. Datele se pot transfera direct n memoria video, dar ntruct nu ntotdeauna adresele sunt aceleai pe toate sistemele, se recomand utilizarea operaiilor INT 10h i INT 21h, care cunosc locaia memoriei video.

Pentru utilizarea terminalului grafic se pot utiliza urmtoarele funcii (INT 10h), selectate de coninutul registrului AH, astfel: Funcia 0 selecie mod de lucru: Registrul AL va specifica modul de lucru selectat: 0 = alfanumeric 40 x 25, alb/negru; 1 = alfanumeric 40 x 25, color; 2 = alfanumeric 80 x 25, alb/negru; 3 = alfanumeric 80 x 25, color; 4 = grafic 320 x 200, color; 5 = grafic 320 x 200, alb/negru; 6 = grafic 640 x 200, alb/negru, etc.; 17= grafic, 640 x 480 pixeli, alb/negru (VGA); 18= grafic, 640 x 480 pixeli, 16 culori (VGA); 19= grafic, 320 x 200 pixeli, 256k culori. Funcia 1 selecie form i dimensiune cursor: Cursorul nu face parte din setul de caractere ASCII i exist numai n modul text. Forma normal a cursorului este similar caracterului subliniere (underline), dar poate fi extins pe vertical, astfel: (CH) = numrul liniei inferioare (minim 0); (CL) = numrul liniei superioare (maxim 7 sau 14 pentru VGA). Funcia 2 poziionare cursor pe ecran: (DH) = numrul liniei; (DL) = numrul coloanei; (BH) = pagina. Funcia 3 citire coordonate i form cursor: (BH) = numrul paginii pentru care se citete poziia. rezultatul va fi n registrele: (DH,DL) = linia, coloana; (CH,CL) = forma cursorului. Funcia 4 citire poziie indicator optic: (AH) = 1; dac este 0, nu s-a cerut poziia; (DH,DL) = poziia linie/coloan caracter; (CH,BX) = poziia linie/coloan, puncte pe ecran (pixeli). Funcia 5 selecie pagin activ pe ecran: (AL)= numrul paginii de activat (numai n mod alfanumeric); Funcia 6 defilarea n sus a imaginii (scroll up): Dac un program afieaz text pe ecran, dup ce scrie ultima linie va continua s scrie urmtoarele linii de text de la nceputul ecranului (prima linie). Soluia este de a deplasa liniile scrise n sus i a insera linii albe (vide) n partea de jos a ecranului. Funcia aceasta permite

tergerea (defilarea) ecranului sau numai a unei pri a acestuia, definind o fereastr pentru care se pot stabili atributele de afiare (culoare fundal i cea pentru afiare caractere). (AL) = numrul de linii de deplasat; 0 pentru ntreg ecranul sau fereastra specificat; (CH,CL) = limite fereastr, colul din stnga sus, n care se face deplasarea (linie/coloan); (DH,DL) = limite fereastr, dreapta jos; (BH) = atribut de culoare pentru liniile introduse. Iat secvena pentru defilarea cu o singur linie: mov mov mov mov int ax, 0601h bh, 71h cx, 00h dx, 184fh 10h ; defilare cu o linie ; atribut fundal (alb-7), culoare caracter (bleu-1) ; de la 0:0 ; tot ecranul 24:79

Pentru ca secvena anterioar s tearg ntreg ecranul, este suficient s ncrcai n AX valoarea 0600h (n loc de 0601h) Registrele CX i DX permit definirea doar a unei ferestre (poriune rectangular a ecranului) pentru defilare. n acest caz, trebuie coordonat valoarea din AL cu distana din CX:DX. De exemplu, vom defini o fereastr delimitat de colul din stnga sus 12:25 i cel din dreapta jos 18:54, deci o fereastr de 7 linii i 30 de coloane, care va fi tears. mov mov mov mov int ax, 0607h bh, 30h cx, 0C19h dx, 1236h 10h ; defilare cu 7 linii ; atribut fundal, culoare caracter ; de la 12:25 ; pana 18:54

Deoarece atributul pentru o fereastr rmne activ pn cnd alt operaie l modific, se pot defini n acelai timp mai multe ferestre cu atribute diferite. Funcia 7 defilare n jos a imaginii (scroll down): Se utilizeaz aceleai registre ca la funcia de deplasare n sus, cu aceeai semnificaie, a imaginii dintr-o fereastr, coninut n pagina activ, dar de data aceasta deplasarea se face n jos i liniile vide apar n partea de sus a ferestrei. Funcia 8 citire caracter i atributele sale de pe ecran, din dreptul cursorului: (BH) = pagina referit. Dup apelul funciei, valorile returnate sunt: (AL) = codul ASCII al caracterului citit; (AH) = atribut de culoare (pt. alfanumeric). Funcia 9 afiare caractere pe ecran, la poziia cursorului: (BH) = numrul paginii n care se face afiarea;

(AL) = codul ASCII al caracterului de afiat; (CX) = numrul de repetri ale afirii acestui caracter; (BL) = atribut de culoare. Aceast operaie nu avanseaz cursorul i nici nu rspunde la caractere de tip semnal sonor (bell), linie nou (line feed), revenire la nceput de linie (carriage return) sau tabulare (tab); n schimb, sunt afiate ca i caractere ASCII. Dac afiarea depete linia respectiv, se va continua afiarea pe linia urmtoare, de la capt. Funcia 12 (0CH) afiare punct pe ecran (pixel): (DX) = numrul liniei; (CX) = numrul coloanei; (AL) = culoare punct (dac primul bit este 1, se va face un sau exclusiv ntre noua culoare i cea curent). Modurile de lucru VGA 0DH, 0EH, 0FH i 10H furnizeaz 16, 8, 4 i respectiv 2 pagini de memorie video. Numrul paginii implicite este 0. Funcia 13 (0DH) citire culoare punct de pe ecran: (DX,CX) = numrul liniei/coloanei punctului; (AL) = codul culorii punctului referit. Funcia 14 (0EH) afiare caracter i actualizare poziie cursor: (AL) = codul ASCII al caracterului de afiat; (BL) = culoare caracter, pentru modul grafic; (BH) = numrul paginii n care se face afiarea. Aceast funcie permite utilizarea monitorului ca terminal pentru afiare. Dup afiarea caracterului, cursorul este avansat pe poziia urmtoare, pe aceeai linie sau la nceput de linie sau de pagin; caracterele speciale (bell=7, backspace=8, line feed=10, carriage return=13) sunt interpretate ca i comenzi pentru formatarea ecranului. Funcia 15 (0FH) citire caracteristici mod de lucru: Dup apelul funciei, aceasta returneaz urmtoarele valori: (AL) = numrul modului de lucru; (AH) = numrul de coloane caracter (caractere pe linie: 20, 40 sau 80); (BH) = numrul paginii curente. Utilizarea modului grafic n modul grafic, pe ecran se afieaz imagini grafice alctuite din puncte (pixeli). Numrul de bii prin care se reprezint un pixel n memoria ecran depinde de numrul de culori ce pot fi afiate pe ecran. Astfel, pentru un monitor monocrom, este suficient un singur bit, cu semnificaia bit aprins(1), respectiv bit stins (0). n general, pentru a afia 2n culori sunt necesari n bii/pixel. Ecranul este considerat ca fiind mprit ntr-o matrice de puncte, fiecare avnd culoare proprie. Dimensiunea matricei de pixeli determin rezoluia care se definete ca fiind:

rezoluia = numr_pixeli_pe_orizontal numr_pixeli_pe_vertical n funcie de rezoluie i de numrul de culori ce se pot afia simultan pe ecran, n memoria video se pot pstra una sau mai multe imagini ecran, numite pagini video. Conceptul de pagin video (ecran) este utilizat i n mod text. Folosirea paginilor video se recomand n aplicaii de animaie pe calculator sau n afiarea unor imagini complexe, care necesit un timp mare de generare a imaginii. Modul grafic utilizeaz la afiare pixeli pentru a genera (desena) pe ecran, n diverse culori. De exemplu, funcia 0, INT 10H, cu o valoare n AL mai mare dect 4 va defini un mod grafic; pentru AL = 10H este modul grafic, color, cu rezoluia 640350. Fiecare octet din memorie reprezint 4 pixeli (cte doi bii pentru fiecare pixel), numerotai de la 0 la 3. Sunt disponibile patru culori, n orice moment, numerotate de la 0 la 3. Limitarea numrului de culori este dat de numrul de bii utilizai (2, deci n total 4 combinaii). Dar pixelul 0 poate fi ales din cele 16 culori pentru fundal (background). Ceilali trei pixeli pot fi alei din dou palete de culori, de cte trei culori. Funcia 0BH, INT 10H poate fi utilizat pentru a selecta o palet de culori i fundalul. O palet conine patru culori: trei culori (ex. gri, rou i maro) plus culoarea de fundal definit. Funciile modului grafic, dintre cele definite anterior, sunt urmtoarele: 04H citire poziie indicator optic, 08H citire caracter i atributele sale de pe ecran, din poziia curent a cursorului, 09H afiare atribute sau caracter pe ecran, la poziia cursorului, 0AH nlocuire caractere cu pstrarea culorii, 0BH fixare caracteristici de culoare, 0CH afiare punct pe ecran (pixel), 0DH citire culoare punct de pe ecran. Vom exemplifica utilizarea unora dintre aceste funcii prin urmtorul exemplu care traseaz pe un anumit fundal linii, n modul grafic, ntre anumite coordonate de pe ecran, dup care se restabilete modul de lucru iniial al terminalului grafic. ; dispvido.asm program care afiseaza direct in memoria video ; programul traseaza linii prin pixeli de diverse culori .model small .stack .code org 100h start proc near mov ah, 0fh ; citire si salvare mod video initial int 10h push ax call smod ; setare mod grafic call afisg ; afisare in modul grafic call citasta ; terminare mod grafic prin apasarea unei taste pop ax ; refacerea modului grafic initial ; mov ah,0 int 10h mov ax, 4c00h ; revenire DOS int 21h start endp

smod

smod afisg

proc mov mov int mov mov mov int ret endp proc mov mov mov mov mov int inc cmp jne mov inc inc cmp jne ret endp

near ah, 0 al, 10h 10h ah, 0bh bh, 0 bl, 01h 10h

; setarea modului grafic VGA 640 x 350

; caracteristici de culori ; culoare fundal: ; albastru

near bx, 0 dx, 70 cx, 140 ah, 0ch al, bl 10h cx cx, 500 iar cx, 140 bl dx dx, 280 iar

; afisare in modul grafic ; pagina initiala 0 ; linia pe care se incepe afisarea ; si coloana de inceput ; functia de afisare pixel ; culoarea de afisare ; registrele BX, CX si DX nu sunt modificate ; incrementare coloana de afisare ; limita coloanei ; daca s-a ajuns la limita, se reia ; modificare/incrementare culoare ; incrementare linie ; daca nu s-au parcurs toate liniile ; se reia afisarea

iar:

afisg citasta

mov int citasta end start

proc near ah, 10h 16h endp

; citirea unei taste

n modul grafic, organizarea informaiei n memoria ecran depinde de tipul adaptorului video i de modul de lucru grafic selectat. Astfel, pentru adaptorul VGA, modul 18 (640 x 480 pixeli, 16 culori simultan), memoria ecran este organizat n 4 plane. n fiecare plan, un bit corespunde unui pixel ecran. Pentru a obine valoarea unui pixel se adreseaz simultan cele 4 plane, cu aceeai adres. ntr-un plan de memorie, informaia este organizat astfel: biii din primul octet corespund primilor 8 pixeli din linia 0, cel de-al doilea octet corespunde urmtorilor 8 pixeli etc. Valoarea unui pixel, de 4 bii din memoria ecran, nu reprezint culoarea pixelului, ci un indice ntr-o tabel de culori, numit palet. Numrul de culori din palet determin numrul de culori ce pot fi afiate simultan pe ecran. Valoarea unui pixel fiind reprezentat pe 4 bii, paleta

are 24 (16) culori. O culoare se reprezint prin diferite valori ale componentelor de baz RGB (Red, Green, Blue). Adaptorul VGA pstreaz, pentru compatibilitate cu EGA, conceptul de palet cu 16 intrri, 6 bii/intrare. Dar intrarea n palet nu mai reprezint o culoare, ci un registru de culoare. Adaptorul VGA dispune n total de 256 de registre de culoare. Un registru de culoare conine o culoare reprezentat pe 18 bii cte 6 bii pentru fiecare component RGB. Culoarea reprezentndu-se pe 18 bii, adaptorul VGA poate genera maxim 218 (256k) culori distincte. n modul de lucru 19, memoria grafic nu mai este organizat n plane. Unui pixel i corespunde un octet n memoria ecran. Valoarea pixelului reprezint un registru de culoare din cele 256 ale adaptorului. n memoria ecran, ncepnd de la adresa segment 0A000h, primii 320 octei corespund liniei 0 de pixeli, urmtorii 320 octei corespund liniei 1 etc. Pentru adaptorul video VGA n modul grafic 19 (rezoluie 320x200, 256 culori simultan pe ecran), accesul la memoria ecran este mult mai simplu dect n modul 18. Offset-ul octetului ce conine valoarea unui pixel (x,y) este: offset = 80 x y + x Caracteristic acestui mod de lucru este numrul mare de culori ce pot fi afiate simultan pe ecran. Funcia INT 10h ofer un set de subfuncii referitoare la paleta i la registrele de culoare. Citirea, respectiv scrierea registrelor de culoare se poate realiza cu funciile: 10h modific (scrie) un registru culoare; date de intrare: BX = index registru culoare; DH, CH, CL = valori RGB (6 bii din fiecare registru, cei mai puin semnificativi). 12h modific (scrie) un set (bloc) de registre de culoare; date de intrare: BX = indexul primului registru culoare din set; CX = contor registre culoare din set ES:DX = adresa tabelei de culori, o culoare fiind reprezentat pe 3 octei (corespunztor componentelor RGB). 15h citete un registru culoare; date de intrare: BX = index registru culoare, date de ieire: DH, CH, CL = valorile RGB (6 bii din fiecare registru, cel mai puin semnificativi). 17h citete un set (bloc) de registre de culoare; date de intrare: BX = indexul primului registru culoare din set, CX = contor registre culoare din set, ES:DX = adresa tabelei de culori, o culoare fiind reprezentat pe 3 octei (corespunztor componentelor RGB), date de ieire: valorile din registrele culoare din set, pe care le nscrie n tabela de culori. Utilizarea discului, INT 13H Pe lng serviciile DOS oferite de funcia INT 21H, se mai poate utiliza i funcia BIOS INT 13H pentru a opera direct cu discul, cu toate c funciile BIOS nu ofer utilizarea automat a directoarelor sau blocarea, respectiv deblocarea nregistrrilor. Funcia INT 13H trateaz datele ca dimensiunea unui sector i manipuleaz adresarea discului folosind numerele efective ale pistei i sectorului. Operaiile INT 13H implic iniializarea, citirea, scrierea, verificarea i formatarea discului. Ele sunt destinate programatorilor cu experien care trebuie s fie ateni n utilizarea lor, precum i la faptul c pot fi diferene ntre diferite versiuni de BIOS. Operaiile furnizate de INT 13H, selectate de coninutul lui AH, sunt urmtoarele:

00H 01H 02H 03H 04H 05H 08H 09H 0AH 0BH

Iniializare unitate /disc sistem Citire stare unitate /disc Citire sectoare Scrie sectoare Verifica sectoare Formatare piste Citire parametrii unitate disc Iniializare unitate Citire buffer sector extins Scriere buffer sector extins

0CH 0DH 0EH 0FH 15H 16H 17H 18H 19H

Cutare cilindru Iniializare disc alternativ Citire buffer sector Scriere buffer sector Determinare tip disc Schimbare strii dischetei Iniializare tip dischet Iniializare tip media pt. format Parcare capete disc

Majoritatea operaiilor INT 13H pun pe 0 sau pe 1 indicatorul CF, dup cum operaia respectiv a reuit sau nu, i returneaz un cod de stare n registrul AH. BIOS pstreaz informaia n zona sa de date, pentru fiecare unitate de disc. Octetul de stare este prezentat n continuare i se poate gsi n zona de date BIOS, la adresa 40:41H pentru zona de date pentru dischet (Diskette Drive Data Area) i la adresa 40:74H pentru hard disc (Hard Disk Data Area). Codul 00H 01H 02H 03H 04H 05H 06H 07H 08H 09H 10H 20H 40H 80H AAH BBH CCH Starea Nu este eroare Comand eronat, nerecunoscut de controller Adresa sau discul nu s-au gsit ncercare de scriere pe un disc protejat Pist / sector invalid Operaie de iniializare euat Dischet scoas/ nlocuit de la ultimul acces Parametrii disc eronai Depire DMA ncercare de scriere/ citire DMA peste limita de 64K Eroare CRC la citire (indic date corupte) Eroare hardware, controller defect Eroare hardware, operaie cutare euat Dispozitivul nu rspunde (u unitate deschis, nu este dischet, sau pentru hard disk depire timp rspuns) Unitatea nu este pregtit Eroare nedefinit Eroare la scriere

Dac o operaie cu discul returneaz o eroare, aciunea obinuit a unui program este s iniializeze discul (funcia 00H) i s reia operaia respectiv de nc trei ori. Dac eroarea persist, programul poate afia un mesaj care s permit utilizatorului s schimbe discheta, dac aceasta este cauza. Operaiile de baz permise de funcia DOS INT 13H sunt urmtoarele:

Funcia 00H iniializare disc sistem: (DL) = unitatea de disc: 0-discul A, 80H-primul hard disc, 80H-al doilea hard etc. Se utilizeaz dup ce o operaie anterioar a semnalat o eroare sever; operaia realizeaz o reiniializare hard a controllerului de disc sau hard disc, adic la urmtorul acces se va iniializa operaia de la cilindrul 0. Dac operaia este reuit CF=0, n caz contrar va fi 1, iar AH va conine codul de stare. Funcia 01H citire stare disc: (DL) = unitatea de disc: 0-discul A, 80H-primul hard disc, 80H-al doilea hard etc. Operaia returneaz n AL codul de stare pentru ultima operaie cu discul (returnat n AH). Operaia valid va pune CF=0 i AH=00H. Funcia 02H citire sectoare disc: Operaia permite citirea unui numr specificat de sectoare de pe aceeai pist direct n memorie. Pentru aceasta, trebuie iniializate urmtoarele registre: (AL) = numrul de sectoare (pn la numrul maxim de sectoare de pe o pist); (CH) = numrul de cilindru/pist (ncep de la 0); (CL) = biii 7-6 conin numrul cilindru/pist (primii doi bii ai numrului, cei mai semnificativi), iar biii 5-0 conin numrul sectorului de start (ncep de la 1); (DH) = numrul cap/fa (0 sau 1 pentru dischet); (DL) = numrul unitii (precizat i anterior, 0-A, 80H-primul hard disc etc.) (ES:BX) = adresa unui buffer n zona de date, care trebuie s fie suficient de mare pentru toate sectoarele de citit. Dac operaia a reuit, CF=0 i se returneaz n AL numrul efectiv de sectoare citite, iar celelalte registre i pstreaz valorile. Dac apare o eroare, CF=1, iar AH va conine codul de stare. Funcia 03H scriere sectoare disc: Operaia scrie coninutul unei zone specificate de memorie de 512 octei sau multiplu de 512 octei n sectoarele specificate. Registrele utilizate pentru a specifica aceti parametri sunt aceleai ca la funcia 02H, iar starea de reuit a operaiei este semnalat asemntor. Funcia 04H verificare sectoare disc: Operaia permite verificarea unui numr specificat de sectoare, n sensul c se pot citi datele i se verific CRC (Cyclical Redundancy Check). Cnd se scrie pe disc, ntr -un sector controllerul de disc calculeaz i scrie o sum de control (CRC) imediat dup sectorul respectiv. Funcia 04H citete sectorul, recalculeaz suma de control i o compar cu suma scris. Verificarea const din recalcularea acestei sume i nu din compararea octeilor din sector cu aceia din memorie. Aceast operaie poate fi utilizat dup o scriere (funcia 03H) pentru a fi siguri de informaia scris, dei necesit un timp supliment ar de procesare. Parametrii se ncarc n registre exact ca la funcia 02H, dar nu este necesar adresa din ES:BX, ntruct nu se verific datele scrise n memorie. Starea de reuit este semnalat la fel ca la funcia 02H.

Funcia 05H formatare piste: Operaia permite formatarea pistelor, pentru a permite operaiilor de citire/scriere s localizeze i s proceseze un anumit sector. nainte de a folosi aceast operaie, trebuie utilizat funcia 17H pentru a stabili tipul dischetei i funcia 18H pentru a stabili tipul mediului. n vederea formatrii, trebuie iniializate urmtoarele registre: (AL) = numrul de sectoare de formatat; (CH) = numrul de cilindru/pist (ncep de la 0); (CL) = biii 7-6 conin numrul cilindru/pist (primii doi bii ai numrului, cei mai semnificativi), iar biii 5-0 conin numrul sectorului de start (ncep de la 1); (DH) = numr cap/fa (0 sau 1 pentru dischet); (DL) = numrul unitii (0-A, 80H-primul hard disc etc.); (ES:BX) = adresa ctre un grup de cmpuri de adres pentru o pist. Pentru fiecare sector de dischet pentru o pist, trebuie s se gseasc o intrare de 4 octei de forma T/H/S/B, unde semnificaia acestor octei este urmtoarea: T (0) numr cilindru/pist; H (1) numr cap/fa; S (2) numr sector; B (3) numr de octei/sector (00H=128, 01H=256, .., 03H=1024H) De exemplu, pentru a formata pista 03, capul 00, 512 octei/sector, prima intrare pentru pist este 03000102, urmat de o intrare pentru fiecare sector rmas. Dac operaia a reuit, CF=0, altfel CF=1, iar AH va conine codul de stare. Utilizarea tastaturii, INT 16H Tastatura conine un controller (8042) care scaneaz constant comutatoarele tastaturii (comandate de taste) pentru a determina dac este vreo tast apsat. Acest proces se desfoar n paralel cu activitile normale ale calculatorului, astfel nct s nu se piard nici o apsare de tast. Codul de scanare furnizat de tastatur este disponibil la portul 60H. Pentru tastatur exist, de fapt, dou proceduri: una pe nivelul 09H de ntreruperi, care trateaz semnalele venite de la tastatur, i una pe nivelul 16H, care poate fi folosit de utilizator pentru obinerea unui caracter de la tastatur. Prima procedur depune caracterele transmise de tastatur ntr-un buffer (de 16 caractere), n timp ce a doua procedur preia caractere din acest buffer. Bufferul este organizat circular, i conine pentru fiecare caracter transmis o pereche de octei (codul ASCII i codul de scanare numrul tastei care l-a furnizat); la depirea capacitii bufferului se emite un semnal sonor. Multe din codurile ASCII sunt caractere tipribile (litere, cifre, semne speciale etc.), dar din cele 256 de coduri, multe nu sunt reprezentate pe tastatur. Pentru a introduce astfel de coduri sau pentru a introduce un cod oarecare, se ine apsat tasta <Alt> i se tasteaz codul respectiv ca o valoare zecimal de la tastele numerice (n intervalul 0-255). Valoarea astfel tastat este memorat pe doi octei n bufferul tastaturii, primul este caracterul ASCII, iar cel de-al doilea este 0. Procedura pentru tratarea ntreruperilor de la tastatur realizeaz interpretarea i execuia unor comenzi corespunztoare i a unor combinaii de taste speciale: CTRL/ALT/DEL = reiniializare sistem; SHIFT/PRTSC = copiere la imprimant a caracterelor de pe ecran;

CTRL/NUM LOCK = oprirea execuiei unui program pn la apsarea altei taste; CTRL/SCROLL LOCK = ncheie execuia unui program; aici utilizatorul i poate defini propria sa rutin de tratare a ntreruperii (1BH). Tastatura furnizeaz trei tipuri de taste funcionale, de baz: 1. Caracterele standard (litere, cifre, caractere speciale care se afl pe tastatur). 2. Tastele pentru funciile extinse, care constau din: taste funcionale, precum F1 sau Shift + F1. tastele numerice din partea dreapt a tastaturii, cu tasta NumLock inactiv: <Home>, duplicatele lor de pe tastatur. <Alt> + liter i <Alt> + taste funcionale 3. Taste de control: <Alt>, <Ctrl>, <Shift>, care lucreaz n combinaie cu alte taste. BIOSul le trateaz n mod diferit fa de celelalte prin actualizarea strii lor curente (apsat sau nu) n octeii de stare ai tastelor de tip <Shift> n zona de date BIOS. Primele PC-uri aveau 83 de taste. Dintre acestea, cele numerice din partea dreapt pot realiza dou tipuri de funciuni. Ele pot reprezenta, pe lng numere, i tastele <Home>, <End>, tastele direcionale < , , , >, <Del>, <Ins>, <PgUp>, <PgDn>, selecia fiind realizat prin tasta <NumLock>. Ulterior, la tastaturile urmtoare, aceast problem a fost rezolvat prin proiectarea tastaturilor cu 101 i apoi cu 104 taste pentru Windows. Dintre tastele noi, doar F11 i F12 sunt funcii noi, restul meninnd funciile tastelor de la tastatura original. Bineneles c i BIOS-ul a fost modificat, pentru a putea interpreta i aceste noi taste. Starea tastelor de tip <Shift> Zona de date BIOS, aflat ncepnd de la adresa de segment 40H, conine i un prim octet cu starea tastelor de tip <Shift> (la adresa 40H: 17H) cu urmtoarea configuraie: 7 6 5 4 3 2 1 0 Insert Caps Num Scroll Alt Ctrl Left Right Lock Lock Lock Shift Shift Pentru citirea lor se folosete funcia 02H, int 16H; o tast activ (1) nseamn c utilizatorul ine apsat acea tast. Acesta este octetul pentru tastatura cu 83 de taste. Tastaturile mbuntite (cu 101 sau 104 taste), care au duplicate i pentru tastele <Ctrl> i <Alt> necesit informaie suplimentar pentru a le testa. Din acest motiv se utilizeaz un al doilea octet de stare la adresa 40:18H n care un bit 1 nseamn c sunt active urmtoarele taste: 7 6 5 4 3 2 1 0 Insert Caps Num Scroll Ctrl/ SysReq Left Left Lock Lock Lock Num Alt Ctrl Un alt octet de stare se afl la adresa 40:96H, care conine i alte informaii, din care bitul 4 specific dac este instalat o tastatur mbuntit. Bufferul tastaturii Transferul datelor ntre tastatur i programele utilizator se face printr-o zon de memorie tampon, denumit buffer. Zona de date BIOS conine la adresa 40:1EH o zon tampon (bufferul) pentru datele introduse de la tastatur. Aceasta permite introducerea pn la 15 caractere, nainte ca

programul s solicite intrarea. Pentru fiecare tast este asociat un cod unic de scanare, transmis la apsarea tastei (denumit cod make); la eliberarea tastei se mai transmite un cod obinut prin adunarea valorii 80H la codul de scanare, denumit cod break. La apsarea unei taste, se solicit n mod automat ntreruperea BIOS INT 09H. Aceasta ia codul scan de la tastatur, l convertete n cod ASCII i-l depune n bufferul tastaturii. Programul utilizator pentru citire din buffer va folosi INT 16H. Cnd se apas o tast, procesorul tastaturii genereaz codul scan i o cerere de ntrerupere, INT 09H, care lanseaz rutina asociat ntreruperii din BIOS. Aceasta citete de la portul de intrare 96 (in al, 60H) codul de scanare, pe care-l compar cu intrarea dintr-o tabel de coduri de scanare pentru a determina codul ASCII ataat caracterului, dac acesta exist. Rutina va furniza cele dou coduri pe doi octei (n registrul AX) n buffer-ul tastaturii. Procedeul acesta este prezentat n figura urmtoare. cod int 09H Tastatura cod scanare Rutina BIOS int 09H scanare Buffer caracter Rutina DOS int21H Rutina BIOS int16H

AX

cod scanare

cod ASCII

Valorile returnate n registrul AX de ntreruperi (BIOS sau DOS) se afl n ordine invers celei din bufferul tastaturii (n AH se gsete codul de scanare i n AL codul ASCII pentru tastele ce au asociate coduri, respectiv 0 pentru cele ce nu au un astfel de cod). ntreruperea INT 09H manipuleaz octeii de stare ai tastaturii (de la adresele 40:17H, 40:18H i 40:96H) pentru <Shift>, <Alt> i <Ctrl>, dar nu genereaz nici un caracter n buffer la apsarea acestor taste, ci doar actualizeaz biii corespunztori din octeii de stare. n cazul n care codul de scanare este generat de tastatur la apsarea unei taste, la eliberarea ei, ntr-un interval de 0,5 sec. se va genera un al doilea cod de scanare (care este primul cod +80H, adic se pune primul bit pe 1). Cel de-al doilea cod indic rutinei de ntrerupere c tasta a fost eliberat. Dac se ine apsat tasta mai mult de 0,5 s, atunci se repet automat operaia (tasta). Bufferul tastaturii pstreaz doi pointeri: unul la nceputul (capul) bufferului pentru a specifica ntreruperii INT 16H de unde se va citi (extrage) urmtorul caracter i unul la sfritul (coada) buffer-ului, pentru a preciza ntreruperii 09H unde se memoreaz urmtorul caracter tastat. Urmtoarele adrese descriu coninutul buffer-ului: 40:1AH adresa (indicatorul) de nceput buffer, urmtoarea poziie de unde int 16H citete un caracter; 40:1CH adresa de sfrit buffer, urmtoarea poziie unde int 09H poate memora caracterul introdus; 40:1EH adresa de nceput a bufferului nsui. El conine 32 de octei (16 caractere), dar

poate depi aceast dimensiune, i conine caracterele tastate i codurile lor de scanare. INT 16H va citi cte doi octei, fiecare caracter i codul su de scanare, i i furnizeaz programului. Acest buffer al tastaturii este unul circular, n sensul c indicatorul de sfrit este avansat de INT 16H. n acest fel, indicatorul de nceput urmrete continuu indicatorul de sfrit. Cnd cei doi indicatori se afl pe aceeai poziie, coada este goal (int 16H a citit toate caracterele). Cnd utilizatorul introduce 15 caractere, bufferul este plin i indicatorul de sfrit se gsete imediat n spatele celui de nceput. n acest moment, int 09H nu mai accept tastarea de noi caractere, bufferul accept numai 15 caractere, cel mult, dei poate conine 16. Structura acestui buffer poate fi descris astfel: BIOS_data segment at 40H ORG 17H stare_KBD ORG 1AH Buf_head Buf_tail Buf_KBD BIOS_data ends

db

dw ? ; pointer de extragere din buffer dw ? ; pointer de introducere in buffer dw 16 dup (?); bufferul tastaturii

Urmtorul program (.com) afieaz starea tastelor Shift, Ctrl i Alt. ; tastshft.asm programul afiseaza daca s-au tinut apasate tastele ; Shift, Ctrl si Alt BIOS_date segment at 40h org 17h stare_KBD db ? BIOS_date ends cod segment para assume cs: cod, es: BIOS_date org 100h start: mov ax, BIOS_date mov es,ax citire: mov ah, 10h ; citire caracter de la tastatura int 16h cmp al,0dh ; caracterul de sfarsit este tasta Enter je gata call test_Shift ; apel functie afisare stare taste Shift jmp citire gata: mov ax, 4c00h ; revenire DOS int 21h test_Shift proc near

push cs ; initializarea registrului segment DS pop ds ; cu adresa segmentului unde sunt mesajele mov bl, stare_KBD test bl, 01h ; test apasare tasta Shift dreapta jz test_Shift_stg lea dx, mes_Shift_dr call tip_mes test_Shift_stg: test bl, 02h ; test apasare tasta Shift stanga jz test_Ctrl lea dx, mes_Shift_stg call tip_mes test_Ctrl: test bl, 04h ; test apasare tasta Ctrl jz test_Alt mov bh, stare_KBD[1]; test Ctrl stanga sau dreapta test bh, 01h ; tasta Ctrl stanga jz Ctrl_dr lea dx, mes_Ctrl_stg call tip_mes jmp test_Alt Ctrl_dr: lea dx, mes_Ctrl_dr call tip_mes test_Alt: test bl, 08h ; test apasare tasta Alt jz gata_test mov bh, stare_KBD[1 ; test Alt stanga sau dreapta test bh, 02h ; tasta Alt stanga jz Alt_dr lea dx, mes_Alt_stg call tip_mes jmp gata_test Alt_dr: lea dx, mes_Alt_dr call tip_mes gata_test: ret test_Shift endp tip_mes proc near mov ah,09h int 21h ret tip_mes endp

; tiparire mesaj de la adresa data in DX

; mesajele de tiparit mes_Shift_dr mes_Shift_stg mes_Alt_dr mes_Alt_stg mes_Ctrl_dr mes_Ctrl_stg cod ends end

db db db db db db

S-a apasat tasta Shift dreapta.,0dh, 0ah, $ S-a apasat tasta Shift stanga.,0dh, 0ah, $ S-a apasat tasta Alt dreapta.,0dh, 0ah, $ S-a apasat tasta Alt stanga.,0dh, 0ah, $ S-a apasat tasta Ctrl dreapta.,0dh, 0ah, $ S-a apasat tasta Ctrl stanga.,0dh, 0ah, $

Pentru utilizarea tastaturii se pot apela urmtoarele funcii, selectate de valoarea din registrul AH: Funcia 0 citire caracter: (AH) = codul de scanare al caracterului; (AL) = codul ASCII al caracterului; Funcia accept tastele corespunztoare tastaturilor cu 83 de taste, dar nu i tastele corespunztoare tastaturilor mbuntite (<F11> i <F12>); pentru acestea, se poate utiliza funcia 10H. Funcia 1 test caracter disponibil: Funcia verific dac exist un caracter disponibil n buffer, dar nu i pentru tastele corespunztoare tastaturilor mbuntite (<F11> i <F12>); pentru acestea, se poate utiliza funcia 11H. Caracterul rmne n buffer pn cnd este citit (cu una din funciile 00h sau 10h) (ZF) = 0, dac exist caracter disponibil n buffer; = 1, dac nu exist caracter n buffer. (AX) = cei doi octei corespunztori caracterului (codul de scanare i codul ASCII); Funcia 2 citire stare taste de tip shift:
(AL) = octetul care codific starea acestor taste, memorat la adresa 40:17H.

Funcia 3 iniializarea ratei pentru autorepetare: Registrul BH conine intervalul de timp de ateptare nainte de nceperea operaiei de autorepetare a tastei ce este inut apsat. Registrul BL va conine rata de repetare, adic numrul de repetri ale tastei respective, ntr-o secund. (BH) = 0, 1, 2, 3 pentru 1/4, 1/2, 3/4 sau 1 secund ntrziere pn la repetare; (BL) = 0-1Fh pentru 30 repetri/s pn la 2 repetri/s. Funcia 5 scriere n bufferul tastaturii: Funcia permite programelor utilizator s insereze caractere n bufferul tastaturii dac utilizatorul a apsat o tast. Se va ncrca codul ASCII n CH i codul su de scanare n CL. Operaia permite introducerea de caractere pn la umplerea bufferului. Funcia 10H citire caracter (inclusiv tastele duplicate de la tastatura mbuntit):

(AH) = codul de scanare al caracterului; (AL) = codul ASCII al caracterului; pentru tastele funciilor extinse (<Home>, <F1>) returneaz 00H, iar pentru tastele extinse de control (duplicatele de la tastatura mbuntit) returneaz E0H.

Funcia accept toate tastele corespunztoare att tastaturilor cu 83 de taste, ct i tastaturilor mbuntite (duplicatele <Home>, <PgUp>, dar i cele noi <F11> i <F12>). Funcia 11H test caracter disponibil: Funcia verific dac exist un caracter disponibil n buffer, dar, spre deosebire de funcia 01H, aceast funcie verific pentru toate tastele corespunztoare oricrui tip de tastatur, adic i pentru tastaturile mbuntite. Utilizarea ei este similar, n rest, cu aceea a funciei 01H. Funcia 12H citire stare taste de tip shift (pentru tastaturile mbuntite): (AL) = octetul care codific starea acestor taste, dup cum urmeaz: 7 SysReq 6 Caps Lock 5 Num Lock 4 Scroll Lock 3 Right Alt 2 Right Ctrl 1 Left Alt 0 Left Ctrl

Utilizarea ceasului de timp real, INT 1AH Pentru ceasul de timp real, BIOS-ul conine dou proceduri: una pentru tratarea ntreruperilor provenite de la acesta i alta disponibil utilizatorului, pentru controlul ceasului de timp real. Prima procedur pentru tratarea ntreruperilor de la ceasul de timp real este apelat de aproximativ 18,21 ori pe secund. La fiecare apel, se incrementeaz un contor format din 4 octei (de la adresa 40:6CH), ce reprezint ora sistemului. La fiecare apel al acestei proceduri, dup actualizarea contorului se va invoca ntreruperea software INT 1CH. Aceasta este procedura pe care o poate defini utilizatorul; dac el nu a definit-o, aceasta va conine doar instruciunea IRET, i deci nu se va realiza nici o prelucrare. Pentru utilizarea ceasului de timp real se pot selecta urmtoarele funcii: Funcia 0 citire contor, pentru ceasul de timp real: (CX) = partea cea mai semnificativ a contorului; (DX) = partea cea mai puin semnificativ a contorului; (AL) = indicator de depire a 24 ore (este 0 dac nu a trecut de ora 24) Valoarea de 32 de bii din CX:DX reprezint numrul de perioade de 55 milisecunde care au trecut de la miezul nopii. Funcia 1 iniializare contor, pentru ceasul de timp real: (CX) = cei mai semnificativi doi octei pentru contor; (DX) = cei mai puin semnificativi doi octei pentru contor

Funcia permite iniializarea ceasului de timp real la valoarea coninut n CX:DX, ca numr de perioade de timp de 55 milisecunde scurse de la miezul nopii. Celelalte funcii, 02H-07H, manipuleaz ora i data pentru serviciile de ceas n timp real.

Utilizarea funciilor DOS


n timp ce BIOS-ul permite manipularea dispozitivelor la nivel cobort, DOS-ul furnizeaz o interfa de nivel ridicat pentru multe dispozitive. De exemplu, una dintre rutinele BIOS permite accesul la unitatea de dischet. Cu aceast rutin se pot citi sau scrie blocuri pe dischet. Din pcate, BIOS-ul nu cunoate mecanismele legate de fiiere i directoare, ci opereaz doar la nivel de blocuri (sectoare). Dac se dorete o operaie pe disc, utiliznd BIOS ul, trebuie tiut exact locul de pe disc (sectorul) unde se afl fiierul. Pe de alt parte, utiliznd DOS-ul se poate opera cu nume de fiiere, n locul adreselor de pe disc. DOS-ul pstreaz informaii asupra localizrii fiierului pe disc i apeleaz rutina ROM-BIOS pentru citirea/scrierea blocurilor respective. Interfaa de nivel ridicat reduce efortul programatorului necesar pentru accesul la date. Utilizarea funciilor DOS este, n general, mai uoar dect cea a funciilor BIOS echivalente, primele fiind mult mai independente de main. ntreruperile de la 20H pn la 3FH sunt rezervate pentru operaii DOS, dup cum urmeaz: INT 20H = terminare program; operaia termin execuia unui program .com, reface adresele pentru CTRL+Break i pentru erorile critice, golete bufferele i red controlul sistemului DOS. INT 21H = solicitare funcie DOS, al crei cod este transmis n AH i este descris n detaliu n continuare. INT 22H = adresa de terminare. Se copiaz adresa acestei ntreruperi n PSP -ul programului (la offset 0AH) cnd programul ncrctor ncarc un program pentru execuie. La terminarea programului, operaia transfer controlul la adresa ntreruperii. INT 23H = adresa pentru CTRL+Break. Este destinat pentru transferul controlului la o rutin DOS (prin PSP, offset 0EH) cnd se tasteaz CTRL+Break sau CTRL+C. Rutina termin execuia unui program sau a unui fiier batch. Un program poate nlocui aceast adres cu aceea a unei rutine proprii, pentru a realiza aciuni specifice fr terminarea programului. INT 24H = manipulare erori critice. Este utilizat de sistem pentru a transfera controlul (prin PSP, offset 12H) cnd este recunoscut o eroare critic (de obicei la o operaie cu discul sau cu imprimanta). Aceste ultime trei ntreruperi, n mod normal, nu ar trebui s fie apelate de programul utilizator. INT 25H = citire absolut de pe disc a unuia sau mai multor sectoare (este nlocuit de INT 21H, funcia 440DH, codul minor 61H). INT 26H = scriere absolut pe disc, din memorie, a unuia sau mai multor sectoare (este nlocuit de INT 21H, funcia 440DH, codul minor 41H). INT 27H = programul se termin, dar rmne rezident. Determin ca un program .COM, dup terminare, s rmn rezident n memorie (nlocuit de INT 21H, funcia 31H). INT 2FH = ntrerupere multiplexare. Aceasta implic o comunicaie ntre programe, cum ar fi comunicarea strii unei imprimante, prezena unui driver de disc, sau comenzi sistem cum ar fi ASSIGN sau APPEND. INT 33H = manipulare mouse, deci furnizeaz serviciile pentru manipulare mouse.

Vom prezenta cteva funcii DOS, INT 21H, mai des utilizate: Funcia 0 terminare execuie program: xor ah, ah int 21h Funcia 1 citire caracter de la tastatur, cu ecou: mov ah, 1 int 21h ; (AL) = codul ASCII al caracterului citit sau 0 daca este o ; tasta functionala, cum ar <Home>, <F1> sau <PgUp> Funcia 2 afiare caracter: mov dl, cod_ASCII_caracter mov ah, 2 int 21h Funciile 3 i 4 intrare sau ieire la un port de comunicare: Cele dou funcii permit citirea (n AL), respectiv scrierea (din DL) a unui caracter la un port, dar este preferat operaia BIOS INT 14H. Funcia 5 scrie caracter la LPT: mov dl, caracter mov ah, 5 int 21h Funcia 6 intrare/ieire direct la consol: Aceast funcie poate transfera orice caracter sau cod de control fr interferen cu DOS-ul. Sunt dou versiuni, una pentru intrare i alta pentru ieire. Pentru intrare se ncarc 0FFH n DL. Dac nu exist un caracter n bufferul tastaturii, operaia pune ZF=1 i nu ateapt intrarea. Dac exist un caracter, acesta este memorat n AL i ZF=0. Operaia este fr ecou i nu verific eventualele combinaii <Ctrl>+<Break> sau <Ctrl>+PrtSc. Dac AL este diferit de 0, este codul ASCII al unui caracter, dac ns este 0, atunci este o tast cu funcie extins (cum ar fi <Home>, <F1> sau <PgUp>) Pentru ieire, caracterul se ncarc n DL (ns nu 0FFh) mov dl, caracter ; sau 0FFh pentru iesire mov ah, 6 int 21h ; pentru iesire se testeaza ZF, dupa care se ia valoarea din AL, daca ZF=0. Funcia 7 citire de la tastatur, fr ecou i fr interpretare break (<Ctrl> + <Break>): mov ah, 7 int 21h ; (AL) = codul ASCII al caracterului citit Funcia 8 citire de la tastatur, fr ecou: mov ah, 8 int 21h ; (AL) = codul ASCII al caracterului citit

Funcia 9 afiarea unui ir de caractere, ce se termin cu $: lea mov int dx, sir ah, 9 21h ; (DS:DX)=adresa de inceput a sirului de caractere

Funcia 0Ah citire ir de caractere: Aceast funcie accept date de la tastatur, dar necesit o list de parametri. Primul care trebuie cunoscut este numrul maxim de caractere (date) de intrare care nu mai poate fi introdus, valoare la apariia creia se anun sonor utilizatorul. Un al doilea parametru, actualizat de funcie, va conine numrul de caractere efectiv introduse. Lista de parametri const din urmtoarele elemente: 1. Prima intrare furnizeaz numele listei de parametri, n forma LABEL BYTE. 2. Primul octet din list conine limita maxim a numrului de caractere de intrare (ntre 0 i 255). 3. Al doilea octet este rezervat pentru memorarea numrului efectiv de caractere tastate. 4. n continuare, este rezervat memorie pentru memorarea caracterelor. n concluzie, o astfel de list poate fi definit astfel: param_list label dim_max dim_efectiv dat byte db db db

50 ; dimensiunea spatiului de memorie alocat ? ; numarul efectiv de caractere citite 50 dup (?); aici se depun caracterele

Apelul funciei se realizeaz astfel: lea mov int dx, param_list ah, 0Ah 21h ; (DS:DX) = adresa listei descrisa anterior

irul de caractere tastat se va termina cu tasta <Enter>, al crei cod nu este numrat, dar este transferat n zona de date. n cazul n care contorul numrului de caractere n momentul apsrii tastei <Enter> este mai mic dect limita numrului maxim de caractere, va fi depus n list ca al doilea octet (parametru). Dac se tasteaz mai multe caractere dect limita maxim stabilit, vor fi memorate doar primele caractere tastate care, alturi de codul tastei <Enter>, 0Dh, se ncadreaz n zona de memorie rezervat (deci mai puin cu unul dect numrul maxim de caractere specificat n lista de parametri). n acest capitol este prezentat un exemplu de utilizare a acestei funcii; programul citaftxt.asm citete un text de maximum 30 de caractere i l afieaz pe centrul ecranului, program care se execut ciclic pn la citirea unui text vid. Funcia 0Bh determinare stare tastatur: mov int ah, 0Bh 21h ; daca (AL) = 0FFH, atunci exista un caracter in buffer

; daca (AL) = 00H, atunci nu exista nici un caracter ; in buffer Funcia 0Ch terge bufferul tastaturii i invoc funcia din AL: mov mov mov int ah, 0Ch ; aceasta operatie poate fi utilizata in asociere cu al, nr_functie ; functiile: 01h, 06h, 07h, 08h sau 0Ah dx, mem_KBD; zona de citire date 21h

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

45. Setul de instruciuni: instruciuni de transfer, aritmetice, de prelucrare la nivel de bit.

Setul de instruciuni
Din motive descriptive, setul de instruciuni de la procesorul 286 este mprit n trei subseturi distincte: setul instruciunilor de baz; setul extins de instruciuni; setul de instruciuni de control sistem. Setul de instruciuni de baz Aceste instruciuni sunt grupate n ase tipuri, i anume: transfer date; aritmetice; operare pe bit (logice, deplasare, rotire); operare pe iruri; transfer control program; control procesor. Aproape fiecare instruciune poate opera fie pe octet, fie pe cuvnt (sau dublu cuvnt, la 386/486). Operanzii instruciunilor pot fi interschimbabili, cu excepia datelor imediate care pot fi numai surs, nu i destinaie. Variabilele din memorie pot fi operate direct n memorie, fr s fie mutate n registre. Setul de instruciuni poate fi considerat ca avnd dou niveluri: nivel de asamblare i nivel main. Pentru programatorul n limbaj de asamblare, procesorul apare ca avnd circa o sut de instruciuni. O instruciune n limbaj de asamblare (de ex. MOV) corespunde, de fapt, la mai multe forme de instruciuni main (pt. MOV sunt circa 30 de tipuri, n funcie de tipul operandului: octet/cuvnt, registru/memorie, dat imediat etc.). La nivel main exist circa trei sute de instruciuni. Instruciunile nivelului de asamblare simplific viziunea programatorului asupra setului de instruciuni: programatorul scrie instruciunea (de ex. INC, de incrementare a unui operand 8/16 bii, registru sau locaie de memorie), asamblorul examineaz operandul i determin instruciunea nivel main ce trebuie generat. Instruciuni de transfer date La rndul lor, aceste instruciuni sunt mprite n patru clase: instruciuni de transfer cu scop general (clasice); instruciuni specifice acumulatorului; instruciuni de transfer adrese obiect; instruciuni de transfer registru indicatori. Aceste instruciuni nu modific indicatorii de condiii, dect cu unele excepii care vor fi menionate corespunztor. Instruciuni de transfer cu scop general MOV <dest>,<sursa> Transfer un octet/cuvnt (sau dublu cuvnt) de la surs la destinaie, fr a modifica nici un indicator din registrul respectiv. n funcie de surs i destinaie, poate avea formele:

MOV MOV MOV

<reg>,<reg> <reg_16>,<reg_seg> <reg_seg>,<reg_16>

Exemple de instruciuni: mov ax,bx mov al,ch mov ax,cs mov ds,ax Registrul segment (reg_seg) CS nu poate fi destinaie i nici nu se pot transfera date direct ntre dou registre segment. MOV <reg>,<mem> MOV <mem>,<reg> Exemple de instruciuni: mov vector[bx][si],ax ; vector este de tip word mov sp,varf_stiva mov bl,byte ptr vector[bp][di] Nu se pot transfera date direct ntre dou locaii de memorie. MOV MOV Exemple: mov mov ds,adr_baza_seg [bx].salv_seg,cs <reg_seg>,<mem_16> <mem_16>,<reg_seg>

Realizeaz transferul ntre o locaie de memorie de 16 bii i un registru segment; CS nu poate fi destinaie. MOV MOV Exemple: mov mov mov mov ax,0 cl,4 byte ptr [si],2ch alfa[bp][si],100 <reg>,<data_imed> <mem>,<data_imed>

Aceast instruciune nu se poate executa utiliznd registrele segment.

Instruciuni de conversie (extensie de semn) Aceste instruciuni realizeaz extensia de semn a acumulatorului (AL, AX, EAX) n extensia sa (AH, DX sau EAX, EDX). Nu se modific nici un indicator. Aceste instruciuni pot fi folosite pentru a furniza un demprit de lungime dubl nainte de a efectua o mprire cu semn. CBW (Convert Byte to Word)

Realizeaz extensia de semn a lui AL n registrul AH. CWDE (Convert Word to Double word Extended)

Realizeaz extensia de semn a lui AX n registrul EAX. CWD (Convert Word to Double word)

Realizeaz extensia de semn a lui AX n registrul DX. CDQ (Convert Double word to Quad word)

Realizeaz extensia de semn a lui EAX n registrul EDX. La 386/486 mai exist instruciunile de transfer cu extensia bitului de semn sau cu extensie de zerouri: MOVSX <dest>,<sursa> (MOVe with Sign eXtension)

Realizeaz transferul operandului surs la destinaie, cu extensia bitului de semn, n octeii superiori. Destinaia poate fi un registru de 16/32 bii, iar sursa poate fi un registru sau o locaie de memorie de 8/16 bii. Deci, se poate face transferul cu extensia bitului de semn a unui:
octet la un cuvnt sau dublu cuvnt:

MOVSX MOVSX
cuvnt la un dublu cuvnt:

reg_16,reg/mem_8 reg_32,reg/mem_8

MOVSX

reg_32,reg/mem_16

Nu este afectat nici un indicator. MOVZX <dest>,<sursa> (MOVe with Zero eXtension)

Transfer sursa (8/16 bii) la o destinaie (16/32 bii) i extinde cu zerouri, la stnga, n octeii superiori, pentru a completa destinaia la dimensiunea sa. Deci se poate face transferul cu extensia de zerouri a unui:

octet la un cuvnt sau dublu cuvnt:

MOVZX MOVZX
cuvnt la un dublu cuvnt:

reg_16,reg/mem_8 reg_32,reg/mem_8

MOVZX

reg_32,reg/mem_16

Nu este afectat nici un indicator. Instruciuni de interschimbare a datelor XCHG <dest>,<sursa> (eXCHanGe)

Instruciunea schimb, ntre ele, coninuturile celor doi operanzi, astfel nct fiecare dintre ei este att surs, ct i destinaie. Instruciunea poate fi de forma: XCHG XCHG XCHG <reg>,<reg> <reg>,<mem> <mem>,<reg>

dar nu poate opera cu registre segment. Instruciuni de transfer cu stiva Stiva este organizat pe cuvinte, iar la 386/486 ea poate fi referit pe dublu cuvnt. Stiva este folosit pentru
salvarea/refacerea adresei de revenire pentru apel, respectiv revenire din apel de procedur sau pentru ntreruperi, respectiv revenire din ntreruperi, cnd se salveaz/reface pe lng adresa de revenire a programului ntrerupt i registrul indicatori; administrarea stivei pentru astfel de operaii este realizat, n mod automat, de ctre procesor; salvarea/refacerea coninutului unor resurse (registre, memorie etc.) la intrarea ntr-o procedur, respectiv la ieirea din aceasta; pentru transferul parametrilor de intrare/ieire ntre o procedur i programul apelant, precum i pentru alocarea dinamic de memorie (adic pe durata execuiei programului) pentru variabilele locale unei proceduri.

PUSH <sursa>

depune in varful stivei <sursa>. (SP) (SP) 2 ((SP)+1:(SP)) (sursa)

Operandul surs poate fi un registru general sau o locaie de memorie de 16 bii, respectiv un registru segment. Exemple:

push push push

si cs beta[bx][si]

ncepnd cu procesorul 80386, instruciunea PUSH (E)SP depune n stiv valoarea registrului (E)SP, aa cum era aceasta naintea execuiei instruciunii (deci fr a fi decrementat). Aceasta difer de procesoarele anterioare (8086/186/286), unde instruciunea PUSH SP depune n stiv noua valoare a registrului SP (decrementat cu 2). POP <dest> extrage din varful stivei si duce la dest. (dest) ((SP)+1:(SP)) (SP) (SP) + 2

Exemple: pop bx pop ds ; cs nu poate fi destinatie pop beta[bp][di] ncrcarea registrului CS prin intermediul stivei se poate face numai la execuia unei instruciuni de revenire dintr-o procedur, n context far, sau la revenirea dintr-o ntrerupere. Informaiile din stiv vor fi extrase n ordinea invers celei n care au fost introduse: ; salvam registrele: ax, bx, cx push ax push bx push cx ; refacem aceleasi registre cu aceleasi valori: pop cx pop bx pop ax Accesul la informaia din stiv se poate face fr descrcarea stivei, utiliznd adresarea bazat astfel: ; memorare informatii in stiva: mov bp,sp ; memorare varful stivei push ax ; se va depune la adresa [bp-2] push bx ; [bp-4] push cx ; [bp-6] ; accesul la informatii se poate face, cu BP, in orice ordine mov ax,[bp-2] mov bx,[bp-4] mov cx,[bp-6] ; descarcarea stivei se poate face modificand valoarea lui SP add sp,6

Dac dorim s nu modificm valoarea lui BP, va trebui s-l salvm i pe acesta n stiv, ceea ce se ntmpl n mod frecvent astfel: ; depunerea de parametri in stiva, inainte de apelul procedurii: push ax push bx push cx ; preluarea parametrilor din stiva, in cadrul procedurii: ; (s-a facut abstractie, in acest exemplu, de salvarea din stiva ; a adresei de revenire si de parametrii transmisi prin stiva) push bp mov bp,sp mov ax,[bp+6] mov bx,[bp+4] mov cx,[bp+2] ; descarcarea stivei si refacerea registrului BP salvat: pop bp add sp,6 Instruciuni de transfer specifice acumulatorului Aceste instruciuni permit transferul de date ntre registrul acumulator (AL, AX sau EAX) i portul de I/O din spaiul de I/O, specificat ca operand. Specificarea portului se poate face direct n instruciune, pe 8 bii, iar pentru adrese mai mari se folosete adresarea indirect prin DX. IN Exemple: in in in in in in al,port_oct ax,port_cuv eax,port_dcuv al,dx ax,dx eax,dx out out out out out out port_oct,al port_cuv,ax port_dcuv,eax dx,al dx,ax dx,eax <acc>,<port> OUT <port>,<acc>

Toate operaiile de intrare/ieire, indiferent de perifericul utilizat, presupun folosirea acestor instruciuni pentru a realiza transferul informaiei. n principiu, fiecrui periferic i sunt asociate porturi pentru: citirea strii dispozitivului; transmiterea comenzii ctre periferic; realizarea transferului propriu-zis. Se pot realiza i transferuri de I/O pe iruri (blocuri): INS <dest>,DX OUTS DX,<sursa>

(INput from port to String ; OUTput String to port) Aceste instruciuni transfer date la sau de la un port de I/O specificat de DX de la surs sau la destinaie. Operandul de memorie, dac este surs, este referit de DS:(E)SI, iar dac este destinaie este referit de ES:(E)DI; selecia ntre registrele de 16 sau 32 de bii (ESI sau SI, respectiv EDI sau DI) se execut n funcie de atributul de dimensiune de adres. Dup realizarea transferului unui element, registrele index sunt automat actualizate, pentru a face referire la urmtoarea adres; dac direcia de parcurgere DF=0, atunci vor fi incrementate, iar dac DF=1, vor fi decrementate. Pasul de actualizare va fi 1, 2 sau 4, dup cum se citete/scrie un octet, cuvnt sau dublu cuvnt. De fapt, n funcie de tipul transferului (octet, cuvnt sau dublu cuvnt), se vor genera instruciunile corespunztoare: INSB / INSW / INSD OUTSB / OUTSW / OUTSD

Aceste instruciuni pot fi precedate de prefixul de repetare REP, pentru a realiza transferuri pe blocuri de date. Dimensiunea blocului de date de transferat se va ncrca n registrul (E)CX, care va contoriza numrul de octei, cuvinte sau cuvinte duble transferate. Efectul acestui prefix este descris ulterior, la paragraful pentru instruciunile pe iruri. XLAT instructiune de transfer dintr-o tabela de octeti sau de transfer de octet, de la un cod la altul: (AL) ((BX) + (AL))

Coninutul acumulatorului este nlocuit de un octet dintr-o tabel. Adresa de nceput a tabelei se afl, n prealabil, n BX. Coninutul registrului AL este considerat ca adres relativ n aceast tabel de conversie (translaie). Valoarea corespunztoare din tabel (de tip octet) este mutat n AL. Referirea la o adres n instruciunea XLAT, este necesar pentru a permite asamblorului s determine registrul segment care va fi utilizat la execuia instruciunii (registrul BX conine numai adresa relativ n cadrul segmentului din care face parte tabela de conversie): XLAT [adr_tabela], XLAT [[rs:] adr_tabela] sau XLATB

Ultima form poate fi utilizat fr operand, dac tabela se afl deja n segmentul curent referit de DS. Instruciuni de transfer adrese LEA <dest_reg>,<sursa_mem> (Load Effective Address)

Transfer n registrul destinaie de 16 bii specificat de instruciune adresa relativ, n segment, a operandului surs, care trebuie s fie un operand din memorie. Registrul destinaie nu poate fi un registru segment. Aceast instruciune poate fi folosit pentru ncrcarea registrelor BX, SI sau DI, care trebuie s conin adrese de operanzi pentru instruciunea XLAT i pentru instruciunile pe iruri. De exemplu instruciunea: lea bx, adr_tab

este echivalent cu: mov bx, offset adr_tab

dar instruciunea: lea si, adr_tab[bx][di]

nu are un echivalent direct, care s utilizeze o singur instruciune, ci o secven de instruciuni: mov add add si, offset adr_tab si, bx si, di

La procesoarele 386/486 destinaia i/sau sursa pot fi i de 32 bii. Dac destinaia i sursa au aceeai dimensiune (16 sau 32 bii) efectul este cel descris anterior. Pot aprea, ns, situaiile:
LEA <reg_16>,<mem_32>, se vor ncrca n registrul destinaie de 16 bii numai ultimii 16 bii ai sursei de 32 de bii din memorie; LEA <reg_32>,<mem_16>, se va face extensia de semn a sursei de 16 bii, din memorie, la dimensiunea registrului destinaie, de 32 de bii. LDS <dest_reg_16>,<sursa_mem_32> (Load pointer using DS) LES <dest_reg_16>,<sursa_mem_32> (Load pointer using ES)

Instruciuni de transfer indicatori LAHF (AH) (Load AH from Flags) (SF, ZF, *, AF, *, PF, *, CF)

Copiaz n AH indicatorii SF, ZF, AF, PF, CF, n formatul n care acetia se gsesc n registrul indicatori (biii 70). Aceast instruciune a aprut la 8086, pentru a asigura compatibilitatea cu procesorul anterior 8080. Nu modific nici un indicator. SAHF (Store AH into Flags) (SF, ZF, *, AF, *, PF, *, CF) (AH)

Transfer biii corespunztori din AH n registrul indicatori (biii 70). Modific doar aceti indicatori; ceilali nu sunt modificai. PUSHF (PUSH Flags) (SP) (SP) 2 ((SP)+1:(SP)) Indicatori (flags)

Transfer indicatorii n cuvntul din noul vrf al stivei. La 386/486, instruciunea PUSHFD pune n stiv registrul indicatori de 32 de bii (EFLAGS). Indicatorii nu sunt modificai. POPF Indicatori ((SP)+1:(SP)) (SP) (SP) + 2 Transfer cuvntul din vrful stivei (la care face referire SP) n registrul indicatori, modificndu-le valorile anterioare. n mod asemntor, la 386 exist instruciunea POPFD, care transfer din vrful stivei un cuvnt dublu n registrul EFLAGS. Instruciuni aritmetice Formatul datelor aritmetice Operaiile aritmetice pot fi efectuate pe patru tipuri de numere: binare: fr semn; cu semn; zecimale: nempachetate; mpachetate; (ambele fr semn). Numerele binare pot fi de 8 sau 16 bii, iar la 386 i de 32 de bii. Numerele zecimale sunt memorate n octei: dou cifre pe un octet, la formatul zecimal mpachetat; o cifr pe un octet, la formatul zecimal nempachetat (prima tetrad conine zero, iar cea de-a doua conine o cifr de la 0 la 9). Procesorul consider, ntotdeauna, c operanzii specificai n instruciunile aritmetice conin date ce reprezint numere valide pentru tipul instruciunii ce trebuie executat. Date incorecte vor conduce la rezultate neprevzute. Numerele binare fr semn se pot gsi n intervalele: [0..255], cele de tip octet, [0..65535], cele de tip cuvnt, i [0..232-1], cele de tip cuvnt dublu. Pentru aceste date sunt definite instruciunile de adunare, scdere, nmulire i mprire. Numerele binare cu semn sunt reprezentate n cod complementar (complement fa de 2) i pot avea valorile: [-128..+127], cele de tip octet, [-32268..+32267], cele de tip cuvnt, i [-231+231-1], cele de tip dublu cuvnt. Sunt definite operaiile de nmulire i mprire, specifice acestui tip de date, iar operaiile de adunare i scdere sunt realizate cu instruciunile pentru numere binare fr semn. Dac pentru numere fr semn depirea este detectat de indicatorul CF, pentru numere cu semn aceasta este detectat de indicatorul OF. Pentru determinarea depirii, n astfel de cazuri se pot utiliza instruciunile de salt condiionat, pentru CF sau OF, dup operaia respectiv.

Numerele n format zecimal nempachetat pot reprezenta valori n intervalul 09, pe un octet fr semn. Operaiile aritmetice cu numere n format zecimal nempachetat se realizeaz n dou etape. Operaiile de adunare, scdere i nmulire, de la numere binare fr semn, furnizeaz un rezultat intermediar n AL, care apoi este ajustat la o valoare corect, de numr n format zecimal nempachetat. mprirea se face n mod asemntor, cu excepia ajustrii care este realizat prima, asupra operandului numrtor, n registrul AL, i apoi se realizeaz mprirea binar fr semn; dac rezultatul nu este corect, mai poate urma o a treia etap de ajustare final. Reprezentarea n format zecimal nempachetat este asemntoare cu aceea a caracterelor numerice 09 n codul ASCII, cu diferena c tetrada mai semnificativ din codul ASCII are valoarea 3H, n loc de 0H. Din acest motiv, formatul zecimal nempachetat mai este denumit format ASCII. Se pot realiza operaii direct pe caracterele numerice ASCII, astfel: se pune pe 0 prima tetrad a numrului ASCII; se efectueaz operaia respectiv i corecia necesar, care las aceast tetrad pe 0H; se pune prima tetrad a numrului pe 3H i se obine direct codul ASCII al cifrei respective. Numerele n format zecimal mpachetat sunt memorate fr semn ntr-un octet care conine cte o cifr zecimal n fiecare jumtate de octet (tetrad sau patru bii). Prima cifr este cea mai semnificativ, i ntruct fiecare tetrad poate conine o cifr de la 0 la 9, rezult c valoarea unui astfel de numr este cuprins n intervalul 099. Operaiile de adunare i scdere se realizeaz n dou etape, la fel ca la numerele n format zecimal nempachetat: se utilizeaz instruciunea binar fr semn respectiv (+, -), care va furniza un rezultat intermediar n AL; se realizeaz corecia rezultatului din AL la o valoare corect n format zecimal mpachetat. Nu exist instruciuni de ajustare pentru operaiile de nmulire sau mprire cu astfel de numere. Dup o astfel de instruciune, indicatorii pot fi: modificai, conform rezultatului; nemodificai, deci vor rmne la valoarea avut anterior acestei instruciuni; nedefinii, adic sunt modificai de instruciunea respectiv, dar nu reflect starea rezultatului. Instruciunile de adunare/scdere ADD <dest>,<sursa> (ADDition) (dest) (dest) + (sursa) Modifica: OF, SF, ZF, AF, PF, CF (ADdition with Carry flag) (dest) (dest) + (sursa) + (CF) Modifica: OF, SF, ZF, AF, PF, CF (INCrement) (dest) (dest) + 1 Modifica: OF, SF, ZF, AF, PF Nu afecteaza: CF ; (ASCII Adjust for Addition)

ADC <dest>,<sursa>

INC <dest>

AAA

nlocuiete coninutul registrul AL, obinut prin adunarea a dou numere n format zecimal

nempachetat, cu un numr n format zecimal nempachetat corect, astfel: if ((AL) & 0FH) > 9 or (AF)=1 then (AL) (AL) + 6; (AH) (AH) + 1; (AF) 1 (CF) 1 (AL) (AL) & 0FH else (CF) 0 (AF) 0 Modifica: AF, CF; Nedefiniti: OF, SF, ZF, PF. Simbolul &, utilizat n descrierea instruciunilor, reprezint operaia I logic la nivel de bit. Corecia aceasta este necesar deoarece procesorul efectueaz calculele n binar, iar un transport de la bitul 3 la bitul 4 nseamn de fapt modificarea valorii de la 8 la 16, valoare interpretat de utilizator ca fiind 10, deoarece numrul este citit n zecimal; din acest motiv, trebuie s se adune valoarea 6, pentru a obine valoarea zecimal corect. DAA (Decimal Adjust for Addition)

nlocuiete coninutul registrului AL, obinut prin adunarea a dou numere n format zecimal mpachetat, cu un numr zecimal mpachetat, astfel: if ((AL) & 0FH) > 9 or (AF)=1 then (AL) (AL) + 6; (AF) 1 else (AF) 0; if ((AL) > 9FH) or (CF)=1 then (AL) (AL) + 60H; (CF) 1 else (CF) 0; Modifica: SF, ZF, AF, PF, CF Nedefinit: OF. Se realizeaz o corecie asemntoare ca la instruciunea precedent, cu deosebirea c aceast corecie se face pentru ambele tetrade, ntruct numrul este zecimal mpachetat. ncepnd de la procesorul 486 i urmtoarele, se mai poate executa i instruciunea: XADD <dest>,<sursa> (eXchange and ADD)

care schimb sursa cu destinaia, asemntor instruciunii XCHG, dar realizeaz i suma celor doi operanzi, ca la instruciunea ADD; deci, practic, combin cele dou instruciuni ntr-

una singur astfel: adun sursa cu destinaia i depune suma la destinaie, dar copiaz i valoarea iniial a destinaiei, pe care o depune la surs. Operandul destinaie poate fi reg/mem, iar cel surs reg. SUB <dest>,<sursa> (SUBtraction) (dest) (dest) (sursa) Modifica: OF, SF, ZF, AF, PF, CF SBB <dest>,<sursa> (SuBtraction with Borrow) (dest) (dest) (sursa) (CF) Modifica: OF, SF, ZF, AF, PF, CF DEC <dest> (DECrement) (dest) (dest) 1 Modifica: OF, SF, ZF, AF, PF Nu afecteaza: CF ; NEG <dest> determin complementul fa de doi al operandului destinaie i-l returneaz destinaiei: (dest) compl2 (dest) { (dest) 0 (dest) } Modifica: OF, SF, ZF, AF, PF, CF Dac operandul este zero, el rmne neschimbat i CF=0. Pentru toate celelalte numere CF=1. Dac se complementeaz cel mai mic numr negativ (de ex. -128 sau -32268), operandul nu se va modifica, dar OF=1. CMP <dest>,<sursa> poziioneaz toi indicatorii pentru operaia: (dest) (sursa) fr ns a modifica operandul destinaie i nici pe cel surs. De obicei, dup o astfel de instruciune urmeaz o instruciune de salt condiionat. CMPXCHG <dest>,<sursa> (CoMPare and eXCHanGe)

Operandul destinaie poate fi reg/mem, iar cel surs reg. Instruciunea este disponibil ncepnd de la procesorul 486. Spre deosebire de instruciunea cmp, instruciunea cmpxchg modific doar indicatorul ZF. Instruciunea utilizeaz, de asemenea, registrul acumulator, alegnd n mod automat, n funcie de dimensiunea operanzilor, unul din registrele al, ax sau eax. Instruciunea compar acumulatorul cu primul operand i actualizeaz ZF. Dac acumulatorul este egal cu primul operand, ZF=1 i copiaz cel de-al doilea operand n primul. n caz contrar, ZF=0 i se copiaz primul operand n acumulator. Procesoarele Pentium permit compararea i interschimbarea pe 64 de bii cu ajutorul instruciunii cmpxchg8b, care are sintaxa:

cmpbxchg8b ax, mem_64 Instruciunea compar valoarea din memorie de 64 de bii la care face referire mem_64 cu valoarea de 64 de bii din edx:eax. n cazul n care cele dou valori sunt egale, se memoreaz valoarea din edx:eax n memorie la mem_64 i se seteaz ZF=1, altfel se ncarc perechea de registre (edx:eax) cu valoarea din memorie (mem_64) i ZF=0. AAS (ASCII Adjust for Subtraction)

nlocuiete coninutul registrului AL, obinut prin scderea a dou numere n format zecimal nempachetat, cu un numr corect n format zecimal nempachetat, astfel: if ((AL) & 0FH) > 9 or (AF)=1 then (AL) (AL) 6; (AH) (AH) 1; (AF) 1 (CF) 1 (AL) (AL) & 0FH else (CF) 0 (AF) 0 Modifica: AF, CF; Nedefiniti: OF, SF, ZF, PF. Corecia aceasta este necesar deoarece procesorul efectueaz calculele n binar i un mprumut de la bitul 4 la bitul 3 nseamn de fapt un mprumut de valoare 16, dar aceast valoare este considerat de utilizator ca fiind 10, deoarece numrul este interpretat n zecimal; din acest motiv trebuie s se scad valoarea 6, pentru a corespunde valorii zecimale reale. DAS (Decimal Adjust for Subtraction)

nlocuiete coninutul registrului AL, obinut prin scderea a dou numere n format zecimal mpachetat, cu un numr n format zecimal mpachetat, astfel: if ((AL) & 0FH) > 9 or (AF)=1 then (AL) (AL) 6; (AF) 1 else (AF) 0; if ((AL) > 9FH) or (CF)=1 then (AL) (AL) 60H; (CF) 1 else (CF) 0; Modifica: SF, ZF, AF, PF, CF

Nedefinit: OF. Exemple de utilizare a acestor instruciuni: 1) Programul adun dou numere fr semn, reprezentate pe mai multe cuvinte (octei), iar rezultatul se va depune peste primul numr. add_data numar_1 lung_nr1 numar_2 add_data multibyte_add start: segment dw 0a8adh, 7fe2h, 0a876h,0 equ ($ numar_1)/2 dw 0cdefh, 52deh, 378ah, 0 ends segment assume cs: multibyte_add, ds: add_data ax,add_data ; initializarea reg. DS ds,ax ; cu adresa de segment cx,lung_nr1 ; contor lungime numar si,0 ; initializare index elemente ; (CF)=0, transportul initial ax,numar_2[si] numar_1[si],ax si ; actualizare index element si bucla ax,4c00h ; revenire in DOS 21h

mov mov mov mov clc bucla: mov adc inc inc loop mov int multibyte_add ends end start 2) Complementarea unui numr reprezentat pe mai multe cuvinte.

Se pornete chiar de la definiia complementului fa de 2: complement fa de 2 pentru numr = 2n numr; unde numar este reprezentat pe n-1 bii. mov clc mov compl: inc inc mov sbb mov loop cx,lung_numar ; contor numar cuvinte ; initializare transport cu 0 ; initializare index ; actualizare index cuvant prim/ urmator

si, -2 si si ax,0 ; echivalentul lui 2n, se face scaderea ax,numar [si] ; cu propagarea imprumutului si ; pozitionare OF/ depasire, la ultimul numar[si],ax ; cuvant, se depune rezultatul, si se compl ; pastreaza ultimul OF ; testare depasire (OF), ce are loc doar pentru ; valoarea minima negativa (80.00... 00h)

Dac numrul iniial are valoarea minim negativ (80 00 ...00H), dup complementare valoarea va fi aceeai, deci rmne nemodificat, ca i n cazul instruciunii de complementare (NEG). Instruciunile de nmulire/mprire MUL <sursa> ; MUL <acumulator>,<sursa> la 386/486

Realizeaz nmulirea fr semn a operandului surs cu acumulatorul (AL, AX sau EAX). Dac sursa este de tip octet atunci este nmulit cu registrul AL i rezultatul de lungime dubl este returnat n AX. Dac operandul surs este de tip cuvnt, atunci este nmulit cu registrul AX, iar rezultatul este returnat n perechea de registre (DX, AX). Dac sursa este de 32 bii, atunci: (sursa_32) (EAX) (EDX, EAX). Operanzii sunt considerai fr semn. Dac jumtatea superioar a rezultatului (AH, DX sau EDX n funcie de tipul operanzilor) este diferit de zero, ceea ce nseamn depirea formatului iniial al numerelor, atunci OF=CF=1; n caz contrar, OF=CF=0. Deci, dac dup nmulirea numerelor rezult OF=CF=1, atunci jumtatea superioar a rezultatului (AH, DX sau EDX) conine cifre semnificative ale rezultatului (depete dimensiunea iniial a operanzilor). Ceilali indicatori sunt nedefinii (SF, ZF, AF, PF). Exemplu de nmulire a unui octet cu un cuvnt: mov mov mul al,op1_octet ah,0 op2_cuv ; inmultitorul de tip octet ; se extinde inmultitorul la cuvant, fara semn ; se realizeaza inmultirea

IMUL <sursa> ; IMUL <acumulator>,<sursa> la 386/486 Realizeaz nmulirea cu semn a operandului surs cu acumulatorul (AL, AX sau EAX) i depune rezultatul de lungime dubl n AX (DX, AX) sau (EDX, EAX), n funcie de tipul sursei. Operaia se realizeaz n mod asemntor ca la nmulirea fr semn. Dac jumtatea superioar a rezultatului (AH, DX, EDX) nu reprezint extensia de semn a jumtii inferioare (AL, AX, EAX), atunci OF=CF=1; n caz contrar, OF=CF=0. Deci, dac dup nmulirea numerelor se obine OF=CF=1, atunci jumtatea superioar a rezultatului conine cifre semnificative ale rezultatului (depete dimensiunea iniial a operanzilor). La 386/486, pe lng aceste instruciuni se pot realiza nmuliri care pot avea ca destinaie i alte registre, nu numai cele prestabilite (AX, DX:AX sau EDX:EAX). Acestea pot avea doi sau trei operanzi: IMUL r_16, r/m_16 IMUL r_32, r/m_32 IMUL r_16, data_8 IMUL r_32, data_8 IMUL r_16, data_16 IMUL r_32, data_32 IMUL r_16, r/m_16, data_8 IMUL r_32, r/m_32, data_8 IMUL r_16, r/m_16, data_16 IMUL r_32, r/m_32, data_32

Instruciunile cu doi operanzi au ca operand destinaie un registru general de 16/32 bii, iar operandul surs poate fi un registru, un operand din memorie, o dat imediat de 8 bii sau o dat imediat, de aceeai dimensiune cu registrul destinaie.

Instruciunile cu trei operanzi au ca operand destinaie un registru general de 16/32 bii i doi operanzi surs: unul este un registru sau operand memorie, de aceeai dimensiune cu destinaia, iar cel de-al doilea poate fi o dat imediat de 8 bii sau de aceeai dimensiune cu ceilali doi operanzi. Pentru aceste instruciuni, care au ca destinaie un alt registru general dect acumulatorul, rezultatul este trunchiat la dimensiunea registrului destinaie. Dac rezultatul nu depete dimensiunea destinaiei, deci nu este necesar trunchierea lui la dimensiunea destinaiei, atunci OF=CF=0; n caz contrar, OF=CF=1. Deci, practic, indiferent de tipul nmulirii i de numrul de operanzi, dac apare o depire a dimensiunii iniiale a destinaiei cei doi indicatori vor fi poziionai pe 1. Exemplu de nmulire cu semn a unui octet cu un cuvnt: mov al,op1_octet cbw extinde semnul inmultitorului la cuvant imul op2_cuv AAM ; inmultitorul de tip octet ; ; se realizeaza inmultirea (Ascii Adjust for Multiply) (AH) (AL)/0AH (AL) (AL) mod 0AH Modifica: SF, ZF, PF; Nedefiniti: OF, AF, CF Corecteaz rezultatul unei nmuliri anterioare a doi operanzi zecimali nempachetai. n urma nmulirii, utiliznd instruciunea MUL, a doi operanzi de tip zecimal mpachetat, se obine produsul n (AH,AL), unde (AH) = 0, iar (AL) <> 0. Pentru ca rezultatul returnat de aceast instruciune s fie corect trebuie ca (AL) < 100, condiie care este ndeplinit dac valoarea sa se obine prin nmulirea a dou numere de tip zecimal nempachetat (valoarea maxim este 9, deci 99 =81< 100). DIV < sursa > sau DIV < acc >,< sursa > la 386. temp) (numarator) if (temp) / (numitor) > MAX then (cat), (rest) nedefiniti (SP) (SP) 2; intrerupere ((SP)+1:(SP)) indicatori; pe (tf), (if) 0; nivelul (SP) (SP) 2; 0 ((SP)+1:(SP)) (CS); (CS) (2) (SP) (SP) 2; ((SP)+1:(SP)) (IP); (IP) (0) else (cat) (temp) / (numitor) (rest) (temp) mod (numitor) se

MAX = FFH/octet, FFFFH/cuvant, FFFFFFFFH/dublu cuvant. Indicatori: toi sunt nedefinii. Aceast instruciune realizeaz mprirea ntreag, fr semn, a acumulatorului (AL, AX, EAX) i a extensiei sale (AH, DX, EDX) prin operandul surs. Operandul demprit este de lungime dubl (AX, DX:AX, EDX:EAX) fa de operandul mpritor (octet, cuvnt sau dublu cuvnt). n cazul n care ctul depete capacitatea destinaiei (>MAX) sau la mprirea prin zero se genereaz ntrerupere pe nivelul 0. n urma mpririi ntregi, restul i ctul se obin n funcie de tipul operanzilor, astfel: rest AH DX EDX IDIV < sursa > ct AL AX EAX sau tip mprire pentru mprire la octet pentru mprire la cuvnt pentru mprire la dublu cuvnt IDIV < acc >,< sursa > la 386/486.

Aceast instruciune realizeaz mprirea ntreag, cu semn, a acumulatorului (AL, AX, EAX) i a extensiei sale (AH, DX, EDX) prin operandul surs. Operandul demprit este de lungime dubl (AX, DX:AX, EDX:EAX) fa de operandul mpritor (octet, cuvnt sau dublu cuvnt). n cazul n care ctul depete capacitatea destinaiei (este mai mare dect MAX sau mai mic dect -MAX-1) sau la mprirea prin zero se genereaz ntrerupere pe nivelul 0, ntocmai ca la mprirea fr semn. Constanta MAX are valorile 7FH, 7FFFH i 7FFFFFFFH pentru cturi pozitive de tip octet, cuvnt i dublu cuvnt, respectiv 80H, 8000H, 80000000H pentru cturi negative de tip octet, cuvnt i dublu cuvnt. La fel ca la mprirea fr semn, la mprirea ntreag toi indicatorii sunt nedefinii, iar restul i ctul mpririi se obin n aceleai perechi de registre (AH,AL ; DX,AX ; EDX,EAX). n rest, descrierea instruciunii IDIV este aceeai ca la mprirea fr semn (DIV), doar cu modificarea corespunztoare a liniei: if (temp) / (numitor) > MAX or (temp) / (numitor) > -MAX 1 then .............................. AAD (ASCII Adjust for Division) (AL) (AH) * 0AH + (AL) (AH) 0 Indicatori: modific SF, ZF, PF, iar ceilali sunt nedefinii: OF, CF, AF. Modific numrtorul din AL naintea mpririi a doi operanzi coreci de tip zecimal nempachetat, astfel nct dempritul s reprezinte corect valoarea respectiv n binar, deoarece instruciunea realizeaz mprirea n binar. AH trebuie s fie zero pentru urmtoarea instruciune DIV, n vederea furnizrii unui rezultat corect. Ctul, n urma operaiei de mprire, este returnat n AL, iar restul n AH. Pentru a transforma rezultatul ntr-un numr corect de tip zecimal nempachetat (ASCII), n cazul n care ctul este mai mare de 9, trebuie utilizat, dup mprire, instruciunea de corecie AAM, bineneles dup ce s-a salvat restul din AH.

Instruciuni de prelucrare la nivel de bit n setul de instruciuni exist trei grupuri de instruciuni pentru manipularea biilor, pentru date de tip octet, cuvnt sau dublu cuvnt, i anume: instruciuni logice (NOT, AND, OR, XOR, TEST etc.); instruciuni de deplasare (SHL, SAL, SHR, SAR etc.); instruciuni de rotire (ROL, ROR, RCL, RCR); Toate aceste operaii se efectueaz bit cu bit. Instruciuni logice Aceste instruciuni modific indicatorii astfel: OF i CF 0; AF nedefinit; SF, ZF, PF sunt poziionai conform rezultatului instruciunii respective i pot fi testai de instruciunile de salt condiionat. Excepie: instruciunea NOT nu modific nici un indicator. NOT <dest> Inverseaz toi biii operandului surs (complement fa de 1). Nu afecteaz nici un indicator. AND <dest>, <sursa> (dest) OR <dest>, <sursa> (dest) XOR <dest>, <sursa> (dest) TEST <dest>, <sursa>

(dest) and (sursa) (dest) or (sursa) (dest) xor (sursa)

Poziioneaz indicatorii pentru operaia (dest) and (sursa), fr a modifica nici un operand. Dac instruciunea TEST este urmat de o instruciune de salt JNZ, saltul va avea loc dac exist cel puin doi bii egali cu 1 pe aceleai poziii n cei doi operanzi ai instruciunii. Operanzii pot fi ntocmai ca la instruciunile de transfer, adic reg/mem pentru destinaie i reg/mem sau dat pentru surs. Tot n aceast categorie pot fi incluse i instruciunile, specifice procesoarelor 386/486, de testare / modificare de bit, cele de scanare pe bit, precum i instruciunile de setare condiionat.

Instruciuni de testare i modificare a unui bit Aceste instruciuni opereaz pe un singur bit, specificat n instruciune prin deplasamentul su (n cel de-al doilea operand, care poate fi o dat de 8 bii sau un registru de 16/32 bii) fa de bitul cel mai puin semnificativ al operandului destinaie (registru sau locaie de memorie de 16/32 bii). Bitul respectiv este transferat n CF i apoi modificat conform instruciunii respective (ceilali indicatori rmn nemodificai). BT <dest>, <pozitie> (Bit Test) (CF) Bit (dest, pozitie) BTS <dest>, <pozitie> (Bit Test and Set) (CF) Bit (dest, pozitie), Bit (dest, pozitie) 1 BTR <dest>, <pozitie> (Bit Test and Reset) (CF) Bit (dest, pozitie), Bit (dest, pozitie) 0 BTC <dest>, <pozitie> (Bit Test and Complement) (CF) Bit (dest, pozitie), Bit (dest, pozitie) Not (Bit (dest, pozitie)) Instruciuni de scanare pe bit Aceste instruciuni permit scanarea direct a biilor din cel de-al doilea operand (de tip cuvnt sau dublu cuvnt), ncepnd cu bitul mai puin semnificativ (forward) sau invers, ncepnd cu bitul cel mai semnificativ (reverse), pentru a determina primul bit egal cu 1. Dac toi biii sunt zero, atunci ZF=1; n caz contrar ZF=0, i registrul destinaie va reine indexul primului bit 1 din operandul surs (registru sau memorie de aceeai dimensiune cu registrul destinaie). Se modific numai indicatorul ZF. scanare direct: BSF
scanare invers:

<dest>, <sursa>

(Bit Scan Forward)

BSR

<dest>, <sursa>

(Bit Scan Reverse)

Instruciuni de setare condiionat Instruciunile din aceast categorie permit poziionarea unui octet pe zero sau unu, n funcie de una din cele 16 condiii definite de indicatori. Operandul destinaie, de tip octet, poate fi un registru sau o locaie de memorie. Aceste instruciuni sunt folosite pentru implementarea expresiilor booleene din limbajele de nivel nalt. Forma general a instruciunii este: SETcond if else (dest) 0 <dest> cond (dest) then 1 (SET byte on condition)

Aceste instruciuni nu modific nici un indicator. Cele 16 instruciuni referitoare la condiiile respective sunt urmtoarele: SETE / SETZ SETNE / SETNZ SETL / SETNGE SETLE / SETNG SETNL / SETGE SETNLE / SETG SETB / SETNAE / SETC SETBE / SETNA SETNB / SETAE / SETNC SETNBE / SETA SETO / SETNO SETP / SETPE SETNP / SETPO SETS / SETNS Condiia ZF = 1 Condiia ZF = 0 Condiia SF <> OF, valori cu semn Cond. SF <> OF sau ZF = 1, valori cu semn Condiia SF = OF, valori cu semn Cond. SF = OF i ZF = 0, valori cu semn Cond. CF = 1, valori fr semn Cond. CF = 1 sau ZF = 1,fr semn Cond. CF = 0, valori fr semn Cond. CF = 0 i ZF = 0,fr semn Cond. OF = 1 / respectiv OF = 0 Cond. PF = 1, adic paritate par Cond. PF = 0, adic paritate impar Cond. SF = 1 / respectiv SF = 0

Instruciuni de deplasare Deplasrile pot fi aritmetice sau logice. Se poate deplasa operandul destinaie cu pn la 31 de bii, corespunztor operandului contor codificat n instruciune (sunt luai n considerare numai ultimii 5 bii ai acestuia). Contorul poate fi specificat ca o constant imediat n instruciune, dac are valoarea 1, sau ca registrul CL, dac este diferit de 1; n acest fel, contorul de deplasri poate fi o variabil furnizat n momentul execuiei. ncepnd de la procesoarele 286 (386/486/Pentium) contorul, chiar dac este diferit de 1, poate fi specificat n instruciune ca dat imediat. Deplasrile aritmetice pot fi utilizate pentru a nmuli sau mpri numere binare prin puteri ale lui 2. Deplasrile logice pot fi utilizate pentru a izola bii n octei sau cuvinte. Indicatorii sunt modificai astfel: OF = este nedefinit ntr-o deplasare pe mai muli bii; = este poziionat corespunztor, dac se efectueaz o deplasare de un bit (1 dac se modific bitul de semn n urma deplasrii, altfel este 0); CF = ultimul bit deplasat n afara operandului destinaie; AF = nedefinit; SF, ZF, PF = modificai conform rezultatului. SHL / SAL <dest>, <contor> (SHift logical Left / Shift Arithmetic Left)

Poziiile eliberate din dreapta operandului se completeaz cu zerouri, indiferent de tipul deplasrii; deci, ntre cele dou mnemonici nu exist nici o deosebire. Bitul cel mai semnificativ se deplaseaz n CF. n cazul n care contorul de deplasri este 1 i dac dup deplasarea aritmetic (SAL), (CF) <> primul bit al rezultatului, deci s-a schimbat semnul rezultatului, atunci (OF) = 1 (depire domeniu de reprezentare); n caz contrar, (OF) = 0. Exemple:

shl sal mov sal shl SHR

ah, 1 ; deplasari de 1 bit, care va ajunge beta[bx][di], 1 ; in CF cl, 5 ; deplasari de mai multi biti, de ex. 5 dx, cl ; ultimul bit deplasat este in CF beta[bp][si], cl (SHift logical Right)

<dest>, <contor>

Fiind o deplasare logic, poziiile eliberate prin deplasare din stnga se vor completa cu zerouri. Bitul cel mai puin semnificativ se va deplasa n CF. La o deplasare de 1 bit, dac se modific bitul de semn atunci (OF)=1; n caz contrar (OF)=0. SAR <dest>, <contor> (Shift Arithmetic Right)

Bitul cel mai semnificativ i pstreaz vechea valoare, dar este i deplasat spre dreapta (extensie de semn), ceea ce nseamn c nu poate s apar depire (schimbarea de semn a rezultatului) i (OF)=0 la o deplasare de 1 bit. Bitul cel mai puin semnificativ se va deplasa n CF. Trebuie menionat c SAR nu furnizeaz acelai rezultat ca instruciunea IDIV pentru aceeai operanzi, dac dempritul este negativ, i bii egali cu 1 sunt deplasai (SAR) n afara operandului. De exemplu, -5 deplasat la dreapta (SAR) cu un bit va furniza rezultatul -3, n timp ce mprirea ntreag (IDIV) va furniza valoarea -2: (-5) = (11111011) (11111101) = (-3) Diferena dintre cele dou instruciuni este c IDIV trunchiaz toate cturile ctre zero, n timp ce SAR trunchiaz numerele pozitive ctre zero, iar pe cele negative ctre infinit negativ. La 386/486 pot fi realizate instruciuni de deplasare dubl, pe cuvnt sau dublu cuvnt, furniznd din doi operanzi de intrare (cuvnt sau dublu cuvnt) un rezultat de ieire de aceeai lungime (cuvnt sau dublu cuvnt). Operandul destinaie poate fi registru sau memorie, iar sursa poate fi un registru general. Rezultatul nlocuiete operandul destinaie, iar contorul numrului de bii deplasai este specificat de registrul CL sau ca o valoare imediat de 8 bii; el poate avea valoarea maxim 31 (deci este considerat modulo 32). Indicatorii sunt poziionai la fel ca la deplasrile multibit. Aceste instruciuni furnizeaz operaiile de baz necesare pentru implementarea operaiilor de deplasare pe iruri lungi de bii (64 sau mai mult) nealiniai. SHLD CF <dest>, <sursa>, <contor> (SHift Left Double) Destinaie Surs

SHRD Destinaie Surs

<dest>, <sursa>, <contor> (SHift Right Double) CF

De notat c registrul surs nu se modific, deci el rmne la valoarea avut anterior deplasrii; poziiile eliberate, pe durata deplasrii, prin deplasarea biilor se vor pune pe zero. Instruciunea este util atunci cnd se mpacheteaz date din mai multe surse diferite. Instruciuni de rotire n cazul rotaiilor, biii deplasai n afara operandului nu sunt pierdui, ca n cazul deplasrilor, ci sunt rotii napoi ctre cellalt capt al operandului. Numrul de rotiri este dat de un contor care poate fi constanta 1 sau registrul CL, dac numrul de rotiri este diferit de 1. Ca i la deplasri contorul din CL este interpretat modulo 32, adic sunt luai n considerare ultimii 5 bii ai acestuia. ncepnd de la procesoarele 286 (deci i la urmtoarele: contorul, chiar dac este diferit de 1, poate fi specificat n instruciune ca dat imediat. Indicatorul CF poate aciona ca o extensie a operandului, la dou dintre instruciunile de rotire, permind unui bit s fie izolat n CF i apoi testat de instruciuni JC sau JNC. Rotaiile modific numai CF i OF: CF = ultimul bit rotit n afara operandului; OF = nedefinit pentru rotaii multibit; = 1 sau 0, pentru rotaie doar de 1 bit, dup cum s-a modificat sau nu bitul de semn al operandului. ROL CF <dest>, <contor> Bn (ROtate Left) B0

ROR CF

<dest>, <contor> Bn

(ROtate Right) B0

RCL CF

<dest>, <contor> Bn

(Rotate through Carry Left) B0

RCR CF

<dest>, <contor> Bn

(ROtate through Carry Right) B0

Exemple utiliznd aceste instruciuni: 5) Tiprirea coninutului registrului DX, n format octal: tip_car proc far ; procedura afiseaza caracterul al carui cod ASCII ; il primeste in registrul AL push dx ; se salveaza registrul de lucru DX mov dl, al ; se apeleaza functia 2 din DOS care mov ah, 2 ; afiseaza caracterul al carui cod int 21h ; ASCII se transmite in registrul DL pop dx ; se reface registrul salvat ret tip_car endp tip_octal proc far ; tipareste in octal valoarea fara semn transmisa in DX push cx ; se salveaza registrele de lucru push ax ; prima cifra de afisat este doar de 1 bit rol dx, 1 ; care este rotit pe ultimul bit mov al, dl ; si dusa in registrul AL and al, 1 ; se sterg ceilalti biti add al, 30h ; este convertita la codul ASCII call tip_car ; si se afiseaza ; urmatoarele 5 cifre sunt de cate 3 biti mov cx, 5 ; contor numar de cifre de afisat octal1: push cx ; se salveaza contorul in stiva mov cl, 3 ; contor numar de rotiri la stanga rol dx, cl ; cifra este rotita pe ultimii 3 biti mov al, dl ; si adusa in AL and al, 7 ; sunt stersi ceilalti biti add al, 30h ; si convertita la codul ASCII call tip_car ; afisarea cifrei pop cx ; se citeste valoarea contorului de cifre loop octal1 pop ax refac registrele salvate in stiva pop cx ret tip_octal endp

se

6) mpachetarea unor date din mai multe surse diferite utiliznd instruciunea de deplasar e pe dublu cuvnt shld. De exemplu, s asamblm ntr-un singur cuvnt 4 tetrade diferite, aflate

n memorie la locaii succesive (ncepnd de la adresa tetrada) aliniate la stnga n cuvintele respective i memorate ncepnd cu tetrada cea mai semnificativ. mov mov reia_depl: mov shld inc loop si, 0 cx, 4 ax[si] bx, ax, 4 si reia_depl ; index tetrada ; contor numar de tetrade, de asamblat in cuvant ; tetrada si ; deplasare tetrada in BX ; actualizare index ; in final in BX se va afla cuvantul asamblat ; (cele 4 tetrade)

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

46. Operare pe iruri, de transfer al controlului programului, de control procesor i de sistem.

Instruciuni de operare pe iruri


Exist cinci operaii de baz ce opereaz pe iruride lungime de pn la un segment (64K la 286, respectiv 4G la 386/486), i permit: mutare, comparare de iruri, scanarea unui ir pentru o valoare i transfer la/de la acumulator. Aceste operaii de baz pot fi precedate de un prefix special de un octet care are ca efect repetarea instruciunii prin hardware. Repetiia se poate termina printr-o varietate de condiii, iar o operaie repetat poate fi ntrerupt sau suspendat. O instruciune pe ir poate avea un operand surs, un operand destinaie sau pe amndoi. irul surs este n (DS) sau ntr-un alt segment, dac este prefixat peste aceast presupunere. irul destinaie se afl, ntotdeauna, n segmentul dat de registrul (ES). SI este ca offset pentru elementului curent al irului surs, iar DI este offset pentru irul destinaie. Instruciunile pe ir actualizeaz automat SI i/sau DI. DF determin dac registrele index sunt auto-incrementate-decrementate (DF=0-1), iar pas de actualizare depinde de tipul irurilor: 1 - octet, 2 - cuvnt, 4 - dublu cuvnt. Dac este prezent un prefix de repetare reg. CX este decrementat la fiecare repetiie a instruciunii pe ir; repetarea va lua sfrit cnd CX=0, sau pentru unele prefixe i n funcie de ZF. Sunt cinci mnemonici pentru dou forme de prefix octet, care controleaz repetarea unei instruciuni pe ir(uri). Prefixele de repetare nu afecteaz indicatorii. REP / REPE / REPZ / REPNE / REPNZ REP - REPeat - este utilizat mpreun cu MOVS- STOS, "repet ct timp nu este sfritul irului, adic (CX<>0)"; REPE / REPZ - REPeat while Equal / Zero - care opereaz la fel i au fizic acelai prefix octet ca REP. Sunt utilizate pentru CMPS i SCAS, i necesit, n plus fa de condiia anterioar, ca ZF s fie setat nainte de efectuarea urmtoarei repetiii; REPNE / REPNZ - REPeat while Not Equal / Zero - este asemntor cu cele anterioare, cu deosebirea c ZF trebuie pus pe 0, sau repetiia se termin. MOVS <sir_dest>, <sir_sursa> (MOVe data from String to string) MOVSB / MOVSW / MOVSD Se transfer un element (octet/cuvnt/dublu cuvnt) de la surs (SI) la destinaie (DI), i actualizeaz SI/DI Utilizat mpreun cu prefixul REP realizeaz un transfer de bloc memorie-memorie. CMPS <sir_dest>, <sir_sursa> (COMPare String operands) CMPSB / CMPSW / CMPSD Aceast instruciune scade operandul destinaie (referit de DI) din cel surs (referit de SI), modific indicatorii de stare, dar nu altereaz nici unul dintre operanzi, dup care actualizeaz SI/DI. Trebuie reinut c spre deosebire de instr. CMP care scade sursa din destinaie, CMPS realizeaz scderea invers: surs - destinaie.

Dac CMPS are prefixul REPE sau REPZ operaia este interpretat "compar ct timp nu este sfrit irul (CX<>0) i irurile sunt egale (ZF=1)"; determina prima pereche de elemente diferite. Dac CMPS este precedat de REPNE/REPNZ "compar ct timp nu este sfrit de ir (CX<>0), i elementele irurilor nu sunt egale (ZF=0)"; determina prima pereche de elemente egale. SCAS <sir_dest> (SCAn String data) SCASB / SCASW / SCASD Instruciunea scade elem. ir dest. (octet/ cuvnt/ dublu cuvnt) adresat de DI, din AL, AX sau EAX, i actualizeaz indicatorii, dar fr a modifica irul destinaie sau acumulatorul. Dac SCAS este prefixat de REPE/REPZ "scaneaz ct timp nu este sfritul irului (CX<>0) i valoarea scanat este egal cu elementele irului (ZF=1)"; determina abaterea fa de o valoare. Dac SCAS este prefixat de REPNE/REPNZ "scaneaz ct timp nu este sfritul irului (CX<>0) i valoarea scanat este diferit de elementele irului (ZF=0)"; localizeaz o valoare ntr-un ir. LODS <sir_sursa> (LOaD String operand) LODSB / LODSW / LODSD Transfer elementul irului surs adresat de SI, n AL, AX sau EAX, i actualizeaz SI. Instruciunea se utilizeaz n bucle soft. STOS <sir_dest> (STOre String data) STOSB / STOSW / STOSD Transfer un element din acumulator (AL, AX, EAX) n irul destinaie, i actualizeaz DI, pentru a referi urmtorul element. Instruciunea poate fi precedat de prefixul REP, i astfel se poate iniializa un ir cu o constant. 1) Copierea unui ir de octei dintr-o zon de memorie ntr-alta. date_sir segment word public 'data' sir1 db 1000 dup (7,0f0h) ; irul surs lung1 equ $ - sir ; lungimea irului surs sir2 db 1000 dup (2 dup (?)) ; rezervare pt. ir dest. ptr_sir1 dd sir1 ; pointer sir1 ptr_sir2 dd sir2 ; pointer sir2 date_sir ends cod segment word public 'code' assume cs:cod, ds:date_sir, es:date_sir start: mov ax, date_sir ; iniializare registru segment DS mov ds, ax ; i apoi adresele celor dou iruri mov es, ax ; sau: les di,ptr_sir2 lea di, sir2 ; lds si,ptr_sir1 lea si, sir1 mov cx, lung1 ; contorul transferului = lungimea sursei cld ; direcia de parcurgere a irului (df=0) repeta: lodsb

cod end

stosb loop repeta mov ax, 4c00h int 21h ends start

; sau: movs sir2,sir1 , sau movsb ; sau: rep movsb ; revenire DOS

2) Determinarea poziiei unui anumit caracter (sau a unui ir de caractere) ntr-un fiier surs de pe disc. .model small .stack 10h .data car equ 'A ; caracterul de identificat (sau irul) lung equ 2048 ; dimensiunea maxim a fiierului-4 sectoare buffer db lung dup (?); spaiu de mem. pentru fiier nume_fis db 'fisier.asm', 0 ; nume fii.- ASCIIZ, adic dup ; numele poate fi precedat i de calea de acces pozitie dw ? ; poziia caracterului n fiier nr_logic dw ? ; numrul logic atribuit fiierului contor dw ? ; numrul efectiv de caractere citite mes_lipsa db 'nu exista fisier cu acest nume$' mes_err_cit db 'eroare de citire de pe disc$' mes_car_lipsa db 'caracterul cautat nu este in fisier$' .code start: mov ax, @data ; iniializare DS mov ds, ax mov ah, 3dh ; apel DOS pentru deschidere de fiier mov al, 0 ; n modul "citete" (1-scrie,2-citire/scriere) lea dx, nume_fis ; adresa numelui fiierului int 21h ; apel funcie 'deschide fiier' jc lipsa_fis mov nr_logic, ax ; se depune numrul sectorului mov bx, ax ; i n BX, pentru funcia de citire mov cx, lung ; contor numr maxim de caractere citite lea dx, buffer ; adresa unde se vor depune caracterele mov ah, 3fh ; funcia de citire din fiier int 21h jc err_cit ; dac a aprut eroare al citire mov contor, ax ; la 'contor' se depune numrul de car. mov cx, ax ; contor de cutare 'car' push ds ; se ncarc n ES adresa de segment pop es ; a 'buffer'-ului lea di, buffer ; i n registrul (DI) offsetul acestuia mov al, car ; caracterul de cutat cld ; stabilire direcie de parcurgere, (DF)=0 repne scasb ; continu scanarea pn-l gsete

je gasit ; dac nu s-a gsit nu se face saltul lea dx, mes_car_lipsa ; i se tiprete mesajul mov ah, 9 ; mesajul: 'caracterul cautat nu este in fisier' int 21h jmp gata gasit: dec di ; poziia caracterului cutat, (DI)-1 mov pozitie, di ; deoarece (DI) a fost actualizat dup ; scanare lipsa_fis: lea dx, mes_lipsa ; nu s-a gsit fiierul cu mov ah, 9 ; numele specificat int 21h jmp gata err_cit: lea dx, mes_err_cit ; eroare la citirea fiierului mov ah, 9 int 21h gata: mov ah, 3eh ; nchiderea fiierului deschis mov bx, nr_logic int 21h mov ax, 4c00h ; revenire DOS int 21h end start

jmp

gata

Instruciuni de transfer al controlului programului


Instruciunile de transfer al controlului programului opereaz asupra lui IP i CS. La apariia unui astfel de transfer, coada de instruciuni nu mai conine instruciunea urmtoare i EU va transmite noua adres la BU, care va obine instruciunea urmtoare direct din memorie, utiliznd noile valori pentru CS:IP; instruciunea va fi transferat ctre IU i EU, pentru execuie, i BU apoi ncepe reumplerea cozii de la noua locaie. Exist patru tipuri de instruciuni de transfer control: - instruciuni de transfer necondiionat; - instruciuni de transfer condiionat; - instruciuni de ciclare; - instruciuni de ntrerupere; Dintre acestea numai instruciunile de ntrerupere afecteaz indicatorii. Instruciuni de transfer control, necondiionat Transferul controlului se poate face la o locaie (int) n segmentul de cod curent (transfer intrasegment/NEAR) sau la un segment de cod diferit (transfer intersegment/FAR). CALL <nume_procedur> Aceast instruciune activeaz o procedur, salvnd adresa de revenire, n stiv, pentru a permite unei instruciuni RET (return), din procedur, s transfere controlul napoi la instruciunea urmtoare lui CALL.

Asamblorul genereaz tipuri diferite de instruciuni main pentru CALL, dup modul cum programatorul a definit numele procedurii, cu atributul NEAR sau FAR. Pentru returnarea corect a controlului, tipul instruciunii CALL trebuie s fie potrivit cu tipul instruciunii RET. Diferitele forme ale instruciunii CALL permit ca adresa procedurii int s fie obinut direct din instruciune (direct), sau de la o locaie de memorie sau dintr-un registru referit de instruciune (indirect). a) - CALL direct intrasegment: (SP) (SP) - 2 ((SP)+1:(SP)) (IP) (IP) (IP) + deplasament La 386/486 deplasamentul poate avea i 32 bii, deci adunarea se va face modulo 4G. call near_etich call near_proc b) - CALL direct intersegment: (SP) (SP) - 2 ((SP)+1:(SP)) (CS) (CS) al 2-lea cuvnt din instr. (adresa de segment) (SP) (SP) - 2 ((SP)+1:(SP)) (IP) (IP) primul cuvnt din instr. (adresa de offset) call far_etich; call far_proc c) - CALL indirect intrasegment: (SP) (SP) - 2 ((SP)+1:(SP)) (IP) (IP) registru / memorie; Exemple: call cx; call word ptr nume_var call word ptr [bx][si]; call mem_word d) - CALL indirect intersegment, poate fi fcut numai prin memorie: (SP) (SP) - 2 ((SP)+1:(SP)) (CS) (CS) al 2-lea cuvnt mem. referit de instruciune (SP) (SP) - 2 ((SP)+1:(SP)) (IP) (IP) primul cuvnt mem. referit de instruciune call dword ptr [bx]; call dword ptr nume_var[bp][si] Cnd se utilizeaz apeluri indirecte trebuie asigurat c tipul lui CALL este potrivit cu tipul instruciunii de revenire RET->erori. RET [val_pop] (RETurn from procedure) Asamblorul genereaz 2 tipuri de instr. main: RET intrasegment dac procedura a fost definit NEAR, i RET intersegment, dac procedura este de tip FAR. Valoarea val_pop, care este opional, este prevzut pentru a descrca parametrii din stiv. (IP) ((SP)+1:(SP)) (SP) (SP) + 2

inter_segment then (CS) ((SP)+1:(SP)) (SP) (SP) + 2 if val_pop <> 0 then (SP) (SP) + val_pop Tipul instruciunii RET trebuie s se potriveasc cu tipul lui CALL: call word ptr [bx] ; pentru o procedur de tip FAR. - se va salva n stiv doar offsetul de revenire (IP), iar la execuia instruciunii RET, din procedura de tip FAR, se va reface din stiv, pe lng IP i CS, cu urmtorul cuvnt din stiv (i se va pierde controlul asupra calculatorului). call dword ptr [bp][si] ; pentru o procedur de tip NEAR. - se vor salva n stiv adresele de revenire pentru CS:IP, dar la terminarea procedurii se va reface din stiv numai IP, rmnnd n stiv un cuvnt, care n final va duce la pierderea controlului. JMP <int> Spre deosebire de CALL, JMP nu salveaz n stiva nici o informaie. a) JMP direct intrasegment, modific IP prin adunarea deplasamentului relativ al intei, coninut n instruciune la valoarea, actualizat, a lui IP. Auto-relative (relocabile dinamic). jmp near_etich ; salt direct intrasegment jmp short near_etich; salt de tip short b) - JMP direct intersegment (instr. are 5 octei/286, sau 5/7 la 386): jmp far_etich ; salt n alt segment jmp far ptr etich ; 'etich' poate fi i n acelai segment c) - JMP indirect intrasegment: jmp ax jmp tabela[bx] jmp si jmp word ptr [bp][di] d) - JMP indirect intersegment, poate fi fcut numai prin memorie: jmp etich_dword jmp dword ptr [bx][si] Programul urmtor execut diferite secvene de program, n funcie de opiunea utilizatorului, introdus de la tastatur. .model small .data executie db 0Dh, 0Ah, 'Executa secventa (1,2,3 sau 4=stop):$' mes_secv1 db 'S-a executat secventa 1',0dh,0ah,'$' mes_secv2 db 'S-a executat secventa 2',0dh,0ah,'$' mes_secv3 db 'S-a executat secventa 3',0dh,0ah,'$' tab_secv label word dw secv1 dw secv2 dw secv3 dw gata .code start: mov ax, @data ; iniializare adresa de segment mov ds, ax iar: lea dx, executie ; solicit secvena dorit, utilizatorului

if

secv1:

secv2:

secv3:

gata: .stack end

mov ah, 9 ; se tiprete mesajul de selecie secven int 21h ; apel funcia 9, tiprire mesaj mov ah, 1 ; apel funcia 1, citire caracter int 21h ; caracter returnat n AL sub al, 31h ; intervalul '1''4' -> 03 i verific dac jc iar ; este n intervalul 03: dac nu, cere cmp al, 4 ; o valoare, n acest interval, fr a executa jnc iar ; vreuna dintre secvene cbw ; extensie pe 16 bii mov bx, ax shl bx, 1 ; *2, pentru a obine adresa relativ jmp word ptr tab_secv[bx] ; n tabela cu adr. secvene lea dx, mes_secv1; se execut prima secven mov ah, 9 int 21h jmp short iar lea dx, mes_secv2; se execut a doua secven mov ah, 9 int 21h jmp short iar lea dx, mes_secv3; se execut a treia secven mov ah, 9 int 21h jmp short iar mov ax, 4c00h ; revenire DOS int 21h 20h

Instruciuni de transfer control, condiionat Jcond <int> Toate salturile condiionate sunt de tip SHORT, adic inta trebuie s fie n segmentul de cod curent, n intervalul de [-128, +127] octei fa de instruciunea de transfer (de ex. JMP 00, realizeaz saltul la primul octet al urmtoarei instruciuni). La 386/486 aceste instruciuni permit i realizarea unui salt de tip NEAR, adic n cadrul aceluiai segment (64K sau 4G, depinde de atributul de dimensiune adres). Deoarece adresa de salt este determinat prin adunarea deplasamentului relativ al intei, la IP-ul actualizat, toate salturile condiionate sunt autorelative. n cazul cnd se dorete un salt condiionat pe o distan mai mare de 128 octei, la 286, sau un salt ntr-un alt segment, atunci trebuie s se utilizeze dou instruciuni de salt: un salt condiionat (pentru condiia negat, adic, de exemplu JE, pentru JNE), n intervalul [ -128,+127], iar, imediat dup instruciunea de salt condiionat, o instruciune de salt, necondiionat, pe distana dorit. JZ / JE JNZ / JNE ZF = 1, dac este egalitate (d) = (s) ZF = 0, dac nu este egalitate (d) <> (s)

JL / JNGE SF <> OF, dac (d) < (s), pentru numere cu semn JLE / JNG SF <> OF sau ZF = 1, (d)<=(s), numere cu semn JNL / JGE SF = OF, dac (d) >= (s), pentru numere cu semn JNLE / JG SF = OF i ZF = 0, (d) > (s), pentru numere cu semn JB /JNAE /JC CF = 1, dac (d) < (s), numere fr semn JBE / JNA CF = 1 sau ZF = 1, (d)<=(s), numere fr semn JNB /JAE /JNC CF = 0, dac (d) >= (s), numere fr semn JNBE / JA CF = 0 i ZF = 0, (d) > (s), pentru numere fr semn JP / JPE PF = 1, dac numrul are paritate par JNP / JPO PF = 0, dac numrul are paritate impar JO/JNO OF = 1/0, dac este/ nu este depire de reprezentare JS /JNS SF = 1/0, dac numrul este negativ/ pozitiv J(E)CXZ (E)CX = 0, test asupra registrului ECX sau CX condiie ZF CF d>s 0 0 d=s 1 0 d<s 0 1 pentru numere fr semn salt pentru d=s d <> s d<s d>s d <= s d >= s numere fr semn JE / JZ JNE / JNZ JB / JNAE / JC JA / JNBE JBE / JNA JAE / JNB / JNC condiie OF SF d > s 0/1 0/1 d=s 0 0 d < s 0/1 1/0 pentru numere cu semn numere cu semn JE / JZ JNE / JNZ JL / JNGE JG / JNLE JLE / JNG JGE / JNL ZF 0 1 0

Determinarea valorii maxime dintr-un ir de valori (cu semn). .model small .stack 10h .data sir db 10,20,-30,100,-100,200 lung dw $-sir maxim db ? mes_sir_vid db 'sir vid de valori$' .code mov ax, @data ; iniializare registru segment mov ds, ax mov cx, lung ; contor numr de valori din ir jcxz sir_vid ; dac irul este vid se tiprete mesaj lea si, sir ; index elemente din ir cld ; direcia de parcurgere mov bl, [si] ; se iniializeaz valoarea maxim din ir inc si ; actualizare index elemente dec cx ; actualizare contor

jcxz gata ; dac a fost un singur element s-a terminat iar: lodsb ; citete element curent din ir cmp bl, al ; se compar cu maximul curent jge urm ; dac max > val. curent trece la elem. urmtor ; pentru numere fr semn se nlocuiete jge cu jnc mov bl, al ; altfel se actualizeaz valoarea maxim urm: loop iar ; se reia ciclul dac mai sunt elem. n ir gata: mov maxim, bl ; se depune valoarea maxim iesire: mov ax, 4c00h ; revenire DOS int 21h sir_vid: lea dx, mes_sir_vid ; se tiprete mesajul mov ah, 9 ; 'sir vid de valori' int 21h jmp iesire ; revenire DOS end Instruciuni de ciclare Aceste instruciuni pot fi folosite pentru a controla repetiia unor cicluri soft. Ele permit o programare uoar a structurilor de control de tip ciclu cu test la sfrit. Ele utilizeaz drept contor, al ciclului, registrul CX. Instruciunile de ciclare sunt auto -relative, i pot transfera controlul la o locaie (int) aflat n intervalul [-128,+127] de octei fa de ele, deci realizeaz numai transferuri de tip SHORT (att pentru 286 ct i pentru 386/486). Aceste instruciuni nu modific nici un indicator. LOOP <short_etich> (LOOP control with CX counter) (CX) (CX) - 1 if (CX) <> 0 then (IP) (IP) + deplasament (short_etich); Calculul sumei elementelor unui ir de tip cuvnt. mov cx, lung_sir ; contor numr de elemente mov ax, 0 ; suma va fi pe dou cuvinte mov bx, ax ; i se iniializeaz cu 0 mov si, ax ; index pentru adresarea elementelor aduna: add ax, sir[si] adc bx, 0 ; transporturile se acumuleaz n BX add si, type sir ; actualizare index loop aduna ; dac nu e gata se reia adunarea mov suma, ax ; se depune rezultatul, ncepnd cu mov suma[2], bx ; cu cuvntul mai puin semnificativ

LOOPNE / LOOPNZ <short_etich> (LOOP while Not Equal/Zero, with CX counter)

(CX) (CX) - 1 if ((CX) <> 0) and (ZF=0) then (IP) (IP) + deplasament (short_etich); Determinarea ultimului element dintr-o list nlnuit. Ultimul element dintr-o list va conine valoarea zero n cmpul de adres. lea bx, offset cap_lista ; adresa de nceput a listei mov cx, N ; dimensiunea maxim a listei urm: mov bx, [bx + lung_info] ; adresa elementului urmtor cmp bx, 0 ; se compar cu 0 loopne urm ; se reia dac nu s-a gsit je gasit ; s-a gsit ultimul element din list, adr. n BX ; dac nu se execut saltul nu s-a gsit ultimul element printre cele N elemente Instruciuni de ntrerupere Aceste instruciuni permit rutinelor de servire a ntreruperilor s fie activate prin program la fel ca la apariia unei ntreruperi hardware externe. Singura instruciune ce altereaz indicatorii este IRET. INT <tip_ntrerupere> (call to INTerrupt procedure) (SP) (SP) -2 ((SP)+1:(SP)) indicatori (tf), (if) 0 (SP) (SP) - 2 ((SP)+1:(SP)) (CS) (CS) (n * 4 + 2) (SP) (SP) - 2 ((SP)+1:(SP)) (IP) (IP) (n * 4 ) (INTerrupt on Overflow) Aceast instruciune genereaz ntrerupere dac OF=1.

INTO

BOUND <dest_reg>, <sursa_mem> (check array index against BOUNDs) Determin dac valoarea, cu semn, coninut n registrul destinaie (16/32 bii), specificat de instruciune, se afl ntre limitele specificate de operandul surs, care trebuie s fie operand din memorie (16/32 bii). Se compar operandul destinaie cu dou cuvinte (sau cuvinte duble), aflate n memorie de la adresa specificat de cel de-al doilea operand. Dac valoarea destinaiei nu este ntre cele dou limite (la locaii succesive), specificate de surs, din memorie, se genereaz ntrerupere pe nivelul 5 (INT 5). IRET / IRETD (Interrupt RETurn) Transfer controlul napoi la punctul de ntrerupere, prin refacerea IP, CS i a indicatorilor, din stiv. Astfel instruciunea IRET afecteaz toi indicatorii, prin restaurarea lor, la valorile anterior salvate.

mprirea unui numr de 32 bii (A1,A0) la un numr de 16 bii (B). Rezultatul, ctul, poate avea, cel mult, 32 de bii (Q1,Q0), iar restul 16 bii (R0). Se va ncerca mai nti o mprire obinuit, i dac ctul este de 16 bii, operaia este terminat. Dac nu, deci dac ctul este de 32 de bii atunci se va face mprirea n modul urmtor: A1 * 216 + A0 = (Q1 * 216 + Q0) * B + R0 unde Q1 = [ A1 / B ] i deci A1 = Q1 * B + R1 nlocuind A1 n prima relaie rezult: R1 * 216 + A0 = Q0 * B + R0 Deci ordinea operaiilor va fi: - se mparte A1 la B i rezult: Q1 i R1; - se mparte (R1 * 216 + A0) la B i rezult: Q0 i R0. ; procedura de mprire, primete: ; (DX, AX) - demprit (32 bii) ; (BX) - mpritor (16 bii) ; i va returna: ; (BX, AX) - ctul ; (DX) - restul pdiv proc cmp bx, 0 ; mpritor = 0 ? jnz cdiv ; dac nu se continu mprirea, altfel int 0 ; se apeleaz procedura de eroare la mprire jmp eroare cdiv: push es ; se salveaz registrele de lucru push di push cx mov di, 0 mov es, di ; ES:DI=0:0, adresa ntrerupere nivel 0 push es:[di] ; se salveaz adresa de tratare ntrerupere push es:[di+2] ; nivel 0 (eroare la mprire) n stiv ; se nlocuiete adresa salvat (proc. de eroare la mprire) cu ; adresa procedurii prezentate anterior lea cx, int_0 ; offset procedura de mprire mov es:[di], cx ; se depune n locul proc. de eroare mov cx, cs ; adresa de segment a noii proceduri mov es:[di+2], cx ; se pune n locul celei de eroare ; se ncearc mprirea normal div bx ; dac ctul are 16 bii s-a terminat i BX = 0 ; dac nu, deci dac ctul are 32 bii, se va genera ntrerupere ; pe nivelul 0, care a fost nlocuit cu procedura de mprire xor bx, bx ; BX = 0, ctul este doar n AX revenire: pop es:[di+2] ; se reface adresa procedurii pop es:[di] ; de ntrerupere, nivel 0, eroare mprire pop cx ; se refac registrele salvate n stiv pop di pop es

ret ; procedura propriu-zis de mprire, care a fost pus n locul ; procedurii de tratare eroare la mprire (nivel 0) int_0: push bp ; salvare BP, pentru a accesa stiva mov bp, sp ; se va nlocui adresa salvat, a instr. ; urmtoare mpririi cu cea a instruciunii de 'revenire' mov word ptr [bp+2], offset revenire ; sau, ntruct instr. xor bx, bx are doi octei. ; se poate utiliza i: add word ptr [bp+2], 2 push ax ; se salveaz A0 mov ax, dx ; (AX) A1 sub dx, dx ; pregtire demprit (DX=0) ; se realizeaz mprirea A1/B -> (R1,Q1) = (DX,AX) div bx pop cx ; CX = A0 push ax ; se salveaz Q1 mov ax, cx ; (DX,AX) = (R1,A0) ; se realizeaz mprirea (R1,A0)/B -> (R0,Q0) = (DX,AX) div bx ; (DX,AX) = (R0,Q0) pop bx ; se reface ctul: (BX) = Q1 pop bp iret eroare: . . . . . ret pdiv endp Instruciuni de control procesor Aceste instruciuni permit programelor s controleze diferite funciuni ale procesorului. Un grup de instruciuni actualizeaz indicatorii, altul este utilizat pentru sincronizarea microprocesorului cu evenimente externe, i mai exist o instruciune care nu realizeaz nimic (NOP). Instruciuni pentru poziionarea indicatorilor CLC (CLear Carry flag) CF 0 STC (SeT Carry flag) CF 1 CMC (CoMplement Carry flag) CF not (CF) Aceste instruciuni de poziionare a lui CF se utilizeaz la operaiile de rotaie, deplasare sau la adunri/scderi de numere reprezentate pe mai muli octei/cuvinte etc. CLD (CLear Direction flag) DF 0 STD (SeT Direction flag) DF 1 Acest indicator va determina direcia de parcurgere a irurilor. CLI (CLear Interrupt enable flag) IF 0

STI

(SeT Interrupt enable flag)

IF 1 Indicatorul IF dezactiveaz sau activeaz, prin poziionare pe 0, respectiv 1, ntreruperile externe, ce apar pe linia INTR. Sunt dezactivate numai ntreruperile mascabile (INTR), nu i ntreruperea nemascabil NMI, care este servit, indiferent de poziia lui IF. La activarea sistemului de ntreruperi (STI), ntreruperea, pe linia INTR, este recunoscut dup execuia instruciunii urmtoare lui STI. Instruciuni de sincronizare cu evenimente externe HLT (HaLT) Determin intrarea proc. n starea 'halt', din care iese doar dac: - se activeaz linia RESET; - se transmite semnal de ntrerupere pe linia NMI; - se transmite semnal de ntrerupere pe linia INTR, dac ntreruperile nu au fost dezactivate. Aceast instruciune se poate folosi la sfritul unei bucle soft, n situaia n care programul trebuie s atepte un eveniment extern (ntrerupere de la un dispozitiv extern). n acest caz se va salva n stiv adresa instruciunii urmtoare lui HLT. WAIT (WAIT) Determin intrarea proc. n starea 'wait', ct timp linia BUSY\ este activ. Procesorul intr ntr-o stare 'idle', i repet testarea liniei BUSY\, ciclic la intervale de ase perioade de ceas. Cnd linia BUSY\ devine inactiv, se continu execuia programului cu instruciunea urmtoare lui WAIT. Aceast stare poate fi ntrerupt, printr-un semnal de ntrerupere, dar dup tratarea ntreruperii se reintr n aceast stare, ntruct se salveaz n stiv adresa acestei instruciuni. ESC <Cod_Op>,<sursa> (ESCape) Aceast instruciune este specific coprocesorului matematic, i ea este identificat prin primii cinci bii ai codului de operare care sunt 11011; ceilali bii din cmpul codului operaiei identific tipul operaiei coprocesorului. De fapt coprocesorul urmrete magistrala sistemului, i cnd identific execuia acestei instruciuni, el o captureaz; dac operandul surs este un registru procesorul nu face nimic cu el, iar dac este un operand din memorie, l citete dar l ignor. n schimb coprocesorul poate captura acest operand cnd este citit din memorie. LOCK (assert LOCK# signal prefix) Acesta este un prefix, de un octet, care determin activarea semnalului de magistral LOCK, ct timp se execut instruciunea precedat de acest prefix. ntr-un sistem multiprocesor, acest semnal poate fi utilizat pentru a asigura procesorului acces exclusiv la utilizarea magistralei, i deci a unei resurse (memorii) partajate. mov al, 1 astept: lock xchg al, semafor ; citire i setare semafor test al, al ; testare semafor = 0 ?, jnz astept ; dac nu, resursa este ocupat ; i se ateapt eliberarea ei .... . ; utilizare exclusiv a resursei mov semafor, 0 ; eliberare resurs

NOP (No OPeration) Dup cum spune i numele acestei instruciuni, ea nu realizeaz nici o prelucrare; nu afecteaz nici un indicator. Ea dureaz trei perioade de ceas, i are codul main al instruciunii XCHG AX,AX, sau XCHG EAX,EAX.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

47. Exemple de programe pentru fiecare tip de instruciuni.

Instruciuni de transfer date.


Exemplu: s inversm, ntre ei, octeii dintr-un ir de cuvinte. .model small .data mesajdw 'Ex','em','pl','u ','pr','og','ra','m ','2$' lung_mesaj equ ($-mesaj)/2 linie_noua db 0dh,0ah,'$' .code start: mov ax,@data ; iniializare registru segment DS mov ds,ax ; cu adresa segmentului de date lea dx,mesaj ; tiprim mesajul sub forma iniial mov ah,9 ; utiliznd funcia 9, din DOS : int 21h ; "xEmelp urpgora m" lea dx,linie_noua ; se trece pe o linie noua mov ah,9 int 21h ; pentru a aduce mesajul la forma dorit trebuie inversai ; octeii, fiecrui cuvnt ntre ei lea si,mesaj mov cx,lung_mesaj mov ax,[si] ; se ia cte un cuvnt xchg al,ah ; i se inverseaz octeii mov [si],ax ; se depune la aceeai adres add si,type mesaj ; se actualizeaz adresa curent loop iar ; i se continu pentru tot irul ; se tiprete mesajul astfel obinut lea dx,mesaj mov ah,9 ; se va tipri mesajul: int 21h ; 'Exemplu program 2' mov ax,4c00h ; revenire DOS int 21h start

iar:

end

Instruciuni de transfer specifice acumulatorului Programul citete de la tastatur codul ASCII al unei taste i afieaz acest cod (sub forma a dou cifre hexa). seg_date segment tab_conv db '0123456789ABCDEF' mesaj db '-are codul ASCII-' tasta db 2 dup (?), 0dh,0ah,'$' seg_date ends seg_cod segment assume cs : seg_cod, ds : seg_date start:

mov mov mov int mov lea and xlat mov mov mov shr xlat mov lea mov int mov int seg_cod end start

ax,seg_date ds,ax ah,1 ; citire cu ecou a unei taste 21h ; fr ecou este funcia 8 ah,al ; salvare cod tast bx,tab_conv ; iniializare BX, pentru XLAT al,0fh ; se reine doar a doua tetrad tab_conv ; codul ASCII al acestei tetrade tasta+1,al ; este cea de-a doua cifr a codului al,ah ; codul iniial al tastei cl,4 ; contor numr de deplasri la dreapta al,cl ; deplasare logic la dreapta cu 4 bii tab_conv ; conversia primei tetrade tasta,al ; codul ASCII al primei tetrade dx,mesaj ah,9 ; se tiprete codul tastei 21h ax,4c00h ; revenire DOS 21h ends

Instruciuni Aritmetice
Programul adun dou numere, fr semn, reprezentate pe mai multe cuvinte (octei), dar de lungimi diferite, iar rezultatul se va depune peste numrul mai lung. add_data_2 segment primul dw 0a8adh, 7fe2h, 0a876h,0 lung_1 dw ($ - primul)/2 al_doilea dw 0fedch, 0abcdh, 0cdefh, 52deh, 5678h, 0 lung_2 dw ($ - al_doilea)/2 add_data_2 ends multi_add_2 segment assume cs: multi_add_2, ds: add_data_2 start: mov ax,add_data_2 mov ds,ax ; se determin cel mai mare numr, unde se pune rezultatul ; vom considera c (BX)= adresa numrului mai lung ; (DX)= dimensiunea numrului mai lung ; (BP)= adresa numrului mai scurt ; (CX)= dimensiunea acestuia ; numrul de octei ai numrului mai mic va controla bucla_1 ; n care ambele numere au cuvinte ce trebuie adunate ; diferena dimensiunilor celor dou numere va controla bucla_2

; necesar dac apare transport, pentru propagarea acestuia mov dx,lung_2 ; presupun, iniial numrul al lea bx,al_doilea ; doilea mai mare mov cx,lung_1 lea bp,primul cmp dx,cx ; verific presupunerea fcut jge num2_mai_mare ; dac e respectat se continu xchg bx,bp ; dac nu se schimb ntre ele coninutul xchg cx,dx ; perechilor de registre, respective num2_mai_mare: sub dx,cx ; determin diferena dintre lungimile lor clc ; (CF)=0 mov si,0 ; se iniializeaz indexul elementelor bucla_1: mov ax,ds:[bp][si] adc [bx][si],ax inc si ; actualizare index inc si loop bucla_1 ; (CX)=contor pentru adunare mov cx,dx ; contor pentru propagarea transportului bucla_2: jnc gata ; dac nu mai este transport de propagat adc word ptr [bx][si],0 inc si inc si loop bucla_2 ; trebuie testat (CF), i dac avem transport, adic se ; depete dimensiunea iniial a numrului mai lung, ; transportul trebuie memorat la adresa urmtoare, ; dac s-a rezervat spaiu, sau semnalat depirea: jc eroare . . . gata: mov ax,4c00h int 21h multi_add_2 ends end start ; (DI) = va conine extensia de semn a numrului mai scurt num2_mai_mare: push cx ; salvare lungime numr mai scurt mov di,0 ; extensie de semn pentru numr pozitiv mov si,bp ; adresa de nceput a numrului mai scurt shl cx,1 ; lungimea * 2 = numr octei ai numrului add si,cx ; se poziioneaz pe primul element sub si,2 ; care conine bitul de semn mov ax,[si] ; i i testm bitul de semn cmp ax,0 ; dac este pozitiv se continu cu valoarea jp cont ; iniial pentru (di)=0 mov di,0ffffh ; altfel (di)=ffffh, extensie semn numr negativ

cont: pop cx ; refacerea contorului sub dx,cx ; determin diferena dintre lungimile lor clc ; (CF)=0 mov si,0 ; se iniializeaz indexul elementelor bucla_1: mov ax,ds:[bp][si] adc [bx][si],ax inc si ; actualizare index inc si loop bucla_1 ; (CX)=contor pentru adunare mov cx,dx ; contor pentru propagarea transportului bucla_2: adc word ptr [bx][si],di ; i a semnului numrului mai scurt inc si inc si loop bucla_2 ; n acest punct se testeaz OF pentru a detecta o depire ; a dimensiunii iniiale a numrului mai lung Instruciunile de nmulire / mprire Afiarea n zecimal a coninutului registrului AX: ; (AX) conine o valoare care este n intervalul 065535 ; dac se mparte numrul la 100 se obine ca prim rest ; o valoare ce conine ultimele dou cifre (zeci, uniti) ; dac se mparte ctul anterior din nou la 100 se va obine ; o valoare ce conine urmtoarele dou cifre (mii, sute) ; iar acest ultim rest va avea valoarea primei cifre ; a zecilor de mii, care este n intervalul: 0 - 6. mov bx,100 ; mpritor mov dx,0 ; extensie semn demprit pozitiv div bx ; dx = ultimele 2 cifre (zeci, uniti) mov cx,dx ; ax = primele 3 cifre, cx = ultimele 2 cifre mov dx,0 ; extensie semn demprit pozitiv div bx ; dx = cifrele: mii, sute; ax = zeci de mii push dx ; se salveaz dx deoarece va fi modificat add al,30h ; se tiprete cifra zecilor de mii(06) mov dl,al ; caracterul de tiprit n DL mov ah,2 ; se apeleaz funcia 2 din DOS int 21h ; care tiprete caracterul din (DL) pop ax ; se iau din stiva valoarea pt. mii, sute aam ; conversie la format zecimal nempachetat add ax,3030h ; conversie la cod ASCII mov dx,ax ; se salveaz cele dou cifre xchg dh,dl ; se tiprete cifra miilor mov ah,2 int 21h

xchg mov int mov aam add mov xchg mov int xchg mov int

dh,dl ah,2 21h ax,cx ax,3030h dx,ax dh,dl ah,2 21h dh,dl ah,2 21h

; se tiprete cifra sutelor ; ultimele dou cifre: zeci, uniti ; conversie la format zecimal nempachetat ; conversie la cod ASCII ; se salveaz cele dou cifre ; se tiprete cifra zecilor ; se tiprete cifra unitilor

Instruciuni de prelucrare la nivel de bit


Determinarea numrului de bii egali cu 1 dintr-o variabil. .model small .stack 100h .data lung_var equ 8 variabila dw lung_var dup (0acfh) nr_unitati db ? .code assume cs: @code, ds: @data start: mov ax, @data mov ds, ax mov si, 0 ; indexul curent al cuvintelor din variabila mov dl, lung_var ; contor numr de cuvinte mov bl, 0 ; contor numr de uniti gsite bucla2: mov cx, 16 ; contorul de bii pentru un cuvnt mov ax, variabila[si] ; se citete cuvntul curent bucla1: rcl ax, 1 ; o rotaie pentru a deplasa un bit adc bl, 0 ; se contorizeaz numrul de uniti loop bucla1 ; pentru un cuvnt add si, type variabila ; se actualizeaz indexul dec dl ; se testeaz dac mai sunt cuvinte jnz bucla2 ; dac da se reia citirea cuvintelor mov nr_unitati, bl ; dac nu se depune rezultatul mov ax, 4C00h ; revenire DOS int 21h end Aceeai problem poate fi rezolvat utiliznd instruciunile BSF i BTR, astfel: mov cx, lung_var ; contor dimensiune variabil mov bl, 0 ; contor uniti

mov si, 0 ; index cuvinte bucla: mov ax, variabila[si] scanare: bsf dx, ax ; determin primul bit 1 (indexul n DX) jz gata_cuv ; dac ZF=0, toi biii sunt 0 btr ax, dx ; transfer 1 din AX, din poziia DX n CF, adc bl, 0 ; iar bitul =0, sau inc bl, numr unitile jmp scanare ; se reia scanarea cuvntului curent gata_cuv: add si, 2 ; indexul cuvntului urmtor loop bucla ; decrementare contor numr de cuv. variabil ; dac nu s-a terminat variabila ia cuv. urmtor Tiprirea coninutului registrului DX, n format octal: tip_car proc far ; procedura tiprete caracterul al crui cod ASCII ; l primete n registrul AL push dx ; se salveaz registrul de lucru DX mov dl, al ; se apeleaz funcia 2 din DOS care mov ah, 2 ; tiprete caracterul al crui cod int 21h ; ASCII se transmite n registrul DL pop dx ; se reface registrul salvat ret tip_car endp tip_octal proc far ; tiprete n octal valoarea, fr semn transmis n DX push cx ; se salveaz registrele de lucru push ax ; prima cifr de tiprit este doar de 1 bit rol dx, 1 ; care este rotit pe ultimul bit mov al, dl ; i dus n registrul AL and al, 1 ; se terg ceilali bii add al, 30h ; este convertit la codul ASCII call tip_car ; i se tiprete ; urmtoarele 5 cifre sunt de cte 3 bii mov cx, 5 ; contor numr de cifre de tiprit octal1: push cx ; se salveaz contorul n stiv mov cl, 3 ; contor numr de rotiri la stnga rol dx, cl ; cifra este rotit pe ultimii 3 bii mov al, dl ; i adus n AL and al, 7 ; sunt teri ceilali bii add al, 30h ; i convertit la codul ASCII call tip_car ; tiprirea cifrei pop loop cx octal1 ; se citete valoarea contorului de cifre

pop pop ret tip_octal

ax cx endp

; se refac registrele salvate n stiv

Instruciuni de operare pe iruri


Copierea unui ir de octei dintr-o zon de memorie ntr-alta. date_sir segment word public 'data' sir1 db 1000 dup (7,0f0h) ; irul surs lung1 equ $ - sir ; lungimea irului surs sir2 db 1000 dup (2 dup (?)) ; rezervare pt. ir dest. ptr_sir1 dd sir1 ; pointer sir1 ptr_sir2 dd sir2 ; pointer sir2 date_sir ends cod segment word public 'code' assume cs:cod, ds:date_sir, es:date_sir start: mov ax, date_sir ; iniializare registru segment DS mov ds, ax ; i apoi adresele celor dou iruri mov es, ax ; sau: les di,ptr_sir2 lea di, sir2 ; lds si,ptr_sir1 lea si, sir1 mov cx, lung1 ; contorul transferului = lungimea sursei cld ; direcia de parcurgere a irului (df=0) repeta: lodsb stosb ; sau: movs sir2,sir1 , sau movsb loop repeta ; sau: rep movsb mov ax, 4c00h ; revenire DOS int 21h cod ends end start Determinarea poziiei unui anumit caracter (sau a unui ir de caractere) ntr-un fiier surs de pe disc. .model small .stack 10h .data car equ 'A ; caracterul de identificat (sau irul) lung equ 2048 ; dimensiunea maxim a fiierului-4 sectoare buffer db lung dup (?); spaiu de mem. pentru fiier nume_fis db 'fisier.asm', 0 ; nume fii.- ASCIIZ, adic dup ; numele poate fi precedat i de calea de acces pozitie dw ? ; poziia caracterului n fiier nr_logic dw ? ; numrul logic atribuit fiierului

contor dw ? ; numrul efectiv de caractere citite mes_lipsa db 'nu exista fisier cu acest nume$' mes_err_cit db 'eroare de citire de pe disc$' mes_car_lipsa db 'caracterul cautat nu este in fisier$' .code start: mov ax, @data ; iniializare DS mov ds, ax mov ah, 3dh ; apel DOS pentru deschidere de fiier mov al, 0 ; n modul "citete" (1-scrie,2-citire/scriere) lea dx, nume_fis ; adresa numelui fiierului int 21h ; apel funcie 'deschide fiier' jc lipsa_fis mov nr_logic, ax ; se depune numrul sectorului mov bx, ax ; i n BX, pentru funcia de citire mov cx, lung ; contor numr maxim de caractere citite lea dx, buffer ; adresa unde se vor depune caracterele mov ah, 3fh ; funcia de citire din fiier int 21h jc err_cit ; dac a aprut eroare al citire mov contor, ax ; la 'contor' se depune numrul de car. mov cx, ax ; contor de cutare 'car' push ds ; se ncarc n ES adresa de segment pop es ; a 'buffer'-ului lea di, buffer ; i n registrul (DI) offsetul acestuia mov al, car ; caracterul de cutat cld ; stabilire direcie de parcurgere, (DF)=0 repne scasb ; continu scanarea pn-l gsete je gasit ; dac nu s-a gsit nu se face saltul lea dx, mes_car_lipsa ; i se tiprete mesajul mov ah, 9 ; mesajul: 'caracterul cautat nu este in fisier' int 21h jmp gata gasit: dec di ; poziia caracterului cutat, (DI)-1 mov pozitie, di ; deoarece (DI) a fost actualizat dup jmp ; scanare lipsa_fis: lea dx, mes_lipsa ; nu s-a gsit fiierul cu mov ah, 9 ; numele specificat int 21h jmp gata err_cit: lea dx, mes_err_cit ; eroare la citirea fiierului mov ah, 9 int 21h gata: mov ah, 3eh ; nchiderea fiierului deschis mov bx, nr_logic

gata

int 21h mov ax, 4c00h ; revenire DOS int 21h end start Determinarea poziiei unui ir de caractere ntr-un fiier: sir_cardb 'asamblare' lung_sir dw $-sir_car ptr_sir dd sir_car ptr_buf dd buffer pozitie dw ? ; poziia irului de caractere ................... les di, ptr_buf lds si, ptr_sir mov cx, contor ; dimensiune buffer sub cx, lung_sir ; cutarea se va face ncepnd de la 0 inc cx ; pn la (contor) - (lung_sir) cld ; direcia de parcurgere (DF=0) reia: push si; se salveaz adresa irului cutat push di ; se salveaz adresa irului n care se cut push cx; se salveaz contorul numrului maxim de cutri mov cx, lung_sir ; contorul de comparaii repe cmps buffer, sir_car ; se compar ct timp sunt egale pop cx ; reface resurse salvate n stiv: contorul pop di ; i adrese iruri: destinaie - irul n care se pop si ; caut, surs (sub)irul care se caut je gasit ; salt dac s-a gsit sir_car n buffer inc di ; cutarea se va relua de la urmtorul caracter loop reia ; din buffer, dac (contor) <> 0 ; -> irul de caractere nu este n fiierul dat (respectiv n buffer) jmp nu_gasit gasit: mov pozitie, di ; valoarea salvat pentru (DI) ................... nu_gasit: ; tiprire mesaj: Nu s-a gasit sirul de caractere

Instruciuni de transfer al controlului programului


Programul urmtor execut diferite secvene de program, n funcie de opiunea utilizatorului, introdus de la tastatur. .model small .data executie db 0Dh, 0Ah, 'Executa secventa (1,2,3 sau 4=stop):$' mes_secv1 db 'S-a executat secventa 1',0dh,0ah,'$' mes_secv2 db 'S-a executat secventa 2',0dh,0ah,'$' mes_secv3 db 'S-a executat secventa 3',0dh,0ah,'$' tab_secv label word

dw dw dw dw

secv1 secv2 secv3 gata

.code start: mov ax, @data ; iniializare adresa de segment mov ds, ax iar: lea dx, executie ; solicit secvena dorit, utilizatorului mov ah, 9 ; se tiprete mesajul de selecie secven int 21h ; apel funcia 9, tiprire mesaj mov ah, 1 ; apel funcia 1, citire caracter int 21h ; caracter returnat n AL sub al, 31h ; intervalul '1''4' -> 03 i verific dac jc iar ; este n intervalul 03: dac nu, cere cmp al, 4 ; o valoare, n acest interval, fr a executa jnc iar ; vreuna dintre secvene cbw ; extensie pe 16 bii mov bx, ax shl bx, 1 ; *2, pentru a obine adresa relativ jmp word ptr tab_secv[bx] ; n tabela cu adr. secvene secv1: lea dx, mes_secv1; se execut prima secven mov ah, 9 int 21h jmp short iar secv2: lea dx, mes_secv2; se execut a doua secven mov ah, 9 int 21h jmp short iar secv3: lea dx, mes_secv3; se execut a treia secven mov ah, 9 int 21h jmp short iar gata: mov ax, 4c00h ; revenire DOS int 21h .stack 20h end Instruciuni de transfer control, condiionat Determinarea valorii maxime dintr-un ir de valori (cu semn). .model small .stack 10h .data sir db 10,20,-30,100,-100,200 lung dw $-sir maxim db ?

mes_sir_vid db .code mov mov mov jcxz lea cld mov inc dec jcxz lodsb cmp jge ax, @data ds, ax cx, lung sir_vid si, sir

'sir vid de valori$' ; iniializare registru segment

; contor numr de valori din ir ; dac irul este vid se tiprete mesaj ; index elemente din ir ; direcia de parcurgere bl, [si] ; se iniializeaz valoarea maxim din ir si ; actualizare index elemente cx ; actualizare contor gata ; dac a fost un singur element s-a terminat iar: ; citete element curent din ir bl, al ; se compar cu maximul curent urm ; dac max > val. curent trece la elem. urmtor ; pentru numere fr semn se nlocuiete jge cu jnc mov bl, al ; altfel se actualizeaz valoarea maxim urm: loop iar ; se reia ciclul dac mai sunt elem. n ir gata: mov maxim, bl ; se depune valoarea maxim iesire: mov ax, 4c00h ; revenire DOS int 21h sir_vid: lea dx, mes_sir_vid ; se tiprete mesajul mov ah, 9 ; 'sir vid de valori' int 21h jmp iesire ; revenire DOS end Instruciuni de ciclare Calculul sumei elementelor unui ir de tip cuvnt. mov cx, lung_sir ; contor numr de elemente mov ax, 0 ; suma va fi pe dou cuvinte mov bx, ax ; i se iniializeaz cu 0 mov si, ax ; index pentru adresarea elementelor aduna: add ax, sir[si] adc bx, 0 ; transporturile se acumuleaz n BX add si, type sir ; actualizare index loop aduna ; dac nu e gata se reia adunarea mov suma, ax ; se depune rezultatul, ncepnd cu mov suma[2], bx ; cu cuvntul mai puin semnificativ Determinarea primului element diferit de 0, dintr-un ir. mov cx, lung_sir ; contorul irului mov si, -1 ; iniializare SI reia: inc si

aici:

cmp sir[si], 0 ; se compar cu 0 loope reia ; dac este 0 se reia comparaia jz sir_zero ; dac ZF=1, tot irul conine numai 0 ; s-a determinat primul element <> 0, la adresa SI

Determinarea ultimului element dintr-o list nlnuit. Ultimul element dintr-o list va conine valoarea zero n cmpul de adres. lea bx, offset cap_lista ; adresa de nceput a listei mov cx, N ; dimensiunea maxim a listei urm: mov bx, [bx + lung_info] ; adresa elementului urmtor cmp bx, 0 ; se compar cu 0 loopne urm ; se reia dac nu s-a gsit je gasit ; s-a gsit ultimul element din list, adr. n BX ; dac nu se execut saltul nu s-a gsit ultimul element printre cele N elemente

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

48. Definirea i utilizarea procedurilor.

Definirea i utilizarea procedurilor


O procedur este constituit dintr-o secven de instruciuni, care poate fi apelat ori de cte ori este nevoie, i se declar folosind urmtoarea sintax: nume_procedura proc . < corpul procedurii > . ret endp [ near / far ]

nume_procedura

Parametrii (datele de intrare) pot fi transmii n diferite moduri:


prin registre; aceast modalitate poate avea, ns, urmtoarele dezavantaje: neconvenabil, dac se transmit un numr mare de parametri, caz n care numrul registrelor poate fi insuficient, sau neeconomic sub aspectul timpului de execuie, necesitnd frecvente salvri i refaceri de registre. prin memorie, care presupune rezervarea de memorie pentru aceti parametri, deci poate fi neeconomic din punct de vedere al spaiului de memorie ocupat (pentru structuri mari de date), mai ales dac astfel de date sunt necesare doar temporar; prin stiv, care este metoda cea mai avantajoas, ntruct permite accesul uor la informaie (cu instruciunile PUSH, respectiv POP), iar dup utilizare memoria alocat n acest scop este eliberat, deci zona respectiv de memorie devine disponibil. n cazul transmiterii parametrilor prin stiv, aceasta trebuie manipulat cu atenie de ctre procedur, astfel nct, n final, n vrful stivei s se gseasc adresa de revenire, pentru a se executa corect ultima instruciune din procedur: RET.

n ceea ce privete parametrii transmii prin stiv, acetia pot fi:


valoare, se transmite valoarea parametrului; adres, se transmite adresa parametrului, deci operaiile descrise de procedur se vor efectua direct asupra parametrului respectiv; n acest caz, procedura nu mai trebuie s returneze programului apelant parametrul respectiv.

n ceea ce privete returnarea parametrilor, aceast operaie se poate realiza utiliznd una din metodele folosite pentru transmiterea parametrilor ctre procedur, descrise anterior (registre, memorie sau stiv). n general, pentru definirea unei proceduri se parcurg urmtoarele etape:
stabilirea prelucrrilor efectuate de procedur; definirea datelor de intrare/ieire, precum i a modului de transmitere a parametrilor (registre, memorie sau stiv); definirea tipului procedurii (NEAR/FAR), mai ales dac parametrii se transmit prin stiv, situaie n care trebuie determinat poziia acestora n stiv; pentru directivele simplificate de segmentare nu este necesar precizarea tipului procedurii,

deoarece tipul este determinat de asamblor, din directiva MODEL; dac n procedur se utilizeaz nume simbolice, pentru a obine n mod corect accesul la acestea trebuie salvat DS n stiv, dup care se ncarc noua valoare i se folosete directiva ASSUME pentru a preciza asocierea segmentului la DS, iar la sfrit se reface registrul DS cu valoarea din stiv. nainte de orice prelucrare trebuie salvate n stiv registrele utilizate de procedur, iar nainte de revenirea n programul apelant, acestea trebuie restaurate. 1) Programul adun cte dou numere de la adrese succesive, i depune suma la locaiile imediat urmtoare. valori segment lista1 db 25 db 37 db ? lista2 db 27 db 35 db ? ........ valori ends stiva segment dw 4 dup (?) varf_stiva label word stiva ends adunare segment assume cs:adunare, ds:valori, ss:stiva mov ax, valori mov ds, ax mov ax, stiva mov ss, ax mov sp ,offset varf_stiva lea si, lista1 call aduna ; se adun elementele din prima list jc depasire ; dac apare transport se semnaleaz ....... lea si, lista2 call aduna ; se adun elementele din lista2 jc depasire ...... depasire: . . . . . ; tiprire mesaj de depire mov ax, 4c00h int 21h aduna proc push ax mov al, [si] ; primul element din list add al, [si+1] ; se adun cu urmtorul mov [si+2], al ; i se depune rezultatul n continuare pop ax

ret aduna endp adunare ends end 2) Adunarea elementelor unui vector, de orice lungime, cu pstrarea rezultatului n acumulator. Procedura primete n BX - adresa vectorului, iar n CX - lungimea sa, returneaz suma n AX. date_vectori segment vector1 db 6, 63, 100, 123, -134, 112, 77 contor1 equ $ - vector1 rezultat1 dw ? ....... date_vectori ends dv equ <date_vectori> pg equ <procedura_generala> procedura_generala segment assume cs:pg, ds:dv aduna proc push si ; se salveaz registrul de adresare vector mov ax, 0 ; se iniializeaz suma cu 0 mov si, 0 ; iniializare index componente vector reia: add al, [bx][si] ; adunare element curent adc ah, 0 ; se contorizeaz transporturile jc gata ; dac apare depire se termin procedura inc si ; actualizare index vector loop reia ; dac nu s-a terminat vectorul, se reia gata: pop si ; se reface registrul salvat ret aduna endp start: mov ax, dv mov ds, ax mov cx, contor1 ; contorul pentru primul vector lea bx, vector1 ; adresa de start a vectorului call aduna ; apel procedura de adunare mov rezultat1, ax ; se depune rezultatul jc depasire ; pt. depire se afieaz mesaj ....... depasire: . . . . . . ; afiare mes. de depire dim. rez. mov ax, 4c00h int 21h procedura_generala ends end start 3) Se va rescrie exemplul anterior utiliznd, n acest caz, pentru transmiterea parametrilor, stiva. Deci prin stiv se va transmite: adresa rezultatului, adresa vectorului i lungimea acestuia. date segment

vector1 db 6, 63, 100, 123, -134, 112, 77 contor1 equ $ - vector1 rezultat1 dw ? vector2 db 16, 163, 101, 232, -144, 26, -79 contor2 equ $ - vector2 rezultat2 dw ? ....... mes_depasire db eroare-depasire dimensiune rezultat, 0dh, $ date ends stiva segment stack 'stack' dw 20 dup (?) stiva ends utilizare_stiva segment assume cs:utilizare_stiva, ds:date, ss:stiva aduna proc far push bp ; se salveaz valoarea lui BP, pentru acces mov bp, sp ; la parametrii din stiv push bx ; se salveaz registrele de lucru push cx mov cx, [bp+6] ; CX = lungime vector mov bx, [bp+8] ; BX = adresa de nceput a vectorului mov ax, 0 ; iniializare sum reia: add al, [bx] ; adun elementul curent adc ah, 0 ; actualizare transport jc iesire ; dac apare depire se termin procedura inc bx ; actualizare index vector loop reia ; dac mai sunt elemente se reia adunarea mov bx, [bp+10] ; se citete adresa rezultatului, din stiv mov [bx], ax ; i se depune rezultatul la aceast adres iesire: ; Adrese mici pop cx ; CX - salvat pop bx ; BX - salvat pop bp ; BP - salvat [BP] ; IP - revenire ; CS - revenire ; contor1 [BP+6] ; offset vector1 [BP+8] ; offset rezultat1 [BP+10] ; Adrese mari ret 6 ; descrcarea stivei de parametrii (cei 6 octei) aduna endp utilizare_stiva endsaduna_date segment assume cs:aduna_date, ds:date, ss:stiva start: mov ax, date mov ds, ax

0ah,

lea ax, rezultat1 ; adresa rezultatului se push ax ; depune n stiv lea ax, vector1 ; adresa de nceput a vectorului push ax ; se depune n stiv mov ax, contor1 ; lungimea vectorului se push ax ; se depune n stiv call aduna ; se adun elementele primului vector jc eroare_add ; depire dim. rezultat (de tip cuvnt) ...... lea ax, rezultat2 ; adresa rezultatului se push ax ; depune n stiv lea ax, vector2 ; adresa de nceput a vectorului push ax ; se depune n stiv mov ax, contor2 ; lungimea vectorului se push ax ; se depune n stiv call aduna ; se adun cel de-al doilea vector jc eroare_add ; depire dim. rezultat (de tip cuvnt) ...... eroare_add: ; se va tipri un mesaj de eroare lea dx, mes_depasire mov ah, 9 int 21h mov ax, 4c00h int 21h aduna_date ends end start 4) Procedur pentru citirea unui numr zecimal ntreg, caractere ASCII, i convertirea numrului la o valoare ntreag, pe 16 bii. ; conversie zecimal (ASCII) binar (16 bii), rez. n AX. ; numrul este citit cifr cu cifr, termin citirea cu un caracter ; care nu este cifra ASCII, adic nu este n intervalul '0''9', ; sau dac s-au citit 5 cifre (val. maxim pe 16 bii ; este 65535); se citete un numr de forma: cncn-1...c1c0 ; valoarea sa n orice baz este: cn*bn+cn-1*bn-1+...+c1*b+c0 ; care se poate scrie: (...((cn*b+cn-1)*b+cn-2)*b+...+c1)*b +c0 ; deci relaia de calcul este val = val * baza + cifra zecbin proc far push bx ; se salveaz registrele de lucru push cx push dx mov cx, 5 ; numrul maxim de cifre ale numrului xor dx, dx ; iniial val = 0 mov bx, 10 ; baza n care se citete numrul reia_cit: mov ah, 1 ; citire cu ecou de la tastatur int 21h

sub al, 30h ; domeniul '0''9' se transform n 09 jb gata_cit ; dac nu este n intervalul 09 cmp al, 9 ; s-a terminat citirea cifrelor ja gata_cit mov ah, 0 ; extensie semn '+' pt. cifra citit push ax ; salvare ultima cifr citit mov ax, dx ; (AX) = val mul bx ; (DX,AX) = val * baza pop dx ; ultima cifr (valoare) citit jc gata ; dac apare depire, CF=1, i se termin add dx, ax ; val = val * baza + cifra jc gata ; eroare, (CF=1), depire rez. (65535) loop reia_cit ; nu s-au citit 5 cifre, continu citirea gata_cit: clc ; ieire normal, fr eroare, (CF=0) mov ax, dx ; depunerea rezultatului n (AX) gata: pop dx ; refacere registre salvate pop cx pop bx ret zecbin endp Programul care apeleaz procedura va testa starea indicatorului CF; dac (CF) = 1, eroare ; dac (CF) = 0, rezultatul conversiei n AX.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

49. Transferul parametrilor pentru proceduri n limbaj de asamblare (memorie, registre, stiv).

Transferul parametrilor pentru proceduri


Parametrii (datele de intrare) pot fi transmii n diferite moduri: prin registre; aceast modalitate poate avea, ns, urmtoarele dezavantaje: neconvenabil, dac se transmit un numr mare de parametri, caz n care numrul registrelor poate fi insuficient, sau neeconomic sub aspectul timpului de execuie, necesitnd frecvente salvri i refaceri de registre. prin memorie, care presupune rezervarea de memorie pentru aceti parametri, deci poate fi neeconomic din punct de vedere al spaiului de memorie ocupat (pentru structuri mari de date), mai ales dac astfel de date sunt necesare doar temporar; prin stiv, care este metoda cea mai avantajoas, ntruct permite accesul uor la informaie (cu instruciunile PUSH, respectiv POP), iar dup utilizare memoria alocat n acest scop este eliberat, deci zona respectiv de memorie devine disponibil. n cazul transmiterii parametrilor prin stiv, aceasta trebuie manipulat cu atenie de ctre procedur, astfel nct, n final, n vrful stivei s se gseasc adresa de revenire, pentru a se executa corect ultima instruciune din procedur: RET. n ceea ce privete parametrii transmii prin stiv, acetia pot fi: valoare, se transmite valoarea parametrului; adres, se transmite adresa parametrului, deci operaiile descrise de procedur se vor efectua direct asupra parametrului respectiv; n acest caz, procedura nu mai trebuie s returneze programului apelant parametrul respectiv. n ceea ce privete returnarea parametrilor, aceast operaie se poate realiza utiliznd una din metodele folosite pentru transmiterea parametrilor ctre procedur, descrise anterior (registre, memorie sau stiv). n general, pentru definirea unei proceduri se parcurg urmtoarele etape: stabilirea prelucrrilor efectuate de procedur; definirea datelor de intrare/ieire, precum i a modului de transmitere a parametrilor (registre, memorie sau stiv); definirea tipului procedurii (NEAR/FAR), mai ales dac parametrii se transmit prin stiv, situaie n care trebuie determinat poziia acestora n stiv; pentru directivele simplificate de segmentare nu este necesar precizarea tipului procedurii, deoarece tipul este determinat de asamblor, din directiva MODEL; dac n procedur se utilizeaz nume simbolice, pentru a obine n mod corect accesul la acestea trebuie salvat DS n stiv, dup care se ncarc noua valoare i se folosete directiva ASSUME pentru a preciza asocierea segmentului la DS, iar la sfrit se reface registrul DS cu valoarea din stiv. nainte de orice prelucrare trebuie salvate n stiv registrele utilizate de procedur, iar nainte de revenirea n programul apelant, acestea trebuie restaurate.

n ceea ce privete programele scrise n limbaje de nivel nalt, acestea folosesc anumite convenii pentru transmiterea parametrilor ctre subprograme. Compilatorul translateaz o instruciune de apel a unui subprogram astfel: depune n stiv (push) argumentele subprogramului i apeleaz apoi subprogramul cu o instruciune de apel (call). n funcie de compilator, argumentele sunt puse n stiv ntr-o anumit ordine. n cazul n care se leag o procedur scris n limbaj de asamblare cu un program scris ntr-un limbaj de nivel nalt, trebuie cunoscut modul de

transmitere a parametrilor i conveniile stabilite de limbajul respectiv pentru apel de subprogram (nume externe, valori returnate). Parametrii pot fi transmii la subprograme prin valoare sau prin referin: la transmiterea prin valoare se va depune n stiv o copie a argumentelor; modificrile efectuate asupra acestor valori nu se vor regsi n parametrii efectivi din procedura apelat. Rezultatele vor fi cunoscute doar dac vor fi comunicate; la transmiterea prin referin, se depune n stiv adresa (pointerul) argumentului (de tip NEAR sau FAR, dup locul n care se afl procedura apelat). n acest caz, modificrile se vor efectua direct asupra argumentelor ce aparin programului apelant. n Pascal i n C se cunosc ambele mecanisme de transmitere a parametrilor. Lim bajele de nivel nalt folosesc urmtoarele registre pentru returnarea de valori ctre programul apelant: (AL) valori de un octet; (AX) valori de doi octei sau adres de tip NEAR; (EAX) valori de 4 octei sau adres de tip NEAR la 386/486; (DX,AX) valori de 4 octei sau pointer FAR, pentru 286; (EDX,EAX) valori de 8 octei sau pointer FAR, pentru 386/486; Pentru valori mai mari de 4 octei, limbajul C consider c valoarea este returnat n zona de memorie alocat pentru segmentul de date i ntoarce n (DX:AX) pointerul ctre acea zon. Limbajul PASCAL rezerv o zon de date n stiv: zona rezervat n stiv i offsetul ctre aceasta se realizeaz de ctre programul apelant; procedura returneaz n (DX:AX) pointerul ctre aceast zon. Descrcarea stivei se face n programul apelant, procedura terminndu-se cu RET; la descrcarea unor argumente, se poate termina cu RET numr_argumentedimensiune. Deci, n principiu, programul apelant realizeaz operaiile: depune argumentele n stiv; apeleaz procedura; descarc stiva. Variabilele locale ntr-o procedur se folosesc pentru a economisi spaiu de memorie (cu meniunea c valorile lor nu se transmit n afara procedurii). Spaiul de memorie necesar pentru variabilele locale se rezerv n stiv i este eliberat la terminarea execuiei procedurii. Alocarea de spaiu pentru variabilele locale se realizeaz cu o secven de forma: Salvare registre de lucru Variabile locale Salvare (BP) Adresa de revenire n program Argumente transmise procedurii unde n = numr de octei alocai. Pentru accesul la variabilele locale se vor utiliza adresri de forma [BP 2], [BP 6] etc. iar pentru argumente, de forma: [ BP + 2 ], [ BP + 4 ], etc. push bp mov bp,sp sub sp,n

Iat un exemplu de adresare la un argument transmis prin stiv i la o variabil local, ntr-o procedur de tip FAR: argument var_loc p1 equ equ proc push mov sub .......... mov add .......... mov pop ret <[bp+6]> <[bp-2]> far bp bp,sp sp,2 ax,argument var_loc,ax sp,bp bp endp ; salvare valoare BP ; initializare cu varful curent al stivei ; rezervare spatiu pentru var_loc, 2 octeti ; se ia argumentul transmis prin stiva ; utilizarea variabilei locale ; eliberarea spatiului rezervat var_loc ; refacerea valorii lui BP ; sau ret 2, daca se descarca stiva in procedura

p1

Dac descrcarea stivei nu se face n procedur, atunci n programul apelant trebuie descrcat stiva cu add sp,2.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

50. Transferul parametrilor pentru proceduri n limbajele de nivel nalt.

Transferul parametrilor pentru proceduri n limbaje de nivel nalt


n cazul limbajului PASCAL, depunerea parametrilor n stiv se face n ordinea n care acetia apar n lista de parametri efectivi, la apelul procedurii (adic ordinea n care au fost specificai parametrii formali la definirea procedurii, deci de la stnga la dreapta). Revenirea din procedur se face cu o instruciune de forma RET n, pentru a descrca stiva, unde n este numrul de octei ocupai de argumentele din stiv. S considerm o procedur definit n PASCAL: procedure begin ...... end; iar apelul de forma: modul (x, y); Pentru aceast procedur se va genera secvena: push bp mov bp,sp ...... mov ax,[bp+8];(AX) x ...... les di,[bp+4] ;(ES):(DI) adresa lui y ...... n final, se va descrca stiva: pop bp ret 6 modul (a : integer; var b : real);

BP salvare BP +2 +4 +6 +8 adresa de revenire adr_off var. b adr_seg var. b valoarea var. a

Pentru apelul acestei proceduri, se va genera secvena urmtoare: mov push mov push push call ax,x ax di,offset y ds di modul

; se depune in stiva valoarea parametrului x ; se depune adresa de segment a parametrului y ; se depune offsetul parametrului y ; apelul procedurii

Spre deosebire de PASCAL, n limbajul C argumentele sunt puse n ordine invers fa de ordinea n care apar n lista de apel (adic de la dreapta la stnga). Adresele de revenire pot fi de tip NEAR, ca n exemplul anterior, sau de tip FAR, n funcie de modul de definire al procedurii.

Pointerii salvai n stiv ca referin de parametru sau ca adres de revenire respect definiia modelului de memorie stabilit n directiva model. De exemplu, aspectul pentru un singur argument este urmtorul: modelul medium push bp mov bp,sp mov di,[bp+6] mov ax,[di] ; acces argument ; tip cuvnt
modelul large

SP, BP salvare bp + 2 adresa revenire - offset adresa revenire - segment + 6 adresa argument

push bp mov bp,sp les di,[bp+6] mov ax,es:[di]; acces argument ; tip cuvnt

SP, BP salvare bp + 2 adresa revenire - offset adresa revenire - segment + 6 adresa argument offset adresa argument segment

Pentru a nu modifica prea multe linii, n funcie de modelul utilizat se pot folosi directivele de asamblare condiionat; de exemplu, pentru cazul anterior se poate defini o constant, astfel: Ptr_FAR equ 1 ........ ........ push bp mov bp,sp ........ ifdef Ptr_FAR les di,[bp+6] mov ax,es:[di] else mov di,[bp+6] mov ax,[di] endif care, dac este definit, va considera modelul large, iar dac nu este definit va considera modelul medium.

Transferul parametrilor pentru subprograme n PASCAL i C


S scriem, pentru exemplificare, un program simplu n Pascal, care citete doi vectori, de aceeai lungime i schimb ntre ei i apoi i afieaz. Vom scrie procedura care schimb ntre ei cei doi vectori n limbaj de asamblare. program schimba_vectori;

type tip_vector = array [1..20] of real; var vector1, vector2 : tipsir; n,i : integer; {$F+} {$L SCHIMB.OBJ} procedure InterSchimb (var v1, v2 : tipsir; lung: word); External; begin { se citesc : dimensiunea si cei doi vectori } InterSchimb (vector1, vector2, sizeof(vector1)); { se afiseaza cei doi vectori dupa interschimbare } end. Directiva de compilare {$F+} Force FAR calls precizeaz c n cadrul codului generat pentru apeluri de proceduri i funcii se folosete modelul FAR (utiliznd acest tip, o procedur poate fi apelat de oriunde din memorie). Dac directiva este dezactivat {$F-}, compilatorul determin automat codul care trebuie generat pentru o instruciune de apel, n funcie de tipul apelului, n interiorul sau n afara segmentului curent. Compilatorul, utiliznd opiunea {$F+}, presupune c rutina se gsete n alt segment, i c orice parametru variabil utilizat de rutin este menionat prin adresele de segment i offset. Directiva {$L nume_fiier} Link object file impune ca pentru un fiier s fie editate legturile mpreun cu programul compilat. Fiierul pentru care se editeaz legturile trebuie s fie n format .OBJ; extensia de nume este implicit. irul de caractere care specific fiierul poate conine i directoarele (calea) de acces ctre fiier. Procedura Interschimb, care se afl n fiierul SCHIMB.OBJ, este urmtoarea: .model TPascal model large,Pascal .code public InterShimb InterSchimb proc far stiva struc val_BP dw IP_rev dw CS_rev dw ? lung dw ? offs_sir1 dw ? seg_sir1 dw ? offs_sir2 dw ? seg_sir2 dw ? stiva ends push bp mov bp, sp ; sau

? ?

; sau adr_rev

dd

; sau adr_sir1 ; sau adr_sir2

dd dd

? ?

push push push push push push mov mov mov mov mov iar: mov xchg mov inc inc loop pop pop pop pop pop pop ret InterSchimb end

ds ; se salveaza registrele de lucru si es di ax cx ; urmeaza initializarile de adrese si contor es, [bp].seg_sir1 ; sau les di, [bp].adr_sir1, sau di, [bp].offs_sir1 ; les di, [bp+8] ds, [bp].seg_sir2 ; sau lds si, [bp].adr_sir2, sau si, [bp].offs_sir2 ; lds si, [bp+12] cx, [bp].lung ; sau mov cx, [bp+6] al, ds:[si] al, es:[di] ds:[si], al si di iar cx ; refacerea registrelor salvate in stiva ax di es si ds 10 ; se descarca stiva de cei 10 octeti endp

Linia de declarare a procedurii poate fi i de forma: InterSchimb proc far Ad_sir1:dword,Ad_sir2:dword,lung:word iar n acest caz, preluarea parametrilor se poate face i mai simplu: les lds mov di,Ad_sir2 si,Ad_sir1 cx,lung

pentru care asamblorul va genera o secven asemntoare celei prezentate n procedur. Modalitatea de definire i utilizare a unei structuri este definit n paragraful urmtor. Vom prezenta n continuare i modul de definire i utilizare a unei funcii n Pascal; funcia prezentat va nsuma elementele unui ir de tip word (integer), fr a lua n considerare eventualul transport; dac dorim, putem s reprezentm rezultatul pe un format dublu (longint), contoriznd n registrul DX eventualele transporturi, iar rezultatul poate fi returnat n perechea DX,AX, n loc de AX.

Vom utiliza i o variabil local, cu toate c n acest caz este inutil, doar pentru a prezenta modul de definire i utilizare a acesteia n programul principal, la fel ca n exemplul anterior. Funcia va fi definit astfel: function Suma (sir: tip_vector; n:word):integer;External; .model large, Pascal public Suma .code Suma proc far adr_sir equ <[bp+8]> n equ <[bp+6]> s equ <[bp-2]> ; variabila locala pentru suma push bp mov bp, sp sub sp, 2 ; rezervare spatiu pentru variabila locala s push ds ; salvarea registrelor de lucru push si push cx lds si, adr_sir ; initializare adresa, contor si suma mov cx, n mov ax, 0 mov s, ax cld ; directia de parcurgere a sirului jcxz gata ; in cazul n care contorul a fost 0, s-a terminat adun: lodsw add s, ax loop adun gata: mov ax, s pop cx pop si pop ds mov sp, bp ; eliberarea spatiului alocat variabilei locale s pop bp ret 6 ; descarcarea stivei de parametri Suma endp end S considerm, acum, i cazul limbajului C. Vom rescrie funcia anterioar, suma(), care va fi apelat din funcia main(). ntruct codul generat de compilatorul C transform denumirile parametrilor funciei suma(), adugnd caracterul _ la nceput, codul modulului apelat cu numele suma() se va numi de fapt _suma(); acelai lucru se ntmpl i pentru ceilali parametri utilizai n ambele module, n sensul c parametrii din C utilizai i n modulul scris n limbaj de asamblare vor fi precedai, n limbaj de asamblare, de caracterul _. Modulul n limbaj de asamblare trebuie s salveze, la nceputul su, i s refac, la sfrit, valorile coninute de registrele BP, SP, CS, DS, SS, DI i SI, dac programul utilizeaz aceste registre.

.model small, C public _suma .code public _suma _suma proc push bp mov bp, sp push cx push ds push si mov cx, [bp+8] lds si, [bp+4] mov ax, 0 ; initializarea sumei cu 0 aduna: add ax, [si] add si, 2 loop aduna pop si pop ds pop cx pop bp ret _suma endp end #include <stdio.h> int suma (int vect[], int dim); void main(void) { int i, dim, vect[100]; printf(Numarul de elemente din vector:); scanf(%d, &dim); printf(Elementele vectorului:\n); for (i=0; i<dim; i++) { printf(vect[%d]=, i+1); scanf(%d, &vect[i]); } printf(Suma elementelor vectorului este: %d\n, suma(vect, dim)); }

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

51. Definirea i utilizarea de proceduri recursive.

Proceduri recursive (reentrante)


O procedur care se apeleaz pe ea nsi (direct sau indirect) se numete procedur recursiv (sau reentrant). Pentru ca apelul s fie corect este necesar ca procedura: s salveze n stiv indicatorii de condiii i registrele utilizate; datele referite s fie n registre sau n stiv, dar nu n memorie; s conin o condiie de oprire a apelului recursiv. Recursivitatea este utilizat cnd fie algoritmul, fie datele sunt descrise recursiv. 1) Procedura citete un ir de caractere (o linie de text) pe care, apoi, le tiprete n ordine invers: proc_scrie_inv proc mov ah, 1 ; citete un caracter int 21h cmp al, 0dh ; se compar cu sfrit de linie jnz citeste ; dac nu e sfrit linie citete caracter ret ; dac e sfrit linie procedura s-a terminat citeste: push ax ; se depune caracterul n stiv call proc_scrie_inv ; se apeleaz recursiv pop ax ; la revenire din apel se ia car. din stiv push dx ; salvare registru folosit pentru tiprire mov dl, al ; caracterul de tiprit se transmite n (DL) mov ah, 2 ; i se tiprete int 21h pop dx ; refacerea registrului ret proc_scrie_inv endp ((SS):(SP)) caracter-ASCII IP_rev_procedur ... caracter-ASCII IP_rev_procedur caracter-ASCII IP_rev_prog_principal Adrese mici

Adrese mari

2a) Procedur pentru calculul recursiv al factorialului. factorial proc ; procedura primete valoarea lui N n registrul AX ; rezultatul va rmne n registrul AX clc ; iniializare (CF=0), la intrarea n procedur, sau ; n prg. principal, nainte de apelul procedurii pushf ; salvare indicatori push dx ; i a registrului (DX), modificat de nmulire push bp mov bp, sp ; iniializare (BP), pentru a lua, la revenire, K-ul cmp ax, 1 ; test de sfrit apel recursiv

je gata_apel push ax ; se depune termenul curent, K, n stiv dec ax ; termenul urmtor din factorial, K-1 call factorial ; apelul recursiv jc poz_cf ; depirea de la apelul anterior se propag mul word ptr [bp-2] ; (AX) * (K-vrf_stiv) = (DX,AX) jnc cont ; dac nu a aprut depire, se continu poz_cf: or word ptr [bp+4], 1 ; poz. (CF=1, imaginea din stiv) cont: add sp, 2 ; descrcarea lui K, din vrful sivei gata_apel: pop bp ; refacerea registrelor salvate pop dx popf ; refacerea indicatorilor ret ; revenire din apel factorial endp Imaginea stivei: bp

bp bp

bp_vechi dx_vechi indicatori adr_rev_proc N-1 ... N bp_vechi dx_vechi indicatori adr_rev_prog_principal

2b) Procedur recursiv de calcul al factorialului, dar valoarea lui N se transmite prin stiv i se returneaz n registrul (AX). fact proc clc ; iniializare (CF=0), la intrarea n procedur sau ; n prog. principal, nainte de apelul procedurii pushf ; salvare indicatori i registre afectate push dx push bp mov bp, sp ; iniializare (BP), pentru a lua, la revenire, K-ul mov ax, [bp+8] ; citete valoarea lui N (K), din stiv cmp ax, 1 ; test sfrit apel recursiv je gata_apel dec ax ; se trece la elementul urmtor, N-1 (K-1) push ax ; se depune acest termen n stiv call fact ; apelul recursiv

jc poz_cf mul word ptr [bp+8] ; rez. nmulirii este n (DX,AX) jnc gata_apel poz_cf: or word ptr [bp+4], 1 ; poz. imaginii din stiv a lui (CF) gata_apel: pop bp ; refacere reg. salvate i a indicatorilor pop dx popf ret 2 fact endp Imaginea stivei pentru aceast procedur este urmtoarea: bp bp_vechi dx_vechi indicatori adr_rev_procedur 1 bp ... N-1 bp bp_vechi dx_vechi indicatori adr_rev_prog_principal N 2c) Procedura recursiv de calcul al factorialului, primete valoarea N prin stiv, i returneaz rezultatul, N!, tot prin stiv. facts proc clc ; iniializare (CF=0), la intrarea n procedur, sau ; n prog. principal, nainte de apelul procedurii pushf ; salvare indicatori push ax ; i registrele de lucru push dx ; afectat de nmulire push bp mov bp, sp ; ini. (BP), pentru a lua, la revenire, K-ul mov ax, [bp+10] ; citete valoarea lui N, din stiv cmp ax, 1 ; test sfrit apel recursiv je gata_apel dec ax ; se trece la elementul urmtor, N-1 push ax ; se depune acest termen n stiv call facts ; apelul recursiv pop ax ; extrage ultim. factorial, calculat, din stiv jc poz_cf mul word ptr [bp+10] ; rezultatul nmulirii, K*f(K-1) jnc gata_apel ; este n (DX,AX)

poz_cf: or word ptr [bp+6], 1 gata_apel: mov [bp+10], ax pop bp pop dx pop ax popf ret facts endp Imagine stiv: bp

; dep. rezultat n stiv

(N 1) <- (N-1)! bp_vechi dx_vechi ax_vechi indicatori adr_revenire_prog_principal N <- N!

3a) Proc. pentru afiarea unei valori din registrul AX n zecimal. conv_bin_zec proc ; procedura primete valoarea de convertit n registrul AX pushf ; se salveaz indicatorii i registrele de lucru push cx push dx mov cx, 10 ; mpritorul, utilizat pentru conversia xor dx, dx ; binar zecimal,(DX,AX) = demprit div cx ; resturile reprezint cifrele n zecimal mov cx, dx ; test condiie de sfrit: ctul i restul sunt 0 ? or cx, ax je gata_apel ; dac ctul i restul sunt 0, nu mai pun n stiv push dx ; depunere rest n stiv call conv_bin_zec ; dac ctul <> 0, apelez recursiv proc. pop dx ; citire rest din stiv add dl, 30h ; conversie la codul ASCII mov ah, 2 ; apel funcie 2, de tiprire caracter int 21h gata_apel: pop dx ; refacerea registrelor de lucru pop cx popf ; refacerea indicatorilor ret conv_bin_zec endp Configuraia stivei pentru acest apel este urmtoarea: adr_rev_procedur sp restul (DX)

dx_vechi cx_vechi indicatori adr_rev_prog_principal

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

52. Programe compuse din mai multe module.

Programe compuse din mai multe module


Este posibil ns s dezvoltm un program care const dintr-un modul principal, legat (editate legturile) mpreun cu unul sau mai multe programe asamblate separat. Motivele organizrii programelor n subprograme sunt urmtoarele: - pentru a face legtura ntre diferite limbaje, pentru a combina uurina programrii n LNI cu eficiena de prelucrare a LA; - pentru a facilita dezvoltarea de proiecte mari, n care diferite echipe elaboreaz separat modulele lor; - pentru a suprapune pri ale unui program pe durata execuiei sale, datorit dimensiunii mari a programului. Programele de dimensiuni mai mari se mpart n mai multe module. Vom denumi modul, un program compus din unul sau mai multe segmente, cuprins ntr-un fiier. Fiecare modul este asamblat separat, genernd propriul su modul obiect. Editorul de legturi realizeaz apoi legarea modulelor obiect ntr-un singur modul executabil. Modulele trebuie s comunice ntre ele. n cazul simbolurilor, definite n cadrul unui modul, ce trebuie referite din alte module, acestea trebuie declarate 'PUBLIC', nmodulul unde sunt definite, i declarate 'EXTRN' : BYTE, WORD, DWORD, FWORD, QWORD, TBYTE - ptr. variabile ABS - pentru constante, NEAR, FAR, PROC - pentru etichete sau proceduri; pentru ultimul tip (PROC) asamblorul determin tipul procedurii. Deci la definire simbolurile se declar 'PUBLIC', iar la referire, din alt modul, se declar 'EXTRN. S considerm un program principal, scris ntr-un modul, care citete (cit_sir) un numr de la tastatur, n zecimal, i-l depune n memorie (sau stiv) sub forma unui ir de caractere ASCII (cel mult 5 cifre sau se va termina cu un caracter diferit de cifr), eventual i lungimea irului (sau este depus n mem. sub forma unui ir ASCIIZ). O alt procedur (conv_binar) va face conversia acestui ir de cifre la un numr binar de 16 bii, i-l returneaz n AX, sau la o locaie din segmentul de date (rezultat). Dup conversie (dac nu apare o eroare), prog. principal, va tipri valoarea n hexa apelnd o tot o proc. (tip_numar). Procedurile vor fi incluse ntr-un modul separat (PROC.ASM) de modulul programului principal (MAIN.ASM). MAIN.ASM .model small .stack 100h .data public numar_ASCII, rezultat, lungime, valoare_hexa public tab_conv tab_conv db '0123456789abcdef' lungime equ 5 numar_ASCII db lungime dup (?) ; rez. pt. coduri ASCII valoare_hexa db 4 dup (?), 0dh, 0ah, '$' ; valoarea hexa rezultat dw ? mes_err db 0dh, 0ah, Eroare de conversie: numar > 65535

CRLF db 0dh, 0ah, $ .code extrn conv_binar: proc, cit_sir: proc, tip_numar: proc start: mov ax, @data mov ds, ax ; iniializare DS call cit_sir ; se citete numrul call conv_binar ; se realizeaz conversia la binar jc tip_mes_err ; mesaj de err, pt. eroare la conversie lea dx, CRLF ; avans la linie noua mov ah, 9 int 21h call tip_numar ; se tiprete numrul n hexazecimal jmp gata_prg ; terminare program tip_mes_err: lea dx, mes_err ; tiprire mesaj de eroare, la conversie mov ah, 9 int 21h gata_prg: mov ax, 4c00h ; revenire DOS int 21h end start PROC.ASM .model small .data extrn numar_ASCII: byte, rezultat : word, lungime : abs extrn valoare_hexa : byte, tab_conv : byte .code public cit_sir, conv_binar, tip_numar ori10 macro ; nmulete cu 10 registrul AX push bx ; se salveaz reg. de lucru shl ax, 1 ;*2 mov bx, ax shl ax, 1 ;*4 shl ax, 1 ;*8 add ax, bx pop bx ; reface registru salvat endm cit_sir proc push ax ; salvare registre de lucru push bx push cx lea bx, numar_ASCII ; adresa unde se depun caracterele mov cx, lungime ; dimensiunea maxim a irului cit:

mov ah, 1 ; citirea unui caracter int 21h mov [bx], al ; se depune caracterul la numar_ASCII inc bx ; actualizarea adresei irului cmp al, '0' ; test dac caracterele sunt cifre jb gata ; dac nu sunt cifre s-a terminat citirea cmp al, '9' ja gata loop cit ; se reia citirea, pt. cel mult 5 cifre gata: pop cx ; refacerea registrelor salvate pop bx pop ax ret cit_sir endp conv_binar proc push si ; salvare registre de lucru push bp push ax push cx lea si, numar_ASCII ; adresa cifrelor ASCII mov cx, lungime ; numr maxim de cifre: 5 cld ; direcia de parcurgere a irului mov bp, 0 ; valoarea convertit/ rezultatul binar reia: mov ah, 0 ; se pune 0 pentru a extinde valoarea n AX lodsb ; se citete o cifr cmp al, '0' ; test de sfrit numr jnb cont_cmp ; daca nu, se continua comp. / conv. clc jmp gata_conv ; dac da, se termin conversia (CF=0) cont_cmp: cmp al, '9' ; test sfrit numr ja gata_conv sub al, '0' ; conversie de la cod ASCII la valoare xchg bp, ax ; (AX) = valoarea ori10 ; se nmulete valoarea cu baza jc gata_conv ; dac apare depire se termin add bp, ax ; se adun ultima cifr citit jc gata_conv ; testarea condiiei de eroare loop reia ; valoarea a rmas n BP (i n AX) gata_conv: ; dac a aprut err CF = 1, altfel CF = 0. mov rezultat, bp ; se depune rezultatul pop cx ; refacerea registrelor salvate pop ax pop bp pop si

ret conv_binar endp tip_numar proc push si ; salvare registre de lucru push ax push cx push bx push dx lea si, valoare_hexa ; adresa unde se depun cifrele hexa mov dx, rezultat ; valoarea de tiprit n hexa mov cx, 4 ; contor numr de cifre de tiprit lea bx, tab_conv ; adresa tabelei de conversie iar: push cx ; salvare contor mov cl, 4 ; contor numr de rotiri rol dx, cl ; se rotesc primii 4 bii pe ultimii 4 mov al, dl and al, 0fh ; se rein doar ultimii patru bii xlat tab_conv ; conversie binar hexa (ASCII) mov [si], al ; depunere la valoare_hexa inc si ; actualizare index pentru depunere pop cx ; contor numr de cifre hexa de tiprit loop iar ; se reia conversia pentru cele 4 cifre lea dx, valoare_hexa ; adresa cifrelor hexa, pentru mov ah, 9 ; tiprire. se utilizeaz funcia int 21h ; 9, din DOS pop dx ; refacerea registrelor salvate pop bx pop cx pop ax pop si ret tip_numar endp end ; sfritul modulului 'PROC.ASM'

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

53. Comunicarea ntre module.

Comunicarea ntre module


Este posibil ns s dezvoltm un program care const dintr-un modul principal, legat (editate legturile) mpreun cu unul sau mai multe programe asamblate separat. Motivele organizrii programelor n subprograme sunt urmtoarele: - pentru a face legtura ntre diferite limbaje, pentru a combina uurina programrii n LNI cu eficiena de prelucrare a LA; - pentru a facilita dezvoltarea de proiecte mari, n care diferite echipe elaboreaz separat modulele lor; - pentru a suprapune pri ale unui program pe durata execuiei sale, datorit dimensiunii mari a programului. Programele de dimensiuni mai mari se mpart n mai multe module. Vom denumi modul, un program compus din unul sau mai multe segmente, cuprins ntr-un fiier. Fiecare modul este asamblat separat, genernd propriul su modul obiect. Editorul de legturi realizeaz apoi legarea modulelor obiect ntr-un singur modul executabil. Modulele trebuie s comunice ntre ele. n cazul simbolurilor, definite n cadrul unui modul, ce trebuie referite din alte module, acestea trebuie declarate 'PUBLIC', nmodulul unde sunt definite, i declarate 'EXTRN' : BYTE, WORD, DWORD, FWORD, QWORD, TBYTE - ptr. variabile ABS - pentru constante, NEAR, FAR, PROC - pentru etichete sau proceduri; pentru ultimul tip (PROC) asamblorul determin tipul procedurii. Deci la definire simbolurile se declar 'PUBLIC', iar la referire, din alt modul, se declar 'EXTRN.

Directivele PUBLIC, EXTRN, GLOBAL, COMM, INCLUDE


n locul directivelor PUBLIC i EXTRN se poate utiliza directiva GLOBAL; ea se substituie directivelor EXTRN i PUBLIC. O alt directiv des utilizat este INCLUDE: PUSH.ASM push ax push bx .... push sp push bp procedura include ..... include ret procedura POP.ASM pop bp pop sp .... pop bx pop ax proc push.asm pop.asm endp

Pentru rezervarea de spaiu de memorie la declararea unor variabile neiniializate (ce fac parte din segmentul BSS), se poate folosi directiva COMM: COMM [ NEAR/FAR ] identificator : tip_element [ : dim ] Atributul NEAR/FAR, dac lipsete se poate determina din modelul de implementare ales, pentru directive simplificate de segmentare, sau se presupune NEAR, pentru directivele complete. Dac aceeai declaraie este n mai multe module, variabila respectiv va fi alocat o singur dat. Utiliznd aceast directiv, nu mai este necesar s se defineasc variabila ca PUBLIC ntr-un modul i EXTRN n cellalt, ntruct atributele asociate de cele dou directive sunt furnizate de .COMM. Directiva va fi plasat n segmentul de date. Atributul tip_element : BYTE, WORD, DWORD, QWORD, i TBYTE, sau un numr ntreg, care specific numrul de octei. Parametrul dim indic numrul de elemente pentru variabil, implicit fiind 1. De exemplu declaraia: COMM FAR VARIABILA : BYTE : 25 definete VARIABILA de 25 de octei.

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

54. Definirea i utilizarea de macroinstruciuni.

Definirea i utilizarea de macroinstruciuni


O macroinstruciune (MI) reprezint o secven de instruciuni creia i se asociaz un nume. Apariia macroinstruciunii n textul programului este nlocuit, automat, de ctre asamblor, cu secvena de instruciuni asociat. Ea poate s fie parametrizat, adic poate fi definit n funcie de o serie de parametrii formali, care sunt actualizai la utilizarea macroinstruciunii, fiind, deci, nlocuii cu parametrii actuali. Diferene ntre MI i procedur: codul obiect al unei proceduri apare o singur dat n program, n schimb codul obiect generat pentru o MI este repetat n program, ori de cte ori apare numele macroinstruciunii. Procedura reduce att dimensiunea programul surs, ct i pe cea a celui obiect, n timp ce MI nu reduce codul obiect, ci doar dimensiunea programului surs. MI nu modific timpul de execuie al programului, pe cnd utilizarea procedurilor crete timpul de execuie. Utilizare macroinstruciunilor: - simplificarea i reducerea secvenelor de cod ce se repet; - reducerea erorilor cauzate de codul repetitiv; - program n limbaj de asamblare mai uor de urmrit. < nume_macro > MACRO [ lista_parametri_formali ] < declaraii/ corpul macroinstruciunii > [;comentarii] ENDM aduna macro t1,t2,suma mov ax, t1 add ax, t2 mov suma, ax endm Utilizarea se poate face astfel: aduna a, b, c mov ax, a add ax, b mov c, ax sau aduna bx,cx,dx mov ax, bx add ax, cx mov dx, ax Dac n definirea unei macro, se utilizeaz etichete, acestea trebuie declarate LOCAL. De exemplu dac dorim s realizm un ciclu, o secven de forma: mov cx, durata_ciclu iar: loop iar va genera erori de multidefinire a etichetei la utilizrile ulterioare. delay macro durata LOCAL iar push cx ;; se salveaz registrul CX mov cx, durata iar: loop iar pop cx endm LOCAL < lista_etichete >

Rolul su este de a declara simbolurile din list ca locale pentru fiecare apel. Directiva se poate utiliza numai n MI, i precede instruciunile din corpul MI. Pentru aceste etichete asamblorul va genera, la expandare, nume de etichete succesive:??0000, ??0001, etc. 1) Calculul puterii ntregi a unui numr ntreg. putere macro numar, exponent local iar, gata push cx ; salvare (CX) i (BX) push bx xor dx, dx ; rezultatul este returnat n (DX, AX) mov ax, 1 ; pregtire rezultat, dac exponentul e 0 mov cx, exponent jcxz gata ; dac CX=0, puterea este 1 mov bx, numar ; nmulitorul n BX iar: mul bx jc gata ; dac apare eroare la *, se poziioneaz CF loop iar gata: pop bx ; refacerea registrelor salvate pop cx endm ; programul ce utilizeaz aceast macro, va testa ; valoarea lui CF, dac este 0 valoare corect n ; (DX,AX), dac ns CF=1, a aprut depire 2) nmulirea unei valori cu 10. ori10 macro x local gata push ax push bx mov ax, x shl ax, 1 ;*2 jc gata mov bx, ax shl ax, 1 ;*4 jc gata shl ax, 1 ;*8 jc gata add ax, bx jc gata ; dup utilizare macro ori10 se va mov x, ax ; testa indicatorul CF pentru a testa gata: pop bx ; o eventual depire pop ax endm

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

55. Macroinstruciuni de repetare.

Macroinstruciunea de repetare
REPT <expresie_contor> < corpul macroinstruciuni > ENDM 1) Alocarea unor valori consecutive la o anumit adres: alocare macro tabela, lungime, vi, pas tabela label byte valoare = vi ; valoare iniial rept lungime valoare = valoare + pas db valoare endm endm Utilizare: alocare tab1, 3, 0, 2 tab1 db alocare tab2, 10, 0, 1 tab2 db

2, 4, 6 1 , . . , 10

2) Generarea alfabetului, pentru litere mari, la o anumit adres. generare_alfabet macro nume nume label byte i=0 rept 26 db 'A' + i i=i+1 endm endm alocare macro tab, dim tab label byte i=0 rept dim if (i gt 255) exitm ;; ieire forat din macro else ;; nainte de execuia tuturor db i ;; instruciunilor secvenei endif i=i+1 endm endm

Macroinstruciuni de repetare condiionat


(Indefinite RePeat) IRP <nume>,<<lista>> < corpul macroinstruciunii > ENDM

<nume>, va fi nlocuit, n corpul MI cu valorile din <lista>. 1) irp endm dw 2) 1, 4, 9, 16, 25 val, <1, 2, 3, 4, 5> dw val*val

suma label byte irp x, <1, 3, 5, 7, 9> db x+x endm suma db 2, 6, 10, 14, 18 irp endm reg, <ax, cx, dx, bx, sp, bp, si, di> push reg

3)

IRPC (Indefinite RePeat Character) - rolul valorilor numerice din IRP este preluat de
caractere. 1) irpc endm 2) Memorarea, la o adres a unei valori n zecimal nempachetat: scrie_val macro adresa, valoare lea si, adresa irpc v, valoare mov byte ptr [si], v inc si endm endm Pentru o utilizare de forma: scrie_val adr1, 1997 se va genera secvena, de cod, care va depune 1, 9, 9, 7, n zec. Dac dorim s depunem o anumit secven de caractere ASCII, se modific doar linia: mov byte ptr [si], '&v' Utilizarea operatorilor &, % i ! Operatorul & este utilizat pentru substituirea simbolurilor, pe care le precede, cu valoarea numeric sau subirul de caractere asociat simbolului respectiv (sau, altfel spus, concateneaz valoarea asociat simbolului), n cazul utilizrii simbolurilor respective ca argumente (parametrii) ale utilizrii unei macroinstruciuni. 1) Declararea unor mesaje, iterative, n cadrul unui program: c, 12345 dw c*c

mesaj macro n msg&n db 'mesaj nr.&n' endm mesaj 5 va genera: msg5 db 'mesaj nr.5' mesaj 11 va genera: msg11 db 'mesaj nr.11 Dac MI are 2 parametri sau mai muli, atunci ea se definete astfel: meserr macro n, o err&n&o db 'eroare &n&&o' endm Utilizarea acestei macro de forma: meserr 2,2 va genera: err22 db 'eroare 22' Dublarea caracterului &, a amnat evaluarea irului &&o, pentru momentul evalurii MI IRP. 2) Compararea reg. AL cu caracterele 'a'..'f', i execuia pentru fiecare dintre ele unei anumite secvene (eticha, etichb, ..., etichf): irpc car, abcdef cmp al, '&car' jz etich&car endm 3) Definirea unei MI pentru rotirea coninutului unei destinaii, cu un numr de bii i o direcie, specificate ca parametrii: rotire macro sens, nr_rot, dest push cx ; salvare CX ; NU salv/reface CX mov cl, nr_rot ; sau rept nr_rot ro&sens dest, cl ; ro&sens dest, 1 pop cx ; refacere CX ; endm endm ; sau ro&sens dest, nr_rot Operatorul % realizeaz conversia simbolului care urmeaz, de la o valoare numeric la un ir de caractere, ce poate fi utilizat pentru a substitui un argument, pentru un apel de MI. Acest operator, de expansiune (%), foreaz evaluarea imediat a expresiei ce urmeaz i convertete rezultatul expresiei la un ir de cifre. mesaj5 macro nume,val db '&nume = &val' endm i declaraia: const1 equ <LOW> pentru a defini mesajul db 'const1 = LOW' se va utiliza MI anterioar, cu urmtorii parametrii:

mesaj5 const1, %const1 Parantezele unghiulare < > se utilizeaz pentru a specifica c textul dintre ele este un singur ir. Aceste paranteze se utilizeaz i cnd se dorete transmiterea unui parametru actual, pentru un apel intern de macro (apelul unei macro n alt macro). Generarea de mesaje multiple, care respect o anumit regul: meserr macro n err&n db 'eroare &n, 0Dh, 0Ah, $' endm diferr macro x m=0 rept x m=m+1 meserr %m endm endm Un apel al acestei macroinstruciuni, de forma: diferr 3 va genera mesajele: err1 db 'eroare 1, 0Dh, 0Ah, $' err2 db 'eroare 2, 0Dh, 0Ah, $' err3 db 'eroare 3, 0Dh, 0Ah, $' Un exemplu de utilizare pentru parantezele unghiulare: mesaj7 macro sir db '&sir',0 ;; definire ir de caractere ASCIIZ endm apelul: mesaj7 <sir caractere> va genera db 'sir caractere',0 Alt operator important pentru macroinstruciuni este operatorul literal, semnul exclamrii (!). Acest simbol comand asamblorului ignore interpretarea caracterului urmtor. Acest simbol poate fi utilizat atunci cnd este nevoie ca unul din urmtoarele caractere s fie inclus ntr-un ir de caractere, ntr-o MI: ! & > % Dac dorim s transmitem ca argument pentru o MI un ir de caractere ce conine i caracterul '>', atunci el va fi precedat de caracterul !, pentru a evita interpretarea lui '>' ca sfrit de ir. mesaj7 <a!>b> care va genera mesajul db 'a>b',0

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

56. Directive de asamblare condiionat.

Directive de asamblare condiionat


Asamblorul permite utilizatorului s realizeze asamblarea doar a unei anumite pri a liniilor care compun modulul surs. n principiu, pot exista dou motive care s necesite o asamblare condiionat: un program general trebuie adaptat pentru o anumit aplicaie, n funcie de parametrii actuali incluzndu-se anumite module, sau dimensionndu-se zone de memorie corespunztor aplicaiei; altfel, prin includerea tuturor modulelor sau prin dimensionarea la maxim a zonelor de memorie, indiferent de aplicaie, se ajunge la dimensionri neeconomice; un alt motiv ar putea fi necesitatea includerii n modulul obiect doar a unora dintre instruciunile prezente n textul surs, datorit unor diferene ntre procesoarele aceleiai familii (286, 386, 486 etc.); dac programul conine instruciuni pentru oricare dintre procesoare, pentru a fi portabil cu maximum de eficien (utilizare de instruciuni specifice unui anumit tip de procesor) fr intervenii n textul surs, aceasta se poate obine prin includerea acestor instruciuni n seciuni controlate de aceste directive de asamblare condiionat. IF [ELSE secventa 2] ENDIF Aceste directive pot fi imbricate. n mod asemntor sunt definite directivele: IFE ; daca expresia este zero, se executa secventa 1 ; altfel se executa secventa 2 IFB argument ; daca argumentul este blanc ( ) se ; executa secventa 1, altfel se executa secventa 2 IFNB <argument> ; adica argumentul <> blanc se executa secventa 1, ; altfel, argument = , executa secventa 2. IFDIF <arg1>,<arg2> ; se compara cele doua argumente caracter cu car ; (senzitiv la tipul literelor: mari si mici), si ; daca sunt diferite executa secv. 1, altfel secv.2 IFDIFI <arg1>,<arg2> ; este asemanatoare cu directiva anterioara, ; cu deosebirea ca ignora tipul literelor. IFIDN <arg1>,<arg2> ; se compara cele doua argumente caracter cu car ; (senzitiv la tipul literelor: mari si mici), si ; daca sunt identice executa secv.1, altfel secv.2 IFIDNI <arg1>,<arg2> ; este asemanatoare cu directiva anterioara, ; cu deosebirea ca ignora tipul literelor. IFDEF <argument> ; daca simbolul prezent ca argument este ; definit executa secv.1, altfel secv.2 IFNDEF <argument> ; daca simbolul prezent ca argument nu ; este definit executa secv.1. expresie conditie secventa 1 ; conditia este o expresie ce poate ; fi evaluata, in momentul asamblarii, ; la o constanta TRUE sau FALSE

Ultimele dou directive se utilizeaz pentru a evita o nou definire a unui simbol, care a fost definit anterior, sau pentru stabilirea variantei de program dorite, ce urmeaz s se asambleze. ntruct asambloarele implic un proces n dou etape, se poate folosi urmtoarea directiv de asamblare condiionat pentru a specifica asamblorului realizarea anumitor operaii numai pe durata primei etape: IF1 secventa; evaluata, numai la prima parcurgere, la asamblare ENDIF Asemntor se definete i directiva IF2, care acioneaz asupra declaraiilor din blocul asociat numai la pasul al doilea al procesului de asamblare. De exemplu, urmtoarea declaraie: IF1 INCLUDE C:\MACRO.LIB ENDIF PURGE putere, scrie_val ; sterge macroinstructiiunile nedorite va permite accesul la biblioteca specificat (MACRO.LIB) numai pe durata primei etape a procesului de asamblare. Directiva anterioar va include toate macroinstruciunile coninute n biblioteca respectiv. Dac ns se dorete includerea numai a anumitor macroinstruciuni, atunci dup directiva anterioar trebuie plasat directiva PURGE urmat de numele macroinstruciunilor din biblioteca respectiv a cror includere nu se dorete. Exemple de utilizare a acestor directive: 1) Macroinstruciune pentru tiprirea unui caracter transmis ca parametru, dar care poate fi apelat fr nici un parametru, pentru afiarea caracterului spaiu. tip_car ifb <car> mov else mov endif mov int endm macro car dl, dl, car ah, 2 21h ; utilizare: tip_car mov mov int tip_car mov mov int x ; genereaza dl, x ah, 2 21h ; va genera dl, ah, 2 21h ; include intreaga biblioteca

2) O macroinstruciune recursiv, care depune registre n stiv; depunerea va nceta cnd n lista registrelor apare caracterul spaiu. push_reg ifnb macro r1, r2, r3 <r1> ; utilizare: push_reg

ax, bx, cx

push r1 push_reg endif endm

r2, r3

push push push

ax bx cx

3) O macroinstruciune ce genereaz diferite instruciuni n funcie de parametrul furnizat. Un utilizator poate s o apeleze cu parametrul B sau W, pentru a preciza dac s genereze instruciunea MOVSB sau MOVSW (implicit se genereaz MOVSB, dac nu se specific parametri). movt macro tip ifdn <tip>,<B> ; utilizare: ifdn B rep movsb ; sau: ifdn W exitm ; sau: ifdn endif ifdn <tip>,<W> rep movsw else rep movsb ; implicit, daca nu are parametru endif endm 4) Evitarea redefinirii unor identificatori sau definirea condiionat: var2 ..... ifdef endif 5) n ultimul exemplu, codul este asamblat condiionat i generat pentru dou procesoare diferite. procesor = 386 ; este iniializat cu 8086 numai pentru acest procesor .... if procesor eq 386 shl ax, 4 ; modific numai AX else ; trebuie s fie procesorul 8086 push cx ; salveaz CX, astfel c i aceast secven mov cl, 4 ; va modifica numai CX, precum shl ax, cl ; secvena anterioar pop cx ; reface CX endif equ var2 var3 2

ifndef var1 var1 endif

equ

equ

Directive pentru generarea condiionat a erorilor


n conjuncie cu directivele de asamblare condiionat, exist un set de directive pentru generarea de mesaje de eroare, n aceleai condiii ca primele. Asamblorul genereaz mesajul de eroare la ntlnirea unei astfel de directive, dac este ndeplinit condiia respectiv. Ele sunt utilizate, cu predilecie, n cadrul MI. .ERR - genereaz mesaj de eroare, de exemplu: if var1 lt var2 .err ; va genera mesaj dac: var1 < var2 endif .ERRE expresie .ERRNZ expresie .ERRB <argument> .ERRNB <argument .ERRDIF <arg1>,<arg2> .ERRDIFI <arg1>,<arg2>

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

57. Elaborarea de programe utiliznd structuri de date (directivele struc i record).

Definirea unei structuri. Directiva STRUC


O structur este o descriere care asociaz un nume i atribute (lungime, tip, etc.) la o colecie de cmpuri, de acelai tip sau de tipuri diferite (echivalent cu RECORD din Pascal sau STRUCT din C). nume_structura STRUC <declaraii i definiri de date> nume_structura ENDS [nume_variabila] nume_structura <[expresie][,exp,.....]> [nume_variabila] nume_structura expr dup (<[expr][,expr,...]>) expresie - evaluat la o constant, valoarea iniial a cmpului; expr. - reprezint numrul de duplicate ale structurii. Exemple de iniializare: <> - asociaz cmpurilor valorile definite iniial, n decl. STRUC; <5> - primul cmp al struc. va fi 5, iar celelalte, nedefinite, se vor asocia valorile definite iniial; <5,15> - se vor iniializa primele dou cmpuri, cu 5 i respectiv 15; <,,7> - cel de-al treilea cmp va lua valoarea 7, iar restul valorile definite iniial; <1,,7> - primul i cel de-al treilea vor primi valorile 1 i respectiv 7, iar celelalte vor primi valorile definite iniial, la declararea structurii. Dac iniial, la definire, nu li s-au asociat valori, cmpurile respective vor lua valoarea 0. Pentru accesul la un cmp al unei structuri se folosete sintaxa: nume_variabila.nume_cmp sau [reg_baza].nume_cmp Tip_persoana struc nume db 20 dup(' ') ; se iniializeaz cu blancuri prenume db 20 dup(' ') varsta db 0 ocupatie db 15 dup(' ') Tip_persana ends p1 Tip_persoana <'Ionescu','Ilie',63,'inginer'> p2 Tip-persoana <> ; copie a valorilor iniiale p3 Tip_persoana <,,21,'student'> ; iniializare vrst i ocupaie grupa Tip_persoana 25 dup(<,,20,'student'>)

Definirea unei nregistrri. Directiva RECORD


nregistrarea permite definirea de bii individuali sau grupuri de bii, dintr-un octet sau cuvnt. Fiecare bit sau grup de bii este denumit cmp. La aceste cmpuri ne putem referi prin numele simbolice asociate. nume_nregistrare RECORD nume_cmp : expr [=expr'][,. . .] expr = numrul de bii alocai cmpului respectiv; expr' = aceast clauz este opional i reprezint valoarea iniial asociat cmpului respectiv; dac nu se specific, va fi implicit, egal cu 0. Suma valorilor expresiilor pentru numrul de bii (expr) trebuie s fie o constant ntreag, i dac este <= 8, rezult c s-a definit o nregistrare de tip octet, dac este > 8 i <=16, rezult c s-a definit o nregistrare de tip cuvnt, etc. Dac sunt definii mai puini bii dect

dimensiunea unui octet (cuvnt, etc.), atunci cmpurile sunt aliniate la dreapta n cadrul tipului respectiv. model_rec record X:3=7, Y:4=8, Z:9=257 pentru aceast declaraie se va genera un cuvnt: 111.1000.100000001. declaraia acestui tip de date poate fi folosit pentru alocare: inregistrari model_rec 100 dup (<,15,3>) n urma acestei declaraii se aloc, ncepnd de la adresa inregistrari, 100 de cuvinte, ale cror cmpuri (X, Y, Z) vor avea valorile: X = 111, pstreaz valoarea de la definire, Y = 1111, iniializat la alocare, Z = 000000011, iniializat la alocare. Pentru astfel de date sunt definii doi operatori: MASK nume_cmp - furnizeaz o masc de bii pentru cmpul respectiv (biii cmpului respectiv sunt 1, iar toi ceilali 0); WIDTH nume_cmp - furnizeaz o constant ntreag egal cu numrul de bii ai cmpului respectiv, sau se poate specifica numele nregistrrii i va furniza numrul de bii al acesteia. Pentru o referire direct la numele cmpului, ntr-o instruciune, asamblorul va genera o valoare ntreag ce reprezint poziia n cadrul octetului (sau cuvntului, etc.). Cu alte cuvinte, reprezint numrul de deplasri la dreapta, necesare pentru a aduce cmpul respectiv n biii cei mai puin semnificativi ai nregistrrii respective. Exemple de utilizare: 1) mov dx, inregistrari [40] ; (DX) = al 21-lea cuvnt and dx, mask Y ; (DX) = 000.11111.000000000 mov cl, Y ; (CL) = 9 shr dx, cl ; se deplaseaz cmpul Y la dreapta mov ax, model <1,7,127> ; (AX) = 001.00111.001111111. dim_X equ width X ; dim_X = 3 dim_model equ width model ; dim_model = 16 2) Selectarea, dintre angajaii unei firme, a brbailor cu o vechime mai mare de cinci ani, necstorii: date_angajat record vechime:6, sex:1, stare:1 tip_angajat struc nume db 20 dup(' ') prenume db 20 dup(' ') date date_angajat < > tip_angajat ends nr_ang equ 100 angajat tip_angajat nr_ang dup (< >) ; ............ mov cx,nr_ang lea bx,angajat iar: mov al, [bx].date test al, mask sex ; 0 = femeie, 1 = brbat jz respins

test al, mask stare jz respins mov cl, vechime shr al, cl cmp al, 5 jb respins;

; 0 = cstorit, 1 = necstorit ; (AL) =0,0,vechime(6 bii) ; testare vechime mai mare de 5 ani ; cel selectat este referit de (BX) ; . . . . afiare: nume & prenume

respins: add bx, size tip_angajat loop iar ....

; se trece la urmtorul angajat

Platform de e-learning i curricul e-content pentru nvmntul superior tehnic

Programare n limbaj de asamblare

58. Programe rezidente (TSR). Instalarea, activarea i dezinstalarea acestor programe.

Programe rezidente n memorie (TSR)


TSR este prescurtarea de la Terminate and Stay Resident. Deci, este vorba despre programe care rmn n memoria RAM dup ce s-a terminat execuia lor. Aceste programe pot fi invocate fie utiliznd anumite taste, fie de ctre alte programe, care lanseaz o ntrerupere software adecvat. De obicei aceste programe sunt de tip .COM. S considerm ce s-ar ntmpla dac, n timp ce un program ruleaz, el ar fi copiat adresa sa top of memory n pointerul special, ce memoreaz locaia de memorie unde DOS ncarc programele pentru execuie. n acest caz, DOS va fi pclit prin ncrcarea fiecrui program ulterior n zona de memorie situat imediat deasupra programului original. n consecin, programul original ar rmne n memorie pe durata executrii tuturor programelor ulterioare. Exact la fel se ntmpl ntr-un program TSR. Acesta nlocuiete pointerul de nceput al programului cu pointerul top of memory. Fiecare program executat dup acest program TSR este ncrcat n zona de memorie superioar acestuia i deci nu se suprapune peste memoria utilizat de programul TSR. Cnd se ncarc mai multe programe rezidente, fiecare dintre ele utilizeaz aceast tehnic. Un program TSR conine dou pri: o parte de iniializare (tranzitorie) i o parte rezident. Partea tranzitorie este responsabil de ncrcarea prii rezidente n memoria RAM i de instalare a unei rutine de ntrerupere care s determine cum este invocat (apelat) programul TSR. Dac programul TSR este invocat de o ntrerupere software, poriunea plaseaz adresa prii rezidente a codului n vectorul de ntrerupere corespunztor. Dac TSR-ul va fi invocat printr-o tast (hotkey) poriunea de iniializare trebuie s modifice manipularea ntreruperilor DOS, pentru tastatur (de fapt pentru tasta respectiv). Cnd poriunea tranzitorie este executat, la sfritul acesteia ea invoc o funcie DOS care permite ca o poriune din fiierul executabil s rmn rezident n memoria RAM dup ncheierea execuiei acestuia, de unde i expresia Termin i Stai Rezident. Poriunea de iniializare a TSR-ului cunoate dimensiunea poriunii rezidente, precum i locaia n memorie a poriunii rezidente, i transmite aceast informaie sistemului DOS. Ulterior, DOS nu va afecta blocul de memorie specificat, dar este liber s ncarce programe n zona de memorie neprotejat. Deoarece sistemul de operare DOS este un sistem monoacces, monoprogramare i nereentrant, apar o serie de restricii si limitri privind operaiile ce pot fi efectuate de codul rezident al programelor din aceast categorie. De aceea este necesar s cunoatem structura sistemului de operare, anumite module care afecteaz un program rezident, precum i modul de lucru al unor dispozitive (ca de exemplu tastatura). Programele TSR pot fi de dou tipuri, dup modul de activare: active i pasive. Un program TSR pasiv se execut ca parte normal a fluxului unui program; el este executat n urma unui apel explicit dintr-o alt aplicaie. TSR-urile pasive sunt aproape ntotdeauna rutine de servire a ntreruperii sau extind apeluri DOS sau BIOS. Un program TSR activ este executat constant, la anumite intervale de timp, sau la apsarea unei anumite combinaii de taste care nu are semnificaie pentru aplicaia curent. Un program TSR activ, de obicei, va suspenda execuia programului curent. TSR-urile active ndeplinesc una din dou funcii: fie ndeplinesc direct o ntrerupere hardware, fie sunt activate periodic, fr un apel explicit de la o aplicaie. Un TSR poate conine att componente active, ct i componente pasive. Astfel, anumite rutine pot fi activate de o ntrerupere hardware, iar altele s fie apelate explicit de alte aplicaii. Urmtorul program este un exemplu de TSR care furnizeaz att o rutin activ (MyInt9h), ct i una pasiv (MyInt16h). Programul utilizeaz vectorii de ntrerupere ai tastaturii:

09h i 16h. De cte ori apare o ntrerupere pentru tastatur, rutina MyInt9h, activ pe acest nivel (INT 09h), va incrementa un contor. Deoarece tastatura genereaz, de obicei, dou ntreruperi la o tastare (una la apsarea i alta la revenirea tastei), valoarea va fi mprit la 2, pentru a aproxima numrul de apsri ale tastelor. Rutina pasiv pe nivelul 16h, MyInt16h, returneaz numrul de apsri ale tastelor ctre programul apelant. Codul urmtor furnizeaz cele dou programe, TSR-ul (tsr_tast.asm) i aplicaia (tsr_tapl.asm) care afieaz numrul de taste apsate de cnd s-a lansat TSR-ul. .model tiny ; tsr_tast.asm - TSR activ, numr ntr. tastatur, dup activare ; pt. a det. nr. de taste apsate ntre dou apeluri succesive ; prog. permite i dezinstalarea lui, la cererea utilizatorului ; Se va genera program de tipul .COM: tlink/t tsr_tast .code org 100h start: jmp test_Instalare ID_tsr db 'TSR_numara_taste_apasate_INT_9h_&_16h' lung_ID equ $-ID_tsr KeyCont dw 0 ; contor ntreruperi de la tastatur OldInt9h dd ? ; salvarea vechilor vectori de ntrerupere OldInt16h dd ? MyInt9h proc far ; comp. activa, rutina de ntr. tastatur, apelat de sistem la ; fiecare apsare de tast, incrementeaz contorul KeyCont, i ; transfer controlul la ntreruperea original, Int 9. inc cs:KeyCont ; incr. contor de ntreruperi tastatur jmp cs:OldInt9h ; apelul vechii ntr., salvat la OldInt9h MyInt9h endp MyInt16h proc far ; componenta pasiv a TSR-ului apelat prin apelul INT 16h. ; Dac registrul AH=0FFh, ntoarce nr-ul de ntreruperi ; de la tastatur, n AX. Dac AH conine alt valoare, atunci ; rutina transmite controlul la ntreruperea original INT 16h. cmp ah, 0FFh ; se solicit valoarea contorului ? je ReturnCont ; dac da, se returneaz valoarea lui jmp cs:OldInt16h ; altfel apeleaz ntreruperea original ReturnCont: mov ax, cs:KeyCont mov cs:KeyCont, 0 ; reiniializare contor la fiecare apel iret MyInt16h endp test_Instalare: push es ; salvare ES, DS push ds push cs pop ds ; init. DS cu CS, i poate lipsi la .COM

mov ax, 0 mov es, ax ; init. ES cu adr. Seg. a TVI (0000H) ; se verific dac nu este deja instalat acest TSR: ; se verific dac au fost instalate cele dou ntreruperi n TVI mov ax, es:[9h*4] ; se comp. offseturile pt. vectorii din tabel cmp ax, offset MyInt9h ; dac nu sunt gsii cei doi vectori jne inst ; se vor instala mov ax, es:[16h*4] cmp ax, offset MyInt16h jne inst ; aici se tie c sunt instalai 2 noi vectori de ntrerupere ; pe nivelurile 9h i 16h, cu offseturile noastre, dar pt a fi siguri ; c sunt chiar acetia vom comp. i id. TSR-ului curent ; cu cel din memorie (din TVI) mov ax, es:[9h*4+2] mov es, ax mov si, offset cs: ID_tsr ; se compar identificatorii mov di, si ; offset celor dou nume_TSR n SI/DI mov cx, lung_ID ; lungimea numelui vectorului nou cld ; direcia de parcurgere, cresctoare repe cmpsb ; se compar cele doua nume jnz inst ; nume diferite -> se instaleaz lea dx, mes_inst ; afiare mesaj program deja instalat mov ah, 9 ; i solicitare utilizator pentru dezinstalare int 21h mov ah, 1 int 21h ; cit. rsp. utilizator, dac dorete dezinst push ax ; salvare rspuns mov ah, 9 ; avans pe linie nou pe ecran lea dx, CRLF int 21h pop ax ; refacere rspuns utilizator and al, 0DFH ; se transform caracterul n liter mare cmp al, 'D' ; se compar cu caracterul 'D' je dezinst ; daca este 'D' se va dezinstala programul pop es ; refacere ES, DS pop ds mov ax, 4c00h ; dac nu, revine n DOS, fr instalarea int 21h ; codului, care este deja instalat (rezident) dezinst: xor ax, ax ; se refac vectorii iniiali salvai n codul mov ds, ax ; rezident; se pun n TVI (adr. seg. 0) mov es, ds:[9*4+2] ; ES = adr. seg. prg. TSR, ncrcat ant., mov ax, word ptr es:[OldInt9h] ; difer de cel actual (TVI) mov ds:[9*4], ax ; reface vectorul 9: offsetul mov ax, word ptr es:[OldInt9h+2]

mov ds:[9*4+2], ax ; i adresa de segment mov ax, word ptr es:[OldInt16h] ; reface vectorul 16h: mov ds:[16h*4], ax ; offsetul mov ax, word ptr es:[OldInt16h+2] mov ds:[16h*4+2], ax ; i adresa de segment pop ds ; refacere ES, DS pop es push cs ; dezinstalarea se face complet, cu pop es ; eliberarea spaiului de memorie mov ah, 49h ; alocat programului TSR int 21h push cs pop ds lea dx, mes_dezi ; afiare mesaj 'Program Dezinstalat' mov ah, 9 int 21h mov ax, 4C00h int 21h ; se memoreaz vechile valori pentru ntr. INT 9 i INT 16 ; direct n variabilele OldInt9h, i respectiv OldInt16h inst: cli ; dezactivare ntreruperi ; seciune critic: modificare vect. ntr. mov ax, es:[9*4] ; citire offset rutin pentru Int 9h i mov word ptr OldInt9h, ax ; salvare la OldInt9h mov ax, es:[9*4 + 2] ; cit. Seg. rutin pentru Int9h i mov word ptr OldInt9h[2], ax ; salvare la OldInt9h+2 mov word ptr es:[9*4], offset MyInt9h ; nlocuire vector mov word ptr es:[9*4+2], cs ; vechi cu cel nou mov ax, es:[16h*4] ; aceleai operaii pentru Int 16h mov word ptr OldInt16h, ax mov ax, es:[16h*4 + 2] mov word ptr OldInt16h[2], ax mov word ptr es:[16h*4], offset MyInt16h mov word ptr es:[16h*4+2], cs sti ; reactivare ntreruperi ; se termin partea de instalare cu lsarea rezident a codului mov ah, 9 ; tiprire mesaj de instalare cod TSR lea dx, mesaj int 21h pop ds ; refacere DS, ES pop es mov dx, offset test_instalare + 15 ; calcul spaiul de memorie push cx ; salvare CX mov cl, 4 ; ocupat de codul rezident, ca nr paragrafe shr dx, cl

pop cx ; refacere CX mov ax, 3100h ; apeleaz funcia ce las rezident codul int 21h ; din seg. curent, pn la 'test_instalare mesaj db 'S-a instalat programul ce numara ''Numarul de taste'' apasate.' CRLF db 0Dh, 0Ah, '$' mes_inst db 'Programul este deja instalat in memorie!!!', 0Dh, 0Ah db 'Doriti dezinstalarea lui (D/d-DA, orice alta tasta pentru NU): $' mes_dezi db 'Programul a fost dezinstalat !!!', 0Dh, 0Ah, '$' end start Pe lng problemele legate de apeluri reentrante ale TSR-ului ctre DOS/ BIOS, se poate ca apelurile DOS ale TSR-ului s afecteze structuri de date utilizate de alte aplicaii curente: stiva aplicaiei, zona DTA, etc. Cnd se execut un TSR el opereaz n contextul (mediul de lucru) al aplicaiei principale. De ex., adresa returnat de TSR i orice valori, pe care TSR -ul le salveaz pe stiv, sunt puse pe stiva aplicaiei. Dac TSR folosete intens stiva, datorit unor apeluri recursive, sau alocrii de spaiu pe stiv pentru variabile locale, atunci TSR-ul trebuie s salveze stiva aplicaiei (adic SS i SP) i s comute pe o stiv local (proprie). Dac TSR-ul execut apelul funciei DOS ce returneaz adresa PSP, se va returna adresa PSP-ului aplicaiei principale, i nu cel al TSR-ului. Dac nu se comut de la PSP-ul aplicaiei principale la cel al TSR-ului, i apare o excepie (manipulare disc, sau ctrl-break), atunci se va executa manipulatorul asociat cu aplicaia principal (n locul celui asociat TSR-ului). De aceea, cnd se execut un apel DOS, care poate rezulta ntr-una din acele condiii, trebuie comutat PSPul. Astfel cnd TSR-ul returneaz controlul la aplicaia principal, trebuie refcut PSP -ul. Funcia 50h iniializeaz adresa PSP a programului curent la valoarea din registrul BX, iar funcia 51h determin adresa PSP a programului curent i o returneaz n registrul BX.

Componentele unui program TSR


Programele TSR utilizeaz, dup cum am artat, n general, ntreruperile de la tastatur sau de la ceasul de timp real; ele nu trebuie s interfereze cu ntreruperile hardware care aparin de domeniul driverelor de dispozitiv, excepie fcnd ntreruperile de la tastatur i de la circuitul de ceas. Circuitul de ceas genereaz ntreruperi hardware la fiecare 1/18,2 secunde (acest interval este dat de faptul c, pe durata unei ore, un registru contor ajunge la valoarea maxim 65535); aceste ntreruperi periodice permit actualizarea orei sistemului. Pentru ceasul de timp real exist doi vectori de ntrerupere, i anume 08h, respectiv 1Ch. ntreruperea de pe nivelul 08h, INT 08h, actualizeaz ora i data sistemului, dup care execut instruciunea INT 1Ch; aceast rutin const dintr-o singur instruciune IRET, tocmai pentru a permite utilizatorului s-i insereze aici rutina de tratare a ntreruperii, i nu pe nivelul 08h, tocmai pentru a nu afecta actualizrile de sistem. ntreruperile de la tastatur, generate att la apsarea unei taste, ct i la eliberarea ei, au fost descrise anterior. ntreruperea de la tastatur se afl pe nivelul 09h, INT 09h; aceast rutin de tratare a ntreruperii citete codul generat de tastatur i n funcie de starea tastelor de tip shift (CTRL, SHIFT, ALT)- memorat ntr-un octet de stare la adresa 40h:17h- genereaz

codul tastei apsate respective. De asemenea, aceast procedur verific i anumite combinaii de taste cu semnificaie deosebit, cum ar fi: CTRL-ALT-DEL (reiniializare), CTRL-BREAK (suspendare), pentru care se execut instruciunile INT 19h, respectiv INT 1Bh. Caracterele de la tastatur sunt depuse ntr-un buffer circular, de 16 cuvinte; bufferul tastaturii se afl la adresa 40h:1Ah i conine un pointer (deplasament) pentru extragere, un pointer (tot de tip cuvnt) pentru introducere i zona de 16 cuvinte unde se depun codurile tastelor. Aplicaiile utilizator vor folosi instruciunea INT 16h pentru accesul la bufferul tastaturii, care permite citirea caracterelor din buffer i verificarea strii tastaturii. Componenta mai simpl a unui program rezident este tocmai cea de iniializare, care l las rezident. n locul terminrii normale, ca pn acum, a programului cu funcia 4Ch, INT 21h, programul se va termina cu funcia 31h, cea care pstreaz programul n memorie. Cnd se va executa rutina de iniializare, sistemul va rezerva blocul de memorie unde este rezident programul i va ncrca programele urmtoare n memoria rmas disponibil dup programul rezident. Componenta mai delicat din elaborarea unui program rezident este cea care realizeaz activarea programului dup ce acesta a devenit rezident, deoarece nu este un program intern, de sistem, cum sunt de exemplu CLS, COPY, DIR etc. Metoda cea mai utilizat pentru activare este cea de modificare a tabelei vectorilor de ntrerupere, astfel nct programul rezident ntrerupe toate tastrile, acionnd la o anumit tast sau combinaie de taste. Partea rezident conine: una sau mai multe proceduri, dintre care una este noua rutin de tratare a ntreruperii (RTI), care apeleaz i vechea ntrerupere; la apariia unei ntreruperi corespunztoare acestei ntreruperi, se va activa RTI din partea rezident. o zon de date, care conine i spaiul alocat n care se salveaz vectorii de ntrerupere ce sunt modificai de programul rezident. Un program rezident obinuit const din urmtoarele componente: 1. O component care redefinete locaiile din tabela vectorilor de ntrerupere, adic instalarea unui nou vector de ntrerupere. 2. O component de iniializare, care se execut doar la prima rulare a programului i care realizeaz: nlocuirea adresei din vectorul de ntrerupere cu propria sa adres (a codului rezident); determin dimensiunea prii rezidente a programului (la nivel de paragrafe, 16 octei); utilizeaz o ntrerupere (31h) care specific sistemului s termine execuia programului curent i s lase rezident n memorie poriunea specificat de program. 3. Componenta (procedura) care rmne rezident i care va fi activat fie printr-o combinaie specific de taste, fie de ceasul de timp real al sistemului. Ca efect, rutina de iniializare stabilete toate condiiile pentru a lsa rezident programul i apoi permite ca ea nsi s fie tears. Organizarea memoriei, acum, apare astfel:

Memoria disponibil Poriunea de iniializare a programului TSR (peste care se poate suprapune urmtorul program) Programul rezident (TSR) COMMAND.COM IO.SYS i MSDOS.SYS Tabela vectorilor de ntrerupere Un program rezident poate utiliza dou funcii DOS, INT 21h, 35h i respectiv 25h, pentru accesul la tabela vectorilor de ntreruperi, deoarece nu exist nici o garanie c adresa acestei tabele va ncepe ntotdeauna de la adresa 0000H. Aceste funcii primesc ca parametru nivelul ntreruperii pe care se dorete instalarea activrii codului rezident sau salvarea vechiului vector, deci nu trebuie cunoscut adresa fizic a acestuia.

Instalarea unui nou vector de ntrerupere


Partea de instalare a unui program TSR trebuie s realizeze urmtoarele operaii: s verifice, n primul rnd, dac nu cumva a fost deja instalat n memorie codul su rezident; dac programul a fost deja instalat, nu l va mai instala i programul se va termina cu funcia 4C00h, INT 21h. s captureze un vector de ntrerupere pe care l nlocuiete cu unul nou. nainte de a modifica vectorul de ntrerupere, programul rezident (cel ce se instaleaz), salveaz n partea sa de iniializare vectorul curent i apoi l nscrie pe cel nou, care reprezint adresa, de tip FAR a procedurii, pentru tratarea ntreruperii definite n partea rezident; s calculeze dimensiunea memoriei necesare pentru codul rezident i s apeleze funcia DOS 31h, care las codul prii rezidente n memorie i termin programul. Prin capturarea unui vector de ntrerupere se nelege nlocuirea vectorului existent, cu unul nou, care conine adresa noii rutine de tratare a ntreruperii, definit n programul TSR. De obicei, noua rutin apeleaz vechea rutin de tratare a ntreruperii. nlocuirea unui vector de ntrerupere, care const n salvarea celui vechi i nscrierea unuia nou, se poate implementa direct de utilizator, utiliznd instruciuni de transfer (mov), dar este mult mai comod utilizarea funciilor DOS (INT 21h) 35h i 25h. Funcia DOS 35h returneaz n ES:BX vechiul vector de ntrerupere, cel care se dorete a fi nlocuit, al crui numr a fost transmis n registrul AL, astfel: mov ah, 35h ; funcia DOS de salvare a vechiului vector mov al, nr_int ; nr. ntr. pe nivelul creia se pune TSR-ul int 21h mov Vechea_Int, bx ; salv. vechiului vector de ntrerupere mov Vechea_Int[2], es ; din ES:BX, n zona TSR-rezident

Funcia 25h scrie noul vector de ntrerupere, transmis n registrele DS:DX, n tabela vectorilor de ntrerupere, n locul vectorului al crui numr (index din tabel) este specificat n registrul AL: mov ah, 25h ; funcia DOS de instalare a noului vector mov al, nr_int ; nr. ntr. pe nivelul creia se pune TSR-ul lea dx, Noua_Int; offsetul RTI, adr. seg. este n DS, ntruct ; toate reg. seg., la programele .COM ; sunt iniializate cu segmentul PSP int 21h ; deci nu mai trebuie reiniializat cu ;seg Noua_Int Ca efect, la apariia unei ntreruperi pe nivelul specificat n AL, se va executa noua procedur rezident (TSR), n locul celei vechi. Salvarea vechiului vector i instalarea celui nou se poate face i fr funciile DOS, direct n tabela vectorilor de ntrerupere (TVI); secvena aceasta trebuie ns executat cu ntreruperile dezactivate. Pentru a evita reinstalarea aceluiai program TSR, se verific dac exist deja o copie n memorie a codului rezident, deci dac acesta a fost deja instalat, prin compararea offset-ului noii rutine cu offset-ul vectorului de ntrerupere utilizat. n cazul n care cele dou offset-uri sunt diferite, nseamn c programul nu este rezident i, deci, poate fi instalat. Dac, ns, cele dou offseturi sunt identice, ntruct se poate ntmpla ca programe diferite s utilizeze acelai vector de ntrerupere i s aib acelai offset, se vor compara identificatorii celor dou programe TSR. Dou TSR-uri diferite pot avea acelai offset al adresei de lansare dac zona de date ce precede nceputul codului TSR are aceeai dimensiune. Din acest motiv trebuie nscris n codul rezident un ir de caractere care s identifice n mod unic acel program; acest identificator de program TSR se plaseaz naintea programului TSR propriu-zis. Pentru a lsa rezident n memorie numai partea rezident a programului TSR se va utiliza funcia 31h, care are ca parametru de intrare dimensiunea de memorie ocupat de partea rezident, exprimat n paragrafe (1 paragraf = 16 octei), transmis n registrul DX (adresa de segment este cea coninut n DS, care are acelai coninut cu toate celelalte registre segment n cazul programelor .COM). Funcia va lsa rezident n memorie codul de lungime specificat i realizeaz ieirea din program, n DOS. Memoria ocupat de partea de iniializare a programului va fi eliberat de DOS. Deci un program TSR are urmtoarea structur: cod_TSR segment ; partea rezident assume cs: cod_TSR org 100H intrare: jmp start_init ; exe. la prima intrare nume_TSR db 'prog_TSR_1' ; ID cod rezident lung_nume equ $ - nume_TSR ; lungime ID vect_vechi dd ? ; spaiu pt salvarea vechiului vector nr_vect equ ... ; vectorul pe care se instaleaz TSR ; definirea noii proceduri de tratare a ntreruperii vect_nou proc far ; noua proc. poate apela i vechea p. push resurse ; salv. resurse utilizate de TSR

......... ; noile prelucrri, descrise de noua ......... ; procedur de tratare a ntreruperii pop resurse ; refacerea resurselor utiliz. de TSR jmp cs: vect_vechi ; vechea ntr., fie cu salt fie ca apel: ; pushf ; apel de tip ntrerupere pentru vechea ; call cs:vect_vechi ; procedur de tratare ntrerupere ; iret ; revenire n programul ntrerupt vect_nou endp ; partea de iniializare a codului rezident start_init: mov al, nr_vect ; numrul vechiului vector de ntrerupere, mov ah, 35h ; cel nlocuit. Salvare vector vechi. int 21h ; (ES:BX) = vect vechi. Comp. offseturile cmp bx, offset vect_nou ; celor doi vectori: vechi nou jnz instalare ; Este deja rezident ? Dac nu, se instaleaz mov si, offset cs: nume_TSR ; Se compar identificatorii mov di, si ; offseturile celor dou nume_TSR n SI/DI mov ax, cs ; adresa de segment pentru numele noului mov ds, ax ; vector mov cx, lung_nume ; lungimea numelui vectorului nou cld ; direcia de parcurgere, cresctoare repe cmpsb ; se compar cele dou nume jnz instalare ; nume diferite -> se instaleaz lea dx, mes_deja_inst ; afiare: Program deja instalat mov ah, 9 int 21h ; aici se poate insera secvena de dezinstalare a TSR-ului ; se ntreab utilizatorul dac dorete dezinstalare: lea dx, mes_dezinst mov ah, 9 int 21h mov ah, 1 ; citire rspuns utilizator int 21h cmp al, D ; dac nu este DA se termin fr dezinst. jnz iesire xor ax, ax ; se reface vectorul din TVI, vect_vechi mov ds, ax ; n codul rezident; se pun n TVI (seg. 0) cli mov es, ds:[nr_int*4+2] ; ES=adr. seg. TSR, deja ncrcat, mov ax, word ptr es:vect_vechi ; care difer de cea actual, mov ds:[nr_int*4], ax ; (se reface n TVI) reface vectorul mov ax, word ptr es:vect_vechi[2] ; nr_int: offsetul mov ds:[nr_int*4+2], ax ; i adresa de segment sti push cs ; dezinstalarea se face complet, cu pop es ; eliberarea spaiului de memorie

mov ah, 49h ; alocat programului TSR int 21h push cs pop ds lea dx, mes_dezi ; afiare mesaj 'Program Dezinstalat' mov ah, 9 int 21h iesire: mov ax, 4c00h int 21h instalare: cli ; dezactivare sistem ntreruperi (INTR) mov word ptr vect_vechi, bx ; se salveaz vechiul mov word ptr vect_vechi[2], es ; vector mov ah, 25h ; funcia DOS de instalare a noului mov al, nr_vect ; vector lea dx, vect_nou ; DS a fost iniializat anterior int 21h ; secvena care las codul vect_nou rezident ; 'start_init' - eticheta de nceput a prii de iniializare, ; reprezint i eticheta de sfrit a codului rezident lea dx, start_init ; adr. de sfrit a prii rezidente, care este add dx, 15 ; rotunjit la paragraful urmtor mov cl, 4 ; pentru a determina shr dx, cl ; dimensiunea n paragrafe mov ah, 31h ; funcia DOS, care l las rezident sti ; reactivare sistem de ntreruperi int 21h mes_deja_inst db 0Ah, 0Dh, TSR-ul este deja instalat !!! db 0Ah, 0Dh, $ mes_dezinst db Doriti dezinstalare (D pentru DA, orice db alta tasta pentru NU): $ mes_dezi db 0Dh, 0Ah, 'Programul a fost dezinstalat !!!' db 0Dh, 0Ah, '$' cod_TSR ends end intrare 'nr_vect' este numrul vectorului de ntrerupere ce se nlocuiete, de exemplu 1Ch vectorul ceasului de timp real, sau 09h pentru tastatur. Partea de iniializare nu va rmne n memorie, ci numai codul rezident (vect_nou), primele (DX) paragrafe, pn la eticheta 'start_init'. Spaiul de memorie ocupat de partea de iniializare a programului TSR, va fi eliberat de DOS. ; se revine n DOS, fr instalarea ; codului, care este deja rezident

Partea rezident a programului TSR


Partea rezident definete o zon de date i prelucrrile respective, reprezentate de una sau mai multe proceduri. Procedurile dintr-un program rezident devin active ca rspuns la un apel direct al unui alt program sau la apariia unei ntreruperi hardware. Dup lansare un lucru nu poate fi ateptat pentru codul apelant: s iniializeze corespunztor registrele segment. Singurul registru segment cu semnificaie pentru codul rezident este registrul CS. Pentru acces la variabilele locale -> rutinele vor iniializa DS sau alte registre segment. De ex. o rutin care numr de cte ori alte programe o apeleaz, dup ce a devenit rezident. Ea ar conine o singur instruciune inc contor, dar s-ar incrementa variabila de la offsetul contor n segmentul referit de DS, i deci nu va incrementa variabila contor. Dou soluii la aceast problem: 1. toate variabilele n segmentul de cod, i s se utilizeze prefixul segment (inc cs:contor); utilizat doar cnd avem puine variabile. 2. salvare registrul segment de date, DS, la intrarea n TSR, iniializarea lui cu noua valoare, iar nainte de ieire din TSR s fie refcut la valoarea avut. Activarea unui program TSR presupune ntreruperea celui curent executat. n cazul n care codul rezident folosete funcii de sistem, el trebuie s testeze, la activarea sa, dac programul ntrerupt executa o funcie DOS/BIOS. Codul rezident nu poate reactiva o funcie de sistem, n timp ce se execut o alt funcie DOS/BIOS, deoarece DOS-ul nu este un sistem de operare reentrant (accesul la disc: 13h, 25h, 26h, nu poate fi ntrerupt). Aceast problem este doar pentru TSR-uri active, ntruct cele pasive sunt apelate i se vor executa n cadrul programului apelant, care nu poate executa simultan dou apeluri. Pentru a evita astfel de operaii sistemul de operare utilizeaz dou variabile: 'eroare critic' i 'seciune sau stare critic', pe care le activeaz corespunztor strii n care se afl. Cele dou variabile pot fi testate de codul rezident, n momentul n care se utilizeaz funcii DOS. Adresele celor dou variabile, i deci starea lor, sunt returnate de funciile 34h (numit indicator seciune critic sau indicator inDOS) i respectiv, 50D6h (eroare critic), n registrele ES:BX. Cele dou adrese pot fi memorate n zona de date a prii rezidente, de ctre partea de iniializare a programului TSR, pentru a le testa direct. ntreruperea multiplexat, INT 2FH Cnd se instaleaz un program TSR care are i componente pasive, trebuie ales un vector de ntrerupere pe care s fie instalat, astfel ca alte programe s poat comunica cu rutinele sale, pasive. Se poate alege un vector aproape la ntmplare dar aceasta poate conduce la anumite probleme de compatibilitate. Ce se ntmpl dac altcineva utilizeaz deja acest vector de ntrerupere ? n multe situaii alegerea este clar, cum ar fi n situaia n care codul pasiv al TSR -ului extinde anumite servicii (tastatur, video). n celelalte situaii, cum ar fi crearea unui nou driver pentru un nou dispozitiv, care s nu interfere funciile furnizate pentru acest dispozitiv, cu alte ntreruperi, alegerea la ntmplare a unui vector de ntrerupere este riscant. Pentru a rezolva aceste situaii DOS-ul furnizeaz soluia utilizrii unei ntreruperi multiplexate, INT 2FH, care permite instalarea, testarea prezenei i a comunicrii cu un program TSR. Pentru a utiliza aceast ntrerupere, o aplicaie plaseaz o valoare de identificare n AH i un numr de funcie n AL, i apoi execut INT 2FH. Fiecare TSR din lanul INT 2FH va compara valoarea din AH cu propria sa valoare unic de identificare. Dac valoarea sa coincide cu cea din AH, atunci TSR-ul respectiv va prelucra comanda specificat de valoarea din registrul AL. Dac

nu se identific, prin valoarea din AH, atunci TSR-ul respectiv transmite controlul la urmtorul manipulator din lanul INT 2FH. Aceasta simplific cumva problema, dar nu o elimin. De obicei, trebuie ales numrul ntreruperii nainte de proiectarea TSR-ului. Cum, ns, o aplicaie va ti ce valoare s ncarce n AH, dac se asigneaz dinamic aceast valoare, cnd TSR-ul este rezident ? Se permite oricrei aplicaii interesate s determine identificatorul (ID) TSR-ului. Prin convenie, funcia zero (AL=0) este un apel ce determin prezena TSR-ului. Acest apel se va realiza nainte de solicitarea oricrui serviciu TSR, pentru a determina dac programul TSR este prezent n memorie. Dezinstalarea unui program TSR La dezinstalarea unui TSR trebuie fcute trei lucruri: - oprirea/ suspendarea oricror activiti nerezolvate sau n ateptare (adic, un TSR poate avea anumii indicatori iniializai pentru a lansa anumite activiti ulterioare); - refacerea tuturor vectorilor de ntrerupere la valorile lor iniiale; - eliberarea spaiului de memorie ocupat, adic cedarea spaiului de memorie rezervat napoi ctre DOS, astfel ca alte aplicaii s-l poat utiliza; Dac dezinstalarea TSR-ului const doar n refacerea valorilor vectorilor de ntrerupere, se va crea o problem, dac exist alte TSR-uri care utilizeaz aceeai vectori de ntrerupere. S presupunem c avem urmtorul lan de TSR-uri, pe un anumit nivel de ntrerupere:

Aceasta va dezactiva efectiv TSR-urile nlnuite din program, iar aceste TSR-uri vor avea efecte neateptate, n aceste condiii. O soluie ar fi tiprirea unui mesaj de eroare, care s informeze utilizatorul c nu se poate dezinstala acest TSR, pn nu se dezinstaleaz toate TSR urile instalate anterior acestuia. Problema va fi n a determina TSR-urile nlnuite n ntrerupere. Pentru aceasta tim c vectorii de ntrerupere ar trebui nc s refere rutina noastr, dac acesta este ultimul TSR care se execut. Atunci, trebuie s comparm vectorii de ntrerupere instalai cu adresele rutinelor de servire a ntreruperii respective. Dac toate acestea se potrivesc, atunci se poate elimina n siguran TSR-ul din memorie. Dac, ns, doar unul dintre ei nu se potrivete, atunci nu putem elimina TSR-ul din memorie.

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