Universitatea Politehnica Bucuresti
Facultatea de Electronica, Telecomunicatii si Tehnologia Informatiei
Studenti: Griparis Andreea
Nedeloiu Dumitru-Valentin
Patrascu Cosmin-Mihnea
Trusca Ionut
Grupa: 431A
Cuprins
Asambloare si procesul de asamblare
Capitolul 1.(Patrascu Cosmin-Mihnea)
1.Limbajul de asamblare..................................................................3
-
Introducere in limbajul de asamblare....………………………………3
-
Avantajele programarii in limbaj de asamblare....…………………...3
-
Prezentarea modului de elaborare a unui program
in limbaj de asamblare….................…………………..…………………...4
1.4.Sintaxa instructiunilor in limbaj de asamblare......…………………..6
Capitolul 2.(Nedeloiu Dumitru-Valentin)
2.Macro.......................................................................................... 10
-
Introducere……………………………….…………………………….10
-
Macrodefiniţie, apel şi expandare............................…………………..10
2.3 Macrodefiniţii cu parametri …………………………………………..12
2.4.Facilităţi avansate.....................................................…………………...12
2.5 Implementarea facilităţii de macrodefiniţii într-un asamblor............13
2.6 Definirea macroinstrucţiunilor în macroinstrucţiuni..........................14
Capitolul 3.(Griparis Andreea)
3.Procesul de asamblare..................................................................16
3.1. Asambloare cu doua treceri.................................................................16
3.2. Prima trecere.........................................................................................16
3.3. A doua trecere.......................................................................................17
3.4. Tabela de simboluri..............................................................................17
Capitolul 4.(Trusca Ionut-Alexandru)
Capitolul 1. Limbajul de asamblare
(Patrascu Cosmin-Mihnea)
1.1 INTRODUCERE IN LIMBAJUL DE ASAMBLARE
Pentru a rezolva o problema care nu este rezolvata de programele curente, un dezvoltator de aplicatii care a ajuns la concluzia ca trebuie sa intervina la nivelul masinii de calcul, are nevoie sa scrie o lista de instructiuni de masina (X86, ALPHA, 8051, etc.) pentru implementarea algoritmilor proprii. Acest text lista cu linii de instructiuni se va intocmi intr-o reprezentare standardizata de fisier sursa, conform cu un limbaj de asamblare al microprocesorului dat.
Translatoarele pot sa fie clasificate grosier in doua grupuri, in functie de relatia dintre limbajul sursa si limbajul destinatie.Cand limbajul sursa este pur si simplu o reprezentare simbolica pentru un limbaj masina numeric, translatorul se numeste asamblor iar limbajul sursa este numit limbaj de asamblare.Cand limbajul sursa este un limbaj de nivel inalt, ca Java sau C si limbajul destinatie este fie un limbaj masina numeric, fie o reprezentare simbolica pentru un astfel de limbaj, translatorul se numeste compilator.
Conform DEX asamblorul este un program special utilitar care asigura trecerea limbajului simbolic in limbajul calculatorului. Asamblorul are deci functia de a prelucra un fisier text sursa cu scopul de a construi un fisier in cod obiect ce are instructiuni scrise in codul masinii.Fisierul obiect rezultat, odata ajuns in memoria principala a microprocesorului este executat.
Un limbaj de asamblare pur, este un limbaj in care fiecare instructiune produce o singura instructiune masina. Exista, astfel, o corespondenta unu la unu intre instructiunile masina si instructiunile din programul de asamblare. Desi nu pare o mare diferenta intre cele doua limbaje, aceasta devine evidenta daca se ia in calcul ca limbajul masina numeric este scris in hexazecimal pe cand limbajul de asamblare foloseste nume si adrese simbolice, mult mai usor de tinut minte decat reprezentarile octale. Asamblorul se ocupa de traducerea numelor simbolice si a adreselor simbolice in instructiuni masina respectiv adrese numerice.
O alta proprietate importanta a limbajelor de asamblare este aceea ca programatorul are acces la toate facilitatile si instructiunile disponibile pe masina tinta, facilitati pe care programatorul in limbaje de nivel inalt nu le are. De exemplu, daca masina tinta are un bit care testeaza depasirea superioara, un program scris in limbaj de asamblare poate testa acel bit direct, pe cand un program scris in Java nu are asemenea posibiltate. Astfel, tot ce se poate face in limbajul masina se poate face si in limbajul de asamblare. Limbajele avansate de
nivel inalt, cum ar fi C, sunt de multe ori o combinatie intre aceste doua tipuri de limbaje de programare.
1.2 AVANTAJELE PROGRAMARII IN LIMBAJ DE ASAMBLARE
Limbajul de asamblare este un limbaj de programare, principala sa deosebire fata de limbajele de nivel inalt precum BASIC, PASCAL si C/C++, fiind aceea ca el ofera doar câteva tipuri simple de comenzi si date. Limbajele de asamblare nu specifica tipul valorilor pastrate in variabile, lasand programatorul sa aplice asupra lor operatiile potrivite. Scopul limbajului de asamblare este de a face mai prietenos procesul de programare decat programarea directa in limbaj masina.
In ciuda unor dezavantaje clare, spcifice programarii in limbaj de asamblare: lizibilitate greoaie a codului (greu de scris, citit si inteles), depanare si intretinere dificila, lipsa portabilitatii codului, exista motive pentru care inca, nu s-a renuntat la limbajul de asamblare. Printre acestea se numara viteza ridicata de executie a programelor, spatiul relativ redus consumat de acestea dar si permiterea accesului la anumite resurse hardware, acces care nu este disponibil in limbajele de nivel inalt.
Un motiv pentru programarea in limbaj de asamblare il reprezinta prezenta rutinelor aferente sistemului de operare.Intrucat acestea sunt apelate foarte des pe parcursul functionarii sistemului de calcul (atat in programe utilizator cat si in functii ale sistemului de operare), este necesar un timp redus de executie din partea lor si sa ocupe cât mai putin spatiu de memorie. Programarea in limbaj de asamblare este in primul rand dependenta de masina (microarhitectura hardware) pe care se proceseaza, obligand programatorul sa cunoasca cat mai detaliat arhitectura setului de instructiuni – ISA.
Un alt motiv in favoarea programarii in limbaj de asamblare il reprezinta amploarea si dinamismul existent in dezvoltarea de sisteme dedicate. Performanta se focalizeaza pe indeplinirea cerintelor de timp real ale aplicatiei (aplicatii cu microcontrolere, procesoare de semnal, aparate foto si camere video, comanda aparatelor electrocasnice, telefoane mobile, imprimante, comenzi auto, jocuri electronice, switch-uri pentru retele, etc). Sunt caracterizate in principal de consumuri reduse de putere (deseori sunt alimentate prin baterii si acumulatori) si memorii de capacitati relativ reduse.
Un alt aspect care recomanda studiul limbajelor de asamblare (desi este dependent de un anumit ISA principiile sunt aceleasi) il reprezinta caracterul sau formativ: o cunoastere si o mai buna intelegere a modului de lucru al procesorului, a modurilor de adresare, a organizarii memoriei, a lucrului cu stiva poate ajuta la intelegerea mecanismelor de generare a stivei de date aferenta functiilor, a recursivitatii si a transferului de parametrii la nivelul functiilor, conducand in final la scrierea de programe eficiente in limbajele de nivel inalt (independente de masina).
De asemenea, medii integrate de programare-dezvoltare si compilatoare de limbaje de nivel inalt (C, Pascal, etc.) prezinta facilitati de inserare in codul sursa de nivel inalt a liniilor scrise direct in limbaj de asamblare sau link-editarea intr-un singur modul a mai multor module obiect provenite de la compilarea unor coduri sursa, scrise in limbaje de programare diferite (C, asamblare). In cazul aplicatiilor ample, modulele care necesita structuri de date complexe si tehnici de programare / algoritmi complicati de rezolvare, sunt scrise module in limbaje de nivel inalt, iar cele care sunt critice din punct de vedere al timpului de executie si al resurselor utilizate sunt implementate in limbaj de asamblare specific procesorului pe care se executa aplicatia.
1.3 PREZENTAREA MODULUI DE ELABORARE A UNUI PROGRAM IN LIMBAJ DE ASAMBLARE
Elaborarea unei aplicatii intr-un anumit limbaj de programare presupune parcurgerea mai multor etape:
-
editarea programului – scrierea "programului sursa" folosind instructiunile si directivele limbajului de programare;
-
compilarea – traducerea programului sursa in secvente de coduri interpretabile si executabile de masina fizica; in urma compilarii se genereaza "module obiect";
-
editarea de legaturi – solutionarea referintelor externe (declaratii de variabile si proceduri in alte module decât cele care le utilizeaza sau le apeleaza), si includerea unor module continute in bibliotecile limbajului de programare; in urma acestei faze se genereaza un program executabil;
-
incarcarea si executia programului – programul executabil se incarca in memoria calculatorului, se actualizeaza adresele conform pozitiei ocupate de program in memorie, dupa care procesorul executa un salt la secventa de inceput a programului.
In cazul utilizarii unor medii avansate de programare (ex: Visual Studio, Turbo Pascal, etc.) aceste etape sunt mai greu de sesizat, deoarece lansarea diferitelor programe si utilitare care solutioneaza aceste etape cade in sarcina mediului. In lipsa unui astfel de mediu, programatorul va lansa succesiv un editor de texte pentru scrierea programului sursa, un compilator si un editor de legaturi. Incarcarea si lansarea in executie a aplicatiei se face de catre sistemul de operare la o comanda data de utilizator.
In figura urmatoare s-a indicat secventa de pasi necesari pentru editarea compilarea si executia unui program scris in limbaj de asamblare.
Editarea unui program sursa in limbaj de asamblare se poate face cu orice editor de text care respecta principiul " WYSWYG - what you see is what you get", adica imaginea de pe ecran este fidela cu continutul fisierului generat. Editorul nu introduce coduri suplimentare de formatare si nu foloseste tehnici de compactare. Astfel se poate utiliza un editor dintr-un alt mediu de programare (ex: din mediul Borland) sau editorul NotePad din Windows.
Compilarea programului (operatie denumita si asamblare) se poate realiza cu o anumita varianta de asamblor: MASM (din mediul MS-DOS) sau TASM (din mediul Borland). Astfel se genereaza un fisier de tip OBJ care contine modulul obiect al programului scris. Editarea legaturilor se realizeaza cu utilitarul LINK (mediul MS-DOS) sau TLINK (Mediul Borland). Aceasta operatie este necesara chiar si in cazul in care programul este continut intr-un singur modul. In urma acestei operatii se genereaza un fisier EXE, care contine programul executabil.
Modulele de program scrise in limbaj de asamblare se pot combina cu alte module scrise in alte limbaje de programare sau cu module obiect continute in biblioteci. Programul generat se poate executa numai dupa ce a fost incarcat in memoria calculatorului la o adresa data de sistemul de operare.
Pentru depanarea erorilor de programare si pentru testarea programului se poate utiliza unul din utilitarele: DEBUG (mediul MS-DOS), TD (turbo-debug, mediul Borland), AFD sau altele. Aceste utilitare permit incarcarea in memorie a programului, executia acestuia pas-cu-pas sau complect si vizualizarea memoriei si a registrelor procesorului.
1.4 SINTAXA INSTRUCTIUNILOR IN LIMBAJUL DE ASAMBLARE:
Desi structura unei instructiuni in limbaj de asamblare se aseamana foarte mult cu structura instructiunii masina pe care o reprezinta, limbajele de asamblare pentru diferite masini si diferite niveluri au suficiente asemanari unele cu altele pentru a permite o discutie generala asupra limbajului de asmblare.
Fiecare linie intr-un program de asamblare reprezinta una din urmatoarele:
-instructiune;
-directiva de asamblare;
-comentariu.
Spatiile albe dintre simboluri sunt ignorate. Comentarile in fisier de asmblare incep cu simbolul ”;”. Orice urmeaza acestui caracter pana la sfarsitul liniei este ignorat.Identificatorii sunt o secventa de caractere alfanumerice, linie de subliniere, si trebuie sa nu inceapa cu un numar. Daca numerele sunt precedate de caracterul 0x, ele sunt interpretate in sistemul de numeratie hexazecimal.
Sirurile sunt incadrate de ghilimele ‘” ’.Caracterele speciale din siruri urmeaza conventia limbajului C. Astfel :
-linie noua \n;
-tab \t;
-ghilimele \”
Formatul instructiunilor este lungime fixa (caracteristica a procesoarelor RISC) pe 16 biti si dupa cum poate fi observat si in figura urmatoare este alcatuit din 4 campuri: Opcode, Operanzi, Etichete si Comentariu (dintre care primele doua sunt obligatorii iar ultimele doua sunt optionale).
Exemplu:
Mai jos sunt prezentate fragmente de program in limbaj de asamblare pentru Pentium II, Motorola 680x0 si Ultra SPARC, care realizeaza calculul N = I + J.
Etichetele sunt utilizate pentru a da nume simbolice adreselor din memorie, sunt necesare si pentru instructiuni executabile, pentru a permite saltul la instructiuni. Sunt de asemenea necesare in cazul cuvintelor care contin date pentru a permite referirea datelor respective prin nume simbolice. Daca o instructiune este etichetata, eticheta (de obicei) incepe din coloana1. Micile diferente de sintaxa, cum ar fi necesitatea de a pune “ : “ dupa fiecare eticheta pentru limbajul Sun, depinde de gusturile celor ce au creat limbajul si nu releva nicio particularitate arhitecturala.
Fiecare masina are registre cu nume diferite. Pentru Pentium II acestea pot fi: EAX, EBX, ECX s.a. Motorola are registre denumite D0, D1, D2 s.a. SPARC are nume multiple pentru registrele sale.
Opcode (Codul operatiei) contine fie o prescurtare simbolica a numelui unei operatii – daca instructiunea este o reprezentare simbolica pentru o instructiune masina – sau o comanda pentru asamblor. Alegerea unui nume potrivit este o chestiune de gust, si proiectantii de limbaje de programare de asamblare diferite fac adesea alegeri diferite. De exemplu, pentru Intel s-a preferat utilizarea MOV pentru incarcarea unui registru din/in memorie, pe cand proiectantii ansamblorului Motorola s-a ales MOVE pentru amble cazuri. Proiectantii limbajului Sun pentru SPARC au ales sa foloseasca LD pentru incarcarea unui registru din memorie si SD pentru memorarea unui registru in memorie.
Necesitatea utilizarii a doua instructiuni masina, incepand cu SETHI, pentru a acesa memoria, este o proprietate inerenta a arhitecturii SPARC, pentru ca adresele virtuale au 32 de biti pentru SPARCv8 sau 44 de biti pentru SPARCv9 iar instructiunile pot sa contina cel mult 22 de biti de date imediate. Deci, vor fi necesare doua instructiuni pentru a furniza toti bitii unei adrese virtuale complete:
SETHI %HI(I),%R1
Pune pe zero cei mai semnificativi 32 de biti si cei mai putini semnificativi 10 biti ai registrului R1(de 64 biti), dupa care pune cei mai semnificativi 22 de biti ai adresei variabilei I in pozitiile de bit de la 10 la 31 ai registrului R1.
Instructiunea urmatoare: LD [%R1+%LO(I)],%R1 aduna R1 si cei mai putin smnificativi 10 biti ai adresei I pentru a obtine adresa completa a lui I, aduce cuvantul din memorie si il pune in R1. Desi dificila, instructiunea este rapida.
Familiile Pentium, 680x0 si SPARC admit operanzi ce se executa pe B, pe W sau pe DW. Pentru ca ansamblorul sa isi dea seama ce lungime sa utilizeze sau ales diverse solutii. Pentru Pentium II, registrele de lungime diferita au nume diferite: EAX este utilizat pentru a mult elemente pe 32 biti, AX pentru elemente pe 16 biti, AL si AH pentru elemente pe 8b.
Proiectantii Motorola au adoptat sufixul .L pentru cuvant lung, .W pentru cuvant (word) si .B pentru octet. SPARC utilizeaza coduri de operatie diferite pentru lungimi diferite (ex: LDSB, LDSH sau LDSW). Cele trei abordari sunt arbitrare si releva libertatea de care se bucura proiectantii de ansambloare.
Cele trei ansambloare difera si prin modul in care se rezerva spatii pentru date. Pentru Intel s-a ales DW (define word) si s-a adaugat .WORD ca alternativa. Pentru Motorola se foloseste DC (define constant) iar Sun utilizeaza .WORD.
Operanzi - campul de operanzi se utilizeaza pentru a specifica adresele si registrele folosite ca operanzi de instructiunea masina. Pentru o instructiune de adunare intreaga, campul de operanzi indica ce cu ce se aduna. Campul de operanzi pentru o instructiune de salt indica eticheta la care se face saltul. Operanzii sunt separati prin virgula. Numarul, ordinea si tipul corespund formatului instructiunii.
Comentariu - este orice secventa de simboluri care urmeaza caracterului „;”. Este ignorat de catre asamblor, rolul sau fiind de a ajuta dezvoltatorii si utilizatorii de programe pentru o mai buna documentare si intelegere a secventelor de cod. Exista insa si câteva artificii (reguli de respectat) in cazul folosirii comentariilor:
-trebuie evitata comentarea unor lucruri evidente: de ex. “se decrementeaza R1”;
-furnizati indicii suplimentare de genul “in R6 se calculeaza produsul prin acumulare – insumari repetate”;
-folositi comentariile pentru a separa bucatile de program cu caracter distinct.
Directivele (pseudoinstructiuni) sunt elemente de limbaj care au rol in procesul de elaborare, compilare si link-editare a unui program, dar care nu se regasesc in programul executabil. In consecinta directivele nu sunt executabile si nu se genereaza cod pe baza acestora.
Totusi scrierea unui program in limbaj de asamblare necesita utilizarea directivelor. Ele se folosesc pentru declararea variabilelor si a constantelor, pentru delimitarea procedurilor si a segmentelor si pentru a controla modul de compilare si link-editare al programului.
Exemple de directive pentru MS MASM:
Pseudoinstructiunea SEGMENT incepe un segment nou, iar ENDS termina un segment. Este permis sa se inceapa un segment de text de cod apoi sa se inceapa un segment de date si apoi sa se revina la segmentul de text s.a.
ALIGN forteaza ca urmatoarea linie, de obicei de date, sa inceapa la o adresa care este multiplu al argumentului sau. De exemplu, daca segmentul curent are deja 61B de date, atunci dupa ALIGN 4, urmatoare adresa alocata va fi 64.
EQU este utilizat pentru a da un nume simbolic unei expresii. De exemplu:
BASE EQU 1000
Simbolul BASE poate fi utilizat oriune in loc de valoare 1000.
DB, DD, DW si DQ aloca memorie pentru una sau mai multe variabile ocupand 1, 2, 4, sau 8 B. Exemplu: TABLE DB 11, 23, 49 aloca spatiu pentru 3B pe care ii initializeaza cu 11, 23 si respectiv 49.
Pseudoinstructiunea INCLUDE produce includerea de catre ansambor a unui alt fisier in fisierul curent. Astfel de fisiere contin de obicei definitii, macro definitii si alte elemente necesare in mai multe fisiere.
Multe ansambloare suporta ansamblarea conditionata (MASM nu face
exceptie). De exemplu:
WORDSIZE EQU 16
IF WORDSIZE GT 16
WSIZE: DW 32
ELSE
WSIZE: DW 16
ENDIF
Se aloca un cuvant de 32b si eticheteaza adresa sa cu WSIZE. Cuvantul respectiv este initializat cu 32 sau 16, in functie de valoarea lui WORDSIZE. In acest caz, cu 16.De obicei, astfel de instructiune se foloseste pentru a putea fi ansamblata si pe o masina de 16b si pe una de 32b. Astfel, programul se poate utiliza pe mai multe masini tinta.
Nici pseudoinstruciunile nu sunt dictate de arhitectura masinii care le foloseste!
Pentru imbunatatirea lizibilitatii si intelegerii codului scris in limbaj de asamblare ar trebui respectate cateva reguli:
1. Realizarea unui antet cu numele autorului, eventual date de contact si scopul programului;
2. Etichetele, opcode-ul, operanzii si comentariile sa inceapa in aceeasi coloana, exceptand cazurile in care intreg randul este un comentariu;
3. Trebuie folosite comentarii pentru a explica ce retine fiecare registru si respectiv ce face fiecare instructiune;
4. Trebuie folosite nume simbolice edificatoare, daca este cazul trebuie mixate literele mici cu cele mari;
5. Trebuie folosite comentarii pentru a separa sectiunile de program cu caracter distinct;
6. Trebuie evitate trunchierile de instructiuni sau desfasurarea lor pe doua pagini de text.Enunturile lungi trebuie separate intr-o maniera estetica.
Bibliografie:
Introducere in stiinta si ingineria calculatoarelor. Interfata Hardware – Software - Adrian Florea (Matrixrom 2007)
Organizarea Structurata a Calculatoarelor – Andrew S. Tanenbaum (editia a IV-a)
http://ro.wikipedia.org/wiki/Limbaj_de_asamblare
Capitolul 2. Macro
(Nedeloiu Dumitru-Valentin)
2 .1 INTRODUCERE
Programatorii în limbaj de asamblare trebuie să repete adesea secvenţe de instrucţiuni de mai multe ori în cadrul aceluiaşi program. Cel mai simplu este să scrie instrucţiunile respective de câte ori este nevoie. Totuşi, dacă o secvenţă de instrucţiuni este lungă, sau dacă trebuie să fie utilizată de multe ori, scrierea repetată poate să devină plicticoasă.
O abordare este transformarea secvenţei respectivă în procedură şi apelarea sa de câte ori este nevoie. Această strategie are dezavantajul că necesită ca o instrucţiune de apel de proceduri şi o instrucţiune de revenire din procedură să se execute ori de câte ori este necesară secventa respectivă. Dacă secvenţa este scurtă - de exemplu, două instrucţiuni - dar este utilizată frecvent, costul apelului de proceduri poate să producă o încetinire semnificativă a programului
Macrourile oferă o soluţie simplă şi eficientă problemei utilizării repetate a aceleiaşi sau aproape aceleiasi secvenţe de instrucţiuni.
2.2 MACRODEFINIE, APEL SI EXPANDARE
O macrodefiniţie este un mod de a da un nume unei secvenţe de text. După ce o macrodefiniţie a fost definită, programatorul poate să scrie numele macroului în locul secvenţei de program. O macrodefiniţie este, de fapt, o prescurtare pentru o bucată de text. Error! Reference source not found. (a) prezintă un program, scris în limbaj de asamblare pentru Pentium II, care schimbă conţinutul variabilelor P şi Q de două ori. Aceste secvenţe pot să fie definite ca o macro aşa cum se vede In Error! Reference source not found (b). După această definiţie, orice apariţie a lui SWAP va fi înlocuită de patru linii:
MOV EAX,P
MOV EBX,Q
MOV Q, EAX
MOV P,EBX
Programatorul a definit SWAP ca pe o prescurtare a celor patru instrucţiuni prezentate mai sus.
MOV
|
EAX,P
|
SWAP
|
MACRO
|
MOV
|
EBX,Q
|
|
MOV EAX,P
|
MOV
|
Q, EAX
|
MOV
|
EBX,Q
|
MOV
|
P,EBX
|
|
MOV Q, EAX
|
|
|
|
MOV P,EBX
|
MOV
|
EAX.P
|
|
ENDM
|
MOV
|
EBX,Q
|
|
|
MOV
|
Q, EAX
|
|
SWAP
|
MOV P,EBX
(a) (b)
Codul în limbaj de asamblare pentru interschimbarea de două ori a lui P cu Q. (a) Fără macro, (b) Cu o macrodefîniţie
Deşi asambloare diferite utilizează notaţii puţin diferite pentru definirea macrourilor. toate necesită aceleaşi componente de bază pentru o macro definiţie:
1. Un antet care dă numele macroului care se defineşte
2.Un text care formează corpul macroului
3.O pseudoinstrucţiune care marchează sfârşitul definiţiei (de exemplu ENDM)
Când asamblorul întâlneşte o macrodefiniţie, o memorează într-o tabelă de definiţii pentru utilizare ulterioară. Din acel moment, ori de câte ori, numele macrodefiniţiei (de exemplu SWAP în exemplu apare pe poziţie de cod de operaţie, asamblorul îl înlocuieşte cu corpul macrodefiniţiei.
Utilizarea numelui macroului drept cod de operaţie se numeşte apel de macro şi înlocuirea sa cu corpul macrodefiniţiei se numeşte macro expandare.
Macro expandarea apare în timpul procesului de asamblare şi nu în timpul execuţiei programului. Acest aspect este important. Programele din (a) şi din (b) vor produce exact acelaşi cod în limbaj maşină. Uitându-ne numai la programul în limbaj maşină, este imposibil să susţinem dacă au fost utilizate macrouri pentru generarea sa. Motivul este că o dată ce macro expandarea s-a terminat, macrodefiniţiile sunt "uitate" de către asamblor. Nici o urmă din acestea nu mai rămâne în programul generat
Apelurile de macrodefiniţii nu trebuie să fie confundate cu apelurile de proceduri. Diferenţa de bază este că un apel de macrodefiniţie este o instrucţiune pentru asamblor, pentru înlocuirea numelui cu corpul macrodefinitia. Un apel de procedură este o instrucţiune maşină care este inserată in programul obiect şi care va fi executată ulterior pentru a apela procedura.Figura urmatoare compară apelurile de macrodefiniţii cu apelurile de proceduri.
Element
|
Apel de macro
|
Apel de procedură
|
Când se face apelul ?
|
In timpul asamblării
|
In timpul execuţiei programului
|
Se face inserarea corpului în programul obiect ori de câte ori se face apelul?
|
Da
|
Nu
|
Se inserează un apel de procedură în programul obiect generat şi se execută ulterior ?
|
Nu
|
Da
|
Trebuie să se utilizeze o instrucţiune
de revenire după ce s-a executat apelul ?
|
Nu
|
Da
|
Câte copii ale corpului apar în 1 programul obiect ?
|
Câte una pentru fiecare apel de macro
|
1
|
Figura . Comparaţia între apeluri de macrodefiniţii şi apeluri de proceduri
Din punct de vedere conceptual, este cel mai bine să se interpreteze procesul de asamblare ca şi cum s-ar executa în două treceri. în prima trecere, toate definiţiile de macrodefiniţii sunt salvate şi apelurile de macrodefiniţii sunt expandate. In trecerea doua, textul care rezultă este prelucrat ca si cum ar fî fost textul original. In această viziune, programul sursă este citit şi apoi transformat într-un alt program din care toate macrodefiniţiile au fost eliminate, şi în care toate apelurile de macrodefiniţii au fost înlocuite cu corpurile lor. Rezultatul, un program în limbaj de asamblare care nu mai conţine de loc macro instrucţiuni, este apoi furnizat asamblorului.
Este important să avem în minte faptul că un program este un şir de caractere conţinând litere, cifre, spaţii, semne de punctuaţie, şi "carriage return" (trecere la o linie nouă). Macro expandarea constă din înlocuirea unui anumit subşir din acest şir cu alte şiruri de caractere. Facilitatea de utilizare macrouri este o tehnică de lucru cu şiruri de caractere, indiferent de semnificaţia acestora.
2.3 MACRODEFINITII CU PARAMETRII
Facilitatea de macrodefiniţie descrisă anterior poate să fie utilizată pentru a scurta programe în care aceeaşi secvenţă de instrucţiuni apare în mod repetat. De multe ori, însă un program conţine mai multe secvenţe de instrucţiuni care sunt aproape, dar nu sunt perfect identice, aşa cum se vede In Fig. (a). Prima secvenţă interschimbă P şi Q, iar a doua interschimbă R şi S.
MOV
|
EAX,P
|
CHANGE MACRO P1,P2
|
MOV
|
EBX,Q
|
MOV
|
MOV
|
Q,EAX
|
MOV
|
MOV
|
P,EBX
|
MOV
|
|
|
MOV
|
MOV
|
EAX,R
|
ENDM
|
MOV
|
EBX,S
|
|
MOV
|
S,EAX
|
CHANGE P,Q
|
MOV
|
R,EBX
|
|
|
|
CHANGE R,S
|
|
(a)
|
(b)
|
Figura Secvenţe aproape identice de instrucţiuni, (a) Fără macro, (b) Cu macro
Macro asambloarele rezolvă cazul secvenţelor aproape identice de instrucţiuni permiţând macrodefiniţiilor să utilizeze parametrii formali şi permiţând apelurilor de macrouri să ofere parametri actuali. Când se face expandarea unei macrodefiniţii, fiecare parametru formal care apare în corpul macroului este înlocuit de parametrul actual corespunzător. Parametrii actuali sunt plasaţi in câmpul de operanzi ai apelului de macro. Fig (b) prezintă programul din Fig. (a) rescris utilizând un macro cu doi parametri. Simbolurile PI şi P2 sunt parametri formali Fiecare apariţie a lui P1 în corpul macroului este înlocuită cu primul parametru actual când se face expandarea macroului. La fel P2 este înlocuit de al doilea parametru. In apelul de macro CHANGE P,Q
P este primul parametru actual şi Q este al doilea parametru actual. în acest mod programele executabile produse de ambele părţi din Fig. sunt identice.
2.4 FACILITATI AVANSATE
Majoritatea macro procesoarelor au un număr mare de facilităţi avansate pentru a face mai simplă viaţa programatorului în limbaj de asamblare. In această secţiune vom arunca o privire asupra câtorva din facilităţile MASM. O problemă care apare în legătură cu toate asambloarele care admit macrouri este cea a etichetelor duplicate. Să presupunem că o macrodefîniţie conţine o instrucţiune condiţionată de salt şi o etichetă la care se face saltul. Dacă macrodefiniţia este apelat de două sau mai multe ori eticheta este duplicată şi se semnalează o eroare de asamblare. O soluţie este ca programatorul să furnizeze ca parametru o etichetă diferită pentru fiecare apel. O soluţie diferită (utilizată de MASM) este să se permită ca eticheta să fie declarată LOCAL, iar asamblorul să genereze automat o etichetă diferită la fiecare expandare de macrodefiniţie. Alte asambloare au ca regulă că etichetele numerice sunt in mod automat locale.
MASM şi majoritatea asambloarelor permit definirea de macrouri în alte macrouri. Această facilitate este utilă împreună cu asamblarea condiţionată. în mod tipic, aceeaşi macrodefîniţie este definită pe ambele ramuri ale unei instrucţiuni IF, ca de exemplu:
M1 MACRO
IF WORDSIzE GT 16 M2 MACRO
....
ENDM
ELSE
M2 MACRO
ENDM
ENDIF
In ambele cazuri. macaxiofiniţia M2 va fi definit, dar definiţia va depinde dacă programul este asamblat pentru o maşină cu o arhitectura do 16 biţi sau pentru o maşină cu 32 de biţi. Dacă M1 nu este apelată, M2 nu va fi definită de loc.
In fine macrodefiniţiilc pot apela alte macrodefiniţii, inclusiv pe ele însele. Dacă o macrodofiniţie este recursivă. adică, dacă se autoapolează, trebuie să-şi transmită un parametru care este modificata fiecare expandare si pc care macrodofiniţia trebuie să-l testeze şi să termine recursivitatea atunci cand se ajunge la o anumita valoare. Altfel asamblorul poate să intre într-un ciclu infinit. Dacă se întâmplă aşa asamblorul trebuie sa fie oprit explicit de către utilizator.
2.5 IMPLEMENTAREA FACILITATII DE MACRODEFINITII INTR-UN ASAMBLOR
Pentru a implementa facilitatea de macrodefîniţie, un asamblor trebuie să fie în stare să realizeze două funcţii: memorarea macrodefiniţiilor şi expandarea apelurilor de macrodefîniţie. Vom examina aceste funcţii pe rând.
Asamblorul trebuie să menţină o tabelă cu toate numele de macrodefîniţie şi pentru fiecare nume. un indicator către definiţia memorată, astfel încât să o poată obţine atunci când este necesară. Unele asanbloare au o tabelă separată de nume de macrouri, altele au o tabelă combinată de coduri de operaţie în care se păstrează toate instrucţiunile maşină, pseudoinstrucţiunile şi numele de macro.
Când se întâlneşte o macrodefîniţie, se construieşte o intrare în tabelă care conţine numele respectiv, numărul de parametri formali, şi un indicator către o altă tabelă - tabela macro definiţiilor - în care se păstrează corpul macro definiţiei. Este construită în acelaşi timp o listă de parametrii formali în vederea utilizării pentru prelucrarea definiţiei. Corpul macrodefiniţiei este apoi citit şi memorat în tabela de macro definiţii. Parametrii formali care apar în corp sunt marcaţi prin nişte simboluri speciale. De exemplu, reprezentarea internă pentru macro definiţia CHANGE cu punct şi virgulă pentru a indica trecerea la linie nouă şi caracterul ampersand (&) ca indicator de parametru formal este următoarea:
MOV EAX,&P1;MOVE BX,&P2;MOV &P2,EAX;MOV &P1,EBX;
In tabelul macrodefiniţiilor corpul unei macrodefiniţii este pur şi simplu un şir de caractere.In timpul primei treceri a asamblării, sunt căutate codurile de operaţie şi sunt expandate macrodefiniţii. Ori de câte ori se găseşte o macrodefiniţie, ea este memorată în tabela de macrouri. Când o macrodefiniţie este apelată, asamblorul nu mai citeşte din fişierul de intrare şi începe în schimb macrodefiniţiei. Parametrii formali care sunt extraşi din corpul macroului sunt înlocuiţi cu parametrii actuali furnizaţi pentru apel. Prezenţa unui caracter amperstand înainte de un parametru formal ajută asamblorului să îl recunoască mai uşor.
2.6 DEFINIREA MACROINSTRUCTIUNILOR IN MACROINSTRUCTIUNI
Se poate spune că macroinstrucţiunile automatizează oarecum procesul de definire a datelor şi a instrucţiunilor. Mai mult decât atât, chiar definirea I macroinstrucţiunilor se poate face prin intermediul altor macroinstrucţiuni.Să considerăm un asemenea caz. în cazul procesorului 8086, instrucţiunile de deplasare şi de rotaţie cu un număr de biţi mai mic sau egal cu 3, se execută mai rapid ca secvenţe de rotaţii de câte un bit, în comparaţie cu instrucţiunile care utilizează registrul CL Dorim să scriem câte o macroinstrucţiune pentru cele 8 instrucţiuni de deplasare şi rotaţie, fiecare cu doi parametri, sursa şi ceea numărul de biţi, care să se expandeze ân secvenţa optimă ca timp de execuţie.
De exemplu, o invocare de forma:
m_shr ax, 5
să se expandeze în secvenţa:
mov c1, 5
shr ax, cl
iar o invocare de forma: m_shr bx, 3
in secvenţa:
shr bx, 1
shr bx, 1
shr bx, 1
Dorim ca generarea macroinstrucţiunilor (având numele de forma m_xxx, unde l xxx este numele instrucţiunii corespunzătoare să fie făcută automat. Incepem prin a defini o macroinstrucţiune care primeşte (in parametrul formal operation) numele instrucţiunii respective şi generează macroinstrucţiunea corespunzătoare:
gen macro operateion
m_&operation macro operand, nr
if nr lt 4
rept nr
operation operand, 1
endm
else
mov cl, nr
oparation operand, cl
endif
endm
endm
La o invocare de forma:
gen shl
se va genera automat macroinstrucţiunea m_shl, conform definiţiei echivalente:
m_shl macro operand, nr
if nr lt 4
rept nr
shl operand, 1
endm
else
mov c1, nr
shl operand, c1
endif
endm
adică exact ce ne-am propus. Generam acum toate cele 8 macroinstrucţiuni, observănd ca numele operaţiilor (Instrucţiunilor) respective se compun din secvenţele RO, RC, SH, SA, la care se adaugă sufixele R sau L. Exploatăm acest fapt prin două macroinstrucţiunl repetitive:
irp X,
irp Y,
GEN x&&Y
endm
endm
Aceasta secvenţă va defini macroinstrucţiunile m_rar, m_rol, m_rcr, m_rcl, m_shr,m_shl,m_ sar si m_sal
Bibliografie:
Organizarea Structurata a Calculatoarelor – Andrew S. Tanenbaum (editia a IV-a)
http://ro.wikipedia.org/wiki/Limbaj_de_asamblare
Asambloare- Aurel Soceneantu
Programare in limbaj de asamblare-Gheorghe Musca
Capitolul 3. Procesul de asamblare
(Griparis Andreea)
3.1.ASAMBLOARE CU DOUA TRECERI
Exista doua tipuri de asambloare in functie de cat de multe treceri sunt necesare pentru a produce programul executabil:
- asambloare cu o singura trecere prin codul sursa.Structura acestuia consta in trei tabele: tabela de simboluri, tabela de pseudoinstructiuni si tabela de operatii;
- asabloare cu doua treceri. Acestea cauta intai codurile de operatie si expandeaza macrodefinitiile, fiind memorate in tabela de macrouri. Apoi, asamblorul va citi direct din tabela, la fiecare apelare.
Motivul initial pentru utilizarea asamboarelor cu o trecere a fost viteza; cu toate acestea, calculatoarele moderne efectueaza asamblare cu doua treceri fara a avea intarzieri inacceptabile.. Avantajul asamboarelor cu doua treceri este ca simbolurile pot fi definite oriunde in codul sursa al programului, permitand programelor care urmeaza sa fie definite intr-un mod mai logic si mai semnificativi, facand programele de asamblare cu doua treceri mai usor de citit si mentinut.
3.2.PRIMA TRECERE
Are ca functie principala construirea unei tabele numita tabela de simboluri, aceasta contine valorile tuturor simbolurilor. Un simbol este o eticheta sau o valoare careia I s-a atribuit un nume simbolic prin intermediul unei pseudoinstructiuni de tipul:
BUFSIZE EQU 8192
In cadrul primei treceri sunt utilizate cel putin trei tabele: tabela de simboluri, tabela de pseudoinstructiuni si tabela de operatii. Tabela de simboluri are o intrare pentru fiecare simbol . Fiecare intrare contine simbolul respectiv, valoarea numerica si uneori alte informatii, cum ar fi: lungimea campului de date asociat cu simbolul, biti de relocare, daca simbolul este sau nu accesibil din afara procedurii.
Tabela pentru codurile operatiilor contine cel putin cate o intrare pentru fiecare nume simbolic din limbajul de asamblare. Fiecare intrare contine un cod de operatie simbolic, doi operanzi, valoarea numerica a codului,operatiei, lungimea instructiunii si un tip numeric care imparte codurile de operatii in grupuri in functie de numarul si tipul de operanzi.
Unele asambloare permit programatorilor sa scrie instructiuni utilizand adresare imediata chiar daca in limbajul tinta nu exista astfel de instructiuni. Asamblorul aloca memorie pentru operandul imediat la sfarsitul programului si genereaza o instructiune care sa il refere. De exemplu, calculatorul IBM 3090 nu are instructiuni imediate, totusi programatorul poate sa scrie: L14,=F’5’.
Pentru a incarca in registrul 14 o constanta 5 reprezentata pe un cuvant intreg. In acest mod programatorul evita sa scrie explicit o pseudoinstructiune pt a aloca un cuvant initializat la 5, dandu-i o eticheta, si apoi utilizand aceasta eticheta in instructiunea L.
Pe masura ce citeste programul , prima trecere trebuie sa parcurga fiecare linie si sa identifice codul operatiei sa determine tipul, si sa calculeze lungimea instructiunii. Aceasta informatie este, de asemenea, pentru cea de-a 2-a trecere, deci este posibil sa o scriem explicit pt a elimina parcurgerea liniei la urmatoarea trecere.
Cand se citeste pseudoinstructiunea END, s-a terminat prima trecere a asamblorului. Tabela de simboluri si cele de literali pot si sortate in acest moment daca este necesar. Tabela de literali sortata, poate fi verificata pt intrari duplicate, care vor fi eliminate.
3.3 A DOUA TRECERE
Functia acestei treceri este de a genera programul obiect si de a afisa listingul programului asamblat. Aceasta trebuie sa furnizeze anumite informatii,necesare editorului de legaturi.
Cea dea doua trecere realizeaza o operatie asemanatoare primei: citeste liniile si le prelucreaza. Operatia principala in generarea codului este facuta de procedurile “eval-type1”, ”eval_type2”. Fiecare dintre ele prelucreaza un anumit model, cum ar fi un cod de operatie cu operanzi din doua registre. Genereaza codul liniar pentru instructiune si il returneaza in “code”, apoi “write_code” depune codul binar acumulat intr-o zona tampon si scrie fisierul pe disc in blocuri mari de date, pentru a reduce traficul de disc.
Pana acum s-a presupus ca programul sursa nu contine erori dar in realitate este aproape imposibil ca un program sa fie scris din prima fara nicio eroare.Erorile cel mai des intalnite sunt:
-
un simbol a fost utilizat, dar nu a fost definit;
-
un simbol a fost definit de mai multe ori;
-
numele din campul codului operatiei nu este un cod de operatie corect;
-
codul unei operatii nu are numarul necesar de operanzi;
-
un numar octal contine una din cifrele 8 sau 9;
-
sunt utilizate registe ilegale;
-
lipseste declaratia END.
In cazul in care un asamblor detecteaza o instructiune eronata, acesta afiseaza un mesaj de eroare si incearca sa continue asamblarea.
3.4. TABELA DE SIMBOLURI
Aceasta este completata cu informatii despre simboluri si valorile lor, pe parcursul primei treceri a procesului de asamblare, pentru a putea fi utilizata in cea dea doua trecere. Tabela de simboluri poate fi organizata in diferite moduri. Toate acestea incearca sa simuleze o memorie asociativa reprezentata printr-o multime de perechi (simbol, valoare). Dandu-se un simbol, memoria asociativa trebuie sa dea o valoare.
Tipuri de organizare a tabelei:
-
ca un tablou de perechi: primul element este simbolul iar al doilea valoarea. Cand se cauta un simbol, rutina asociata tabelei de simboluri, cauta liniar in tabela pana cand gaseste simbolul respectiv. Aceasta metoda este cea mai simpla tehnica de implemantare dar este lenta.
-
Ordonarea tabelei dupa simboluri iar cautarea se face cu un algoritm de cautare binara.Algoritmul compara intrarea din mijlocul tabelei cu simbolul cautat, daca acesta este alfabetic inaintea intrarii din mijloc apartine primei jumatati, daca este dupa intrarea din mijloc apartine celei de-a doua jumatati.Algoritmul se repeta pana cand simbolul va fi egal cu jumatatea intervalului de cautare. Acest algoritm este mai rapid decat precedentul dar necesita mentinerea ordonata a tabelei.
-
Organizare in urma codarii de dispersie. In acest caz este necesara utilizarea unei functii de dispersie care face corespondenta intre simboluti si valori;e intregi din intervalul de la 0 la k-1. Cu “n” simboluri si “k” intrari in tabela lungimea medie a listei va fi n/k. Prin modificarea lui “k” putem reduce dimensiunea tabelei dar costul se va mari.
Informatii continute de TS
In cazul limbajelor sursa care definesc programe structurate pe blocuri (functii si/sau proceduri) care pot sa apara pe mai multe nivele de imbricare, in TS ar trebui sa apara , in principiu, urmatoarele informatii:
-
NUME - referinta la sirul de caractere care formeaza identificatorul. Acest sir constituie de fapt cheia de cautare in TS.
-
CLASA - categoria identificatorului, care poate fi: nume de program, nume de constanta (declarat in sectiunea const), nume de variabila simpla , nume de functie, nume de procedura , nume de parametru formal transmis prin adresa (declarat cu var in lista de parametri), nume de parametru formal transmis prin valoare, nume de tablou, nume de structura (record), nume de camp al unei structuri.
-
TIP - tipul (simplu) declarat pentru variabilele simple, parametrii formali, elementele unui tablou, campurile unei structuri sau rezultatul returnat de o functie. Pentru limbajul dat in Anexa B, acest tip poate fi: intreg, real sau caracter.
-
VAL - se utilizeaza pentru numele de constante (declarate in sectiunea const) si contine indicele spre TabCONST unde se afla valoarea atribuita constantelor respective.
-
ADREL -adresa relativa fata de inceputul unitatii de program in care este declarat identificatorul. Se refera la variabilele declarate in sectiunea var si la parametrii formali.
Functii de acces la TS
Asupra TS se pot efectua doua operatii de baza :
a) Cautarea unui identificator. Cheia de cautare este sirul de caractere care compun identificatorul. Cautarea se va face intotdeauna in sens descrescator al nivelului de imbricare (campul NIVEL) si se va opri la prima aparitie a simbolului cautat sau la epuizarea tabelei. Functia de cautare, pe care o vom nota Cauta _TS va returna indicele intrarii in TS la care s-a gasit simbolul, respectiv o valoare negativa , daca simbolul nu exista in TS
Operatia de cautare este invocata cand in textul sursa se intalneste o referire la un simbol, precum si inaintea unei inserari in TS. In primul caz, daca simbolul nu este gasit, se va considera ca a aparut o eroare de tipul "simbol nedeclarat".
b) Inserarea unui identificator. Aceasta operatie este efectuata cand in textul sursa se intalnesc declaratii de simboluri (numele programului principal, constante, variabile, functii, proceduri si parametri formali). Inainte de inserare se va efectua o cautare a simbolului de inserat, pentru a se detecta eventualele declaratii multiple. Daca un simbol mai este declarat o data in acelasi bloc, se va semnala o eroare de tip "identificator multiplu declarat". Exceptie de la aceasta regula vor face numele de campuri de structuri, in sensul ca:
-
se permit situatii in care un nume de camp coincide cu un nume de variabila simpla, de tablou sau de functie/procedura declarate in acelasi bloc ca si structura in cauza;
-
de asemenea se permite ca doua campuri care apar in structuri diferite sa aiba acelasi nume; in acest caz se vor crea intrari distincte in TS pentru cele doua campuri.
NU se permite, insa , ca in aceeasi structura sa apara doua campuri cu acelasi nume.
Functia de inserare, pe care o vom nota Insert_TS primeste ca parametru identificatorul de inserat si returneaza indicele intrarii din TS alocate identificatorului respectiv.
Rezultatul returnat de functiile de acces la TS va fi utilizat in continuare pentru: extragerea de informatii legate de un anumit simbol si/sau a completa diferitele campuri ale TS cu informatii dobandite pe parcursul analizarii textului sursa.
Indiferent de forma de organizare a TS, in cele ce urmeaza vom utiliza urmatoarele notatii:
-
TS[i] - pentru a referi intrarea cu indicele i din TS;
-
TS[i].nume_camp - pentru a referi campul nume_camp al intrarii de indice i din TS.
Bibliografie:
Organizarea Structurata a Calculatoarelor – Andrew S. Tanenbaum (editia a IVa)
http://jalobean.itim-cj.ro/Cursuri/TehnCompil/LFT08.htm
http://translate.google.ro/translate?hl=ro&langpair=en|ro&u=http://en.wikipedia.org/wiki/Assembly_language
Dostları ilə paylaş: |