Home - qdidactic.com
Didactica si proiecte didacticeBani si dezvoltarea cariereiStiinta  si proiecte tehniceIstorie si biografiiSanatate si medicinaDezvoltare personala
referate stiintaSa fii al doilea inseamna sa fii primul care pierde - Ayrton Senna





Aeronautica Comunicatii Drept Informatica Nutritie Sociologie
Tehnica mecanica

Calculatoare


Qdidactic » stiinta & tehnica » informatica » calculatoare
Elemente ale limbajului de asamblare



Elemente ale limbajului de asamblare


ELEMENTE ALE LIMBAJULUI DE ASAMBLARE

1. INTRODUCERE IN LIMBAJUL DE ASAMBLARE INTEL


Limbajul de asamblare poseda instructiuni cod-masina,  mnemonice (provin de la cuvintele in engleza ce specifica actiunea lor) precum ADD, MOV, SUB sau JMP.

Programul scris folosind un limbaj de asamblare apare sub forma unei liste de de mnemonice ce pot fi convertite usor in limbajul de cod binar. Programele ce fac aceasta translatare se numesc asambloare.

Exemple de limbaje de asamblare sunt: MASM (Microsoft Assembler) si TASM (Turbo Assembler – dezvoltat de firma Borland).


2. Formatul general al unei instructiuni in limbaj de asamblare


O linie de cod scrisa in limbaj de asamblare are urmatorul format general:


<nume> <instructiune/directiva> <operanzi> <;comentariu>

unde:

- <nume> - reprezinta un nume simbolic optional;

- <instructiune/directiva> - reprezinta mnemonica (numele) unei instructiuni sau a unei directive;



- <operanzi> - reprezinta o combinatie de unul, doi sau mai multi operanzi (sau chiar nici unul), care pot fi constante, referinte

de memorie, referinte de registri, siruri de caractere, in functie de structura particulara a instructiunii;

- <;comentariu> - reprezinta un comentariu optional ce poate fi plasat dupa caracterul „;” pana la sfarsitul liniei respective de cod.




3. Instructiuni generale (mnemonice)

o       MOV - mutare de informatie,

o       PUSH - punere de informatii in memoria organizata ca o stiva,

o       POP - aducerea informatiei din memoria stiva;

instructiuni de intrare/iesire

o       IN - depunerea in registrul acumulator a informatiei stocate in registrul de intrare/iesire (portul de date),

o       OUT - scrierea in portul de date a informatiei aflate in registrul acumulator;

instructiuni aritmetice

o       adunare (ADD, ADC, INC etc.),

o       scadere (SUB, DEC, NEG, CMP etc.),

o       inmultire (MUL, IMUL etc.),

o       impartire (DIV, IDIV etc.);

instructiuni de manipulare a sirurilor de biti

o       operatii logice (NOT, AND, OR, XOR, TEST),

o       deplasare (SHL, SAL, SHR, SAR),

o       rotire (ROL, ROR, RCL, RCR);

instructiuni de transfer

o       salt neconditionat (CALL, RET, JMP),

o       salt conditionat - prin testarea indicatorilor de conditii (JC, JNC, JE, JG, JL etc.),

o       cicluri (LOOP etc.),

o       intreruperi (INT, IRET etc.);

instructiuni de sincronizare externa: HLT, WAIT, NOP etc.


Registrii microprocesorului Intel


Registrii (sau registrele) microprocesorului reprezinta locatii de memorie speciale aflate direct pe cip; din aceasta cauza reprezinta cel mai rapid tip de memorie. Un lucru deosebit legat de registri este faptul ca fiecare dintre acestia au un scop bine precizat, oferind anumite functionalitati speciale, unice.


Exista patru mari categorii de registri:


  1. Registrii de uz general,
  2. Registrul indicatorilor de stare (flags),
  3. Registrii de segment,
  4. Registrul pointer de instructiune.

1. Registrii de uz general


Registrii de uz general sunt implicati in operarea majoritatii instructiunilor, drept operanzi sursa sau destinatie pentru calcule, copieri de date, pointeri la locatii de memorie sau cu rol de contorizare.

Fiecare dintre cei 8 registrii de uz general AX, BX, CX, DX, SP, BP, DI,SI sunt registrii pe 16 biti pentru microprocesorul 8086, iar de la procesorul 80386 incoace au devenit registrii pe 32 de biti, denumiti, respectiv: EAX, EBX, ECX, EDX, ESP, EBP, EDI, ESI (Extended ). Mai mult, cei mai putin semnificativi 8 biti ai registrilor AX, BX, CX, DX formeaza respectiv registrii AL, BL, CL, DL (Low), iar cei mai semnificativi 8 bitiai acelorasi registrii formeaza registrii AH, BH, CH, DH (High).



Registrul AX (EAX)


Registrul AX (EAX) este denumit si registrul acumulator, fiind principalul registru de uz general utilizat pentru operatii aritmetice, logice si de deplasare de date. Totdeauna operatiile de inmultire si impartire presupun implicarea registrului AX. Unele dintre instructiuni sunt optimizate pentru a se executa mai rapid atunci cand este folosit AX. In plus, registrul AX este folosit si pentru toate transferurile de date de la/catre porturile de Intrare/Iesire. Poate fi accesat pe portiuni de 8, 16 sau 32 de biti, fiind referit drept AL (cei mai putin semnificativi 8 biti din AX), AH (cei mai semnificativi 8 biti din AX), AX (16 biti) sau EAX (32 de biti). Acest lucru este utilizat pentru a lucra cu date pe un octet, permitand ca registrul AX sa fie folosit pe postul a doi registri separati (AH si AL).


Prezentam in continuare alte cateva exemple de instructiuni ce utilizeaza registrul AX. De remarcat este faptul ca transferurile de date se fac pentru instructiunile (denumite si mnemonice) Intel de la dreapta spre stanga, exact invers decat la Motorola, unde transferul se face de la stanga la dreapta.


Exp:


Urmatoarele trei instructiuni seteaza registrul AH cu valoarea 1, incrementeaza cu 1 aceasta valoare si apoi o copiaza in registrul AL:


MOV AH, 1

INC AH

MOV AL, AH


Valoarea finala a registrului AX va fi 22 (AH = AL = 2).



Registrul BX (EBX)


Registrul BX (Base), sau registrul de baza poate stoca adrese pentru a face referire la diverse structuri de date, cum ar fi vectorii stocati in memorie. O valoare reprezentata pe 16 biti stocata in registrul BX poate fi utilizata ca fiind o portiune din adresa unei locatii de memorie ce va fi accesata. Spre exemplu, urmatoarele instructiuni incarca registrul AH cu valoarea din memorie de la adresa 21.


MOV AX, 0

MOV DS, AX

MOV BX, 21

MOV AH, [ BX ]


Se observa ca am incarcat valoarea 0 in registrul DS inainte de a accesa locatia de memorie referita de registrul BX. Acest lucru este datorat segmentarii memoriei (segmentare discutata mai in detaliu in sectiunea consacrata registrilor de segment); implicit, atunci cand este folosit ca pointer de memorie, BX face referire relativa la registrul de segment DS adresa la care face referire este o adresa relativa la adresa de segment continuta in registrul DS).


Registrul CX (ECX)


Specializarea registrului CX (Counter) este numararea; de aceea, el se numeste si registrul contor. De asemenea, registrul CX joaca un rol special atunci cand se foloseste instructiunea LOOP. Rolul de contor al registrului CX se observa imediat din exemplul urmator:


MOV CX, 5

start:


<instructiuni ce se vor executa de 5 ori>


SUB CX, 1JNZ start


Deoarece valoarea initiala a lui CX este 5, instructiunile cuprinse intre eticheta start si instructiunea JNZ se vor executa de 5 ori (pana cand registrul CX devine 0). Instructiunea SUB CX, 1 decrementeaza registrul CX cu valoarea 1 iar instructiunea JNZ start determina saltul inapoi la eticheta start daca CX nu are valoarea 0.

In limbajul microprocesorului exista si o instructiune speciala legata de ciclare. Aceasta este instructiunea LOOP, care este folosita in combinatie cu registrul CX. Liniile de cod urmatoare sunt echivalente cu cele anterioare, dar aici se utilizeaza instructiunea LOOP:


MOV CX, 5

start:


<instructiuni ce se vor executa de 5 ori>


LOOP start


Se observa ca instructiunea LOOP este folosita in locul celor doua instructiuni SUB si JNZ anterioare; LOOP decrementeaza automat registrul CX cu 1 si executa saltul la eticheta specificata (start) daca CX este diferit de zero, totul intr-o singura instructiune.

Registrul DX (EDX)


Registrul de uz general DX (Data register), denumit si registrul de date, poate fi folosit in cazul transferurilor de date Intrare/Iesire sau atunci cand are loc o operatie de inmultire sau de impartire. Instructiunea IN AL, DX copiaza o valoare de tip Byte dintr-un port de intrare, a carui adresa se afla in registrul DX. Urmatoarele instructiuni determina scrierea valorii 101

in portul I/O 1002:


MOV AL, 101

MOV DX, 1002

OUT DX, AL


Referitor la operatiile de inmultire si impartire, atunci cand impartim un numar pe 32 de biti la un numar pe 16 biti, cei mai semnificativi 16 biti ai deimpartitului trebuie sa fie in DX. Dupa impartire, restul impartirii se va afla in DX. Cei mai putin semnificativi 16 biti ai deimpartitului trebuie sa fie in AX iar catul impartirii va fi in AX. La inmultire, atunci cand se

inmultesc doua numere pe 16 biti, cei mai semnificativi 16 biti ai produsului vor fi stocati in DX iar cei mai putin semnificativi 16 biti in registrul AX.



Registrul SI


Registrul SI (Source Index) poate fi folosit, ca si BX, pentru a referi adrese de memorie. De exemplu, secventa de instructiuni urmatoare:


MOV AX, 0

MOV DS, AX

MOV SI, 33

MOV AL, [ SI ]


Incarca valoarea (pe 8 biti) din memorie de la adresa 33 in registrul AL. Registrul SI este, de asemenea, foarte folositor atunci cand este utilizat in legatura cu instructiunile dedicate tipului STRING (sir de caractere).



Registrul DI


Registrul DI (Destination Index) este utilizat in mod asemanator registrului SI. In secventa de instructiuni urmatoare:


MOV AX, 0

MOV DS, AX

MOV DI, 1000

ADD BL, [ DI ]


se aduna la registrul BL valoarea pe 8 biti stocata la adresa 1000. Registrul DI este putin diferit fata de registrul SI in cazul instructiunilor de tip string; daca SI este intotdeauna pe post de pointer sursa de memorie, registrul DI serveste drept pointer destinatie de memorie. Mai mult, in cazul instructiunilor de tip string, registrul SI adreseaza memoria relativ la registrul de segment DS, in timp ce DI contine referiri la memorie relativ la registrul de segment ES. In cazul in care SI si DI sunt utilizati cu alte instructiuni, ei fac referire la registrul de segment DS.



Registrul BP


Rolul registrilor BP si SP este prezenta in contextul utilizarii stivei. Stiva reprezinta o portiune speciala de locatii adiacente din memorie. Aceasta este continuta in cadrul unui segment de memorie si identificata de un selector de segment memorat in registrul SS (cu exceptia cazului in care se foloseste modelul nesegmentat de memorie in care stiva poate fi localizata oriunde in spatiul de adrese liniare al programului). Stiva este o portiune a memoriei unde valorile pot fi stocate si accesate pe principul LIFO (Last In – First Out), drept urmare ultima valoare stocata in stiva este prima ce va fi citita din stiva. De regula, stiva este utilizata la apelul unei proceduri sau la intoarcerea dintr-un apel de procedura (principalele instructiuni folosite sunt CALL si RET).


Registrul pointer de baza, BP (Base Pointer) poate fi utilizat ca pointer de memorie precum registrii BX, SI si DI. Diferenta este aceea ca, daca BX, SI si DI sunt utilizati in mod normal ca pointeri de memorie relativ la segmentul DS, registrul BP face referire relativ la segmentul de stiva SS.

Deoarece BX, SI si DI se refera la segmentul de date, nu exista o modalitate eficienta de a folosi registrii BX, SI, DI pentru a face referire la parametrii salvati in stiva din cauza ca stiva este localizata intr-un alt segment de memorie. Registrul BP ofera rezolvarea acestei probleme asigurand adresarea in segmentul de stiva.

Spre exemplu, instructiunile:


PUSH BP

MOV BP, SP

MOV AX, [ BP+4 ]


fac sa se acceseze segmentul de stiva pentru a incarca registrul AX cu primul parametru trimis de un apel C unei rutine scrise in limbaj de asamblare. In concluzie, registrul BP este conceput astfel incat sa ofere suport pentru accesul la parametri, variabile locale si alte necesitati legate de accesul la portiunea de stiva din memorie.


Fig. Structura stivei




Registrul SP


Registrul SP (Stack Pointer), sau pointerul de stiva, retine de regula adresa de deplasament a urmatorului element disponibil in cadrul segmentului de stiva. Acest registru este, probabil, cel mai putin „general” dintre registrii de uz general, deoarece este dedicat mai tot timpul

administrarii stivei.

Registrul BP face in fiecare clipa referire la varful stivei – acest varf al stivei reprezinta adresa locatiei de memorie in care va fi introdus urmatorul element in stiva. Actiunea de a introduce un nou element in stiva se numeste „impingere” (in engleza push); de aceea, instructiunea respectiva poarta numele de PUSH. In mod asemanator, operatia de scoatere a unui element din varful stivei poarta, in engleza, numele de pop, iar instructiunea echivalenta operatiei se numeste POP.


Este permisa stocarea valorilor in registrul SP precum si modificarea valorii sale prin adunare sau scadere la fel ca si in cazul celorlalti registri de uz general; totusi, acest lucru nu este recomandat daca nu suntem foarte siguri de ceea ce facem. Prin modificarea registrului SP, vom modifica adresa de memorie a varfului stivei, ceea ce poate avea efecte neprevazute,

aceasta pentru ca instructiunile PUSH si POP nu reprezinta unicele modalitati de utilizare a stivei.


Indiferent daca apelam o subrutina sau ne intoarcem dintr-un astfel de apel de subrutina, fie procedura sau functie, in acest caz este folosita stiva. Unele resurse de sistem, precum tastatura sau ceasul de sistem, pot folosi stiva in momentul trimiterii unei intreruperi la microprocesor. Acest lucru presupune ca stiva este folosita continuu, deci daca se modifica registrul SP (adica adresa stivei), datele din noile locatii de memorie nu vor mai fi cele corecte. In concluzie, registrul SP nu trebuie modificat in mod direct; el este modificat automat in urma instructiunilor POP, PUSH, CALL, RET. Oricare dintre ceilalti registri de uz general pot fi modificati in mod direct in orice moment.



2.2. Registrul pointer de instructiuni (IP)


Registrul pointer de instructiuni este folosit, intotdeauna, pentru a stoca adresa urmatoarei

instructiuni ce va fi executata de catre microprocesor. Pe masura ce o instructiune este executata, pointerul de instructiune este incrementat si se va referi la urmatoarea adresa de memorie (unde este stocata urmatoarea instructiune ce va fi executata). De regula, instructiunea ce urmeaza a fi executata se afla la adresa imediat urmatoare instructiunii ce a fost executata, dar exista si cazuri speciale (rezultate fie din apelul unei subrutine prin instructiunea CALL, fie prin intoarcerea dintr-o subrutina, prin instructiunea RET). Pointerul de instructiuni nu poate fi modificat sau citit in mod direct; doar instructiuni speciale pot incarca acest registru cu o noua valoare. Registrul pointer de instructiune nu specifica pe de-a intregul adresa din memorie a urmatoarei instructiuni ce va fi executata, din aceeasi cauza a segmentarii memoriei. Pentru a aduce o instructiune din memorie, registrul CS ofera o adresa de baza iar registrul pointer de instructiuneindica adresa de deplasament plecand de la aceasta adresa de baza.




Fig. Registrii de segment, pointerul de instructiuni si registrul

indicatorilor de stare



2.3. Registrul indicatorilor de stare (FLAGS) pe 16 biti contine informatii legate de starea microprocesorului precum si de rezultatele ultimilor instructiuni executate. Un indicator de stare (flag) este in sine o locatie de memorie de 1 bit ce indica starea curenta a microprocesorului si modalitatea sa de operare. Un indicator se spune ca “este setat” daca are

valoarea 1 si “nu este setat” in caz contrar. Indicatorii de stare se modifica dupa executia unor instructiuni aritmetice sau logice.

Exemple de indicatori de stare:

- C (Carry) indica aparitia unei cifre binare de transport in cazul unei adunari sau imprumut in cazul unei scaderi;

- O (Overflow) apare in urma unei operatii aritmetice. Daca este setat, inseamna ca rezultatul nu incape in operandul destinatie;

- Z (Zero) indica faptul ca rezultatul unei operatii aritmetice sau logice este zero;

- S (Sign) indica semnul rezultatului unei operatii aritmetice;

- D (Direction) – cand este zero, procesarea elementelor sirului se face de la adresa mai mica la cea mai mare, in caz contrar este invers;

- I (Interrupt) controleaza posibilitatea microprocesorului de a raspunde la evenimente externe (apeluri de intrerupere);

- T (Trap) este folosit de programele de depanare (de tip debugger), activand sau nu posibilitatea executiei programului pas cu pas. Daca este setat, UCP intrerupe fiecare instructiune, lasand programul depanator sa execute programul respectiv pas cu pas;

- A (Auxiliary carry) suporta operatii in codul BCD. Majoritatea programelor nu ofera suport pentru reprezentarea numerelor in acest format, de aceea se utilizeaza foarte rar;

- P (Parity) este setat in conformitate cu paritatea bitilor cei mai putin semnificativi ai unei operatii cu date. Astfel, daca rezultatul unei operatii contine un numar par de biti 1, acest indicator este setat. Daca numarul de biti 1 din rezultat este impar, atunci indicatorul PF este zero. Este folosit de regula de programe de comunicatii, dar Intel a introdus acest indicator nu pentru a indeplini o anumita functionalitate, ci pentru a asigura compatibilitatea cu vechile microprocesoare ale familiei x86.



3.4 Registrii de segment


Proprietatile registrilor de segment sunt in stransa legatura cu notiunea de segmentare a memoriei. Premisa de la care se pleaca este urmatoarea: 8086 este capabil sa adreseze 1MB de memorie, astfel ca sunt necesare adrese pe 20 de biti pentru a cuprinde toate locatiile din

spatiul de 1 MB de memorie. Totusi, registrele utilizate sunt registre pe 16 biti, deci a trebuit sa se gaseasca o solutie pentru aceasta problema.

Solutia gasita se numeste segmentarea memoriei; in acest caz memoria de

1MB este impartita in 16 segmente de cate 64 KB (16*64 KB = 1024 KB = 1 MB).

Notiunea de segmentare a memoriei presupune utilizarea unor adrese de memorie formate din doua parti. Prima parte reprezinta adresa segmentului iar cea de-a doua portiune reprezinta adresa de deplasament, sau offset-ul.


Exemplu de program scris folosind instructiunile limbajuli de asamblare :


Cerinta :


Sa se scrie secventa de cod cu ajutorul careia se pot interschimba doua linii dintr-o matrice.


Rezolvare:


main()

//matricea ocupa in memorie 12*4 octeti


long col=3;

long i=1;

long j=4;

long tempESP=0;             //variabile utilizate pt. memorarea pointerului (cursorului) si bazei stivei

long tempEBP=0;

long vari=0; //variabila in care memoram adresa primului element din linia i

long varj=0; //variabila in care memoram adresa primului element din linia j

long sz=sizeof(long);


//incarcam adresa efectiva a primului element al matricei           

_asm lea ebx,matr


//calculam offset-ul primului octet al primului element din linia i, adica (i-1) x col

_asm mov eax,i

_asm sub eax

_asm mul col

_asm mul sz ;luam in calcul faptul ca elementele matricei sunt de tip long, adica sunt variabile pe 4 octeti


//stim offset-ul (calculat in eax) si, ca atare, putem calcula adresa primului element al liniei i; memoram

//in <vari> aceasta adresa

_asm add ebx,eax

_asm mov vari,ebx


//REincarcam adresa efectiva a primului element al matricei       

_asm lea ebx,matr


//calculam indicele primului element din linia j, adica (j-1) x col

_asm mov eax,j

_asm sub eax,1

_asm mul col

_asm mul sz ;luam in calcul faptul ca elementele matricei sunt de tip long, adica sunt variabile pe 4 octeti


//stim indicele (calculat in eax) si, ca atare, putem calcula adresa primului element al liniei j; memoram in <varj> aceasta adresa

_asm add ebx,eax

_asm mov varj,ebx


_asm mov ecx,col

_asm mov eax,vari

_asm mov ebx,varj


_asm mov tempESP,esp ;salvam indicatorul de stiva

_asm mov tempEBP,ebp ;salvam baza stivei


_asm bucla:       


_asm push [eax]

_asm push [ebx]


_asm mov edx,esp //salvam cursorul (pointerul) stivei


_asm pop [eax] //scoatem ultima valoare dusa in stiva in locul valorii din EAX


_asm mov esp,edx //restauram pointerul stivei de dinanintea ultimului pop

_asm add esp,sz //incrementam pointerul stivei cu patru octeti (elementele matricei noastre sunt pe 4 octeti)


_asm mov edx,esp //salvam cursorul (pointerul) stivei


_asm pop [ebx]


_asm mov esp,edx //restauram pointerul stivei de dinanintea ultimului pop

_asm add esp,sz //incrementam pointerul stivei cu patru octeti (elementele matricei noastre sunt pe 4 octeti)


_asm add eax,sz //ne deplasam la urmatorul element din linia i

_asm add ebx,sz //ne deplasam la urmatorul element din linia j


_asm loop bucla


_asm mov esp,tempESP //restauram pointerul si baza stivei memorate anterior

_asm mov ebp,tempEBP


return 0;





Contact |- ia legatura cu noi -| contact
Adauga document |- pune-ti documente online -| adauga-document
Termeni & conditii de utilizare |- politica de cookies si de confidentialitate -| termeni
Copyright © |- 2024 - Toate drepturile rezervate -| copyright