NOTA: Referatul contine un exemplu de program ce calculeaza maximul intr-un sir de numere intregi, cu semn, reprezentate pa cate un octet !
INTRODUCERE
AVANTAJELE PROGRAMARII IN ASM
Exista, intr-adevar, o tendinta justificata de indepartare de limbajul de asamblare, dar nu de renuntare la el, intrucat multe medii integrate de dezvolare de programe (IDE - Integrated Development Enviroments) si compilatoare de limbaje de nivel inalt (C, Pascal, Basic, Fortran, etc.) prezinta facilitati de inserare de linii scrise direct in limbaj de asamblare.
Prezentarea posibilitatilor oferite de limbajele de programare:
Cu toate acestea, exista si numeroase componente ale sistemului de operare si ale altor aplicatii, care sunt considerate critice si performante, iar acestea au fost si mai sunt realizate in limbaj de asamblare, deoarece aceste secvente trebuie sa consume cat mai putin timp si, eventual, cat mai putina memorie. Aceasta performanta este realizata prin utilizarea cat mai eficienta a instructiunilor si a structurii procesorului.
In concluzie, la ora actuala programele sunt hibride: ele contin linii scrise in limbaje de nivel inalt, dar pot contine si linii in limbaj de asamblare. Pentru a rezolva astfel de situatii, implementarile limbajelor de nivel inalt accepta introducerea in textul sursa de linii scrise in limbaj de asamblare sau legarea intr-un singur modul a unor module obiect provenite de la compilarea unor texte sursa, scrise in diverse limbaje de programare. Modulele care presupun algoritmi complicati sau structuri de date complexe sunt scrise in limbaje de nivel inalt, iar cele care sunt critice din puctul de vedere al timpului de executie si al resurselor ocupate sunt scrise in limbaj de asamblare. In plus, exista anumite resurse ale calculatorului la care accesul nu este realizabil din limbajele de nivel inalt.
Un alt motiv pentru care se recomanda si experienta programarii in limbaj de asamblare este acela ca un specialist in informatica trebuie sa cunoasca mecanisele fine ale procesorului pntru a le folosi in diferite aplicatii.
De asemenea, uneori, depanarea unui program poate trece de textul sursa si ajunge la depanarea codului obiect, caz in care este necesara cunoasterea libajului de asamblare.
Motivul pentru care secventele critice, ca timp de executie si resurse, se scriu in limbaj de asamblare si nu in limbaje de nivel inalt, este urmatorul: compilatorul are "cunostinte limitate" asupra intregului program, dar el trebuie a genereze un set generalizat de instructiuni masina , care vor lucra in toate sitatiile, dar nu vor fi optime in situatii particulare.
Programarea in limbaj de asamblare este mult mai dificila decat cea intr-un limbaj de nivel inalt, deoarece programatorul trebuie sa cunoasca, pe langa limbajul de asamblare, si structura interna a calculatorului ( registre, organizarea si adresarea memoriei, porturi de intrare-iesire, etc.)
Limbajul de asamblare (ASM) permite intelegerea la nivel de amanunt a ceea ce se intampla in realitate intr-un calculator. Codul generat in ASM se executa foarte rapid.si permite accesul la hardware, acces care nu este disponibil in limbajele de nivel inalt.
Unitatea de baza a informatiei memorate in calculator este bitul. Un bit reprezinta o cifra binara, deci poate avea valorile 0 sau 1. Modelul hardware corespunzator este acela de bistabil. Un bistabil este, deci un circuit electronic cu doua stari stabile, configurate 0 sau 1 , capabil sa memoreze un bit de informatie.
Un grup de bistabili formeaza un registru. De exemplu, 8 bistabili formeaza un registru de 8 biti. Iformatia care se poate memora intr-un asemenea registru poate fi codificata binar, de la valoarea 0000.0000, pana la valoarea 1111.1111. Numarul combinatiilor care pot fi memorate este 256 (). Aceste combinatii se numesc octeti sau bytes (daca n=8), respectiv cuvinte (daca n=16, 32, etc.).
Memoria unui calculator este vazuta ca o succesiune de octeti. Fiecare octet are asociata o adresa de memorie. Pentru a adresa memoria, e nevoie de un registru de adrese a carui lungime determina dimensiunea maxima a memoriei. Zonele de memorie vor fi reprezentate grafic pe verticala, ca succesiuni de octeti sau cuvinte, de la adrese mici catre adrese mari.
Tipurile de date sunt:
Byte (1 octet) - ocupa un octet si poate fi reprezentat atat in memoria interna cat si intr-un registru de 8 biti al procesorului. Interpretarile tipului byte pot fi:
# intreg pe 8 biti;
# caracterASCII.
Directiva pentru definirea datelor de acest tip este db (define byte).
Word (2 octeti) - ocupa doi octeti si poate fi reprezentat atat in memoria interna cat si intr-un registru de 16 biti al procesorului. Interpretarile tipului word pot fi:
# intreg pe 16 biti cu sau fara semn;
# secventa de doua caractere ASCII;
# adresa de memorie de 16 biti.
Directiva pentru definirea datelor de acest tip este dw (define word).
Double Word (4 octeti) - ocupa 4 octeti si poate fi reprezentat atat in memoria interna cat si intr-opereche de registre de 16 biti ale procesorului sau intr-un registru de 32 biti. Interpretarile tipului dword pot fi:
# intreg pe 32 biti cu sau fara semn:
# numar real in simpla precizie;
# adresa de memorie de 32 biti.
Directiva pentru definirea datelor de acest tip este dd (define double word).
Quand Word (8 octeti) - ocupa 8 octeti si poate fi reprezentat atat in memoria interna cat si
intr-o pereche de registre de 32 biti. Interpretarile tipului qword pot fi:
# intreg pe 64 biti cu sau fara semn;
# numar real in dubla precizie.
Directiva pentru definirea datelor de acest tip este:dq (define quand word).
Ten Bytes (10 octeti) - ocupa 10 octeti si poate fi reprezentat atat in memoria interna cat si intr-unul din registrele coprocesoarelor matematice 80x87. Interpretarile tipului tbyte pot fi:
# numar intreg reprezentat ca secventa BCD;
# numar real in precizie extinsa.
Directiva pentru definirea datelor de acest tip este dt (define ten bytes).
Sistemul de operare MS-DOS permite doua formate de memorare a programelor, pe suport extern, pentru programele executabile, si anume formatele .EXE si .COM.
In cazul formatului .EXE fisierul contine programul intr-un format realocabil, precum si un antet care contine informatii necesare pentru realocare. Formatul .COM, caracterizat prin faptul ca programul - inclusiv datele si stiva - nu ocupa mai mult de un segment, contine o imagine memorie a programului.
Acest program trebuie sa inceapa cu directiva ORG 100H, deoarece toate registrele sunt pozitionate pe adresa de inceput a prefixului de program (PSP); adresa de start a programului este la aceasta adresa, si eticheta acesteia este precizata in directiva END. Datele pot fi plasate oriunde in segment, dar, de obicei, se plaseaza la inceput. Stiva este initializata, automat, la sfarsitul segmentului ocupat de program. Programul se poate incheia cu instructiunea INT 20H sau RET.
Fisierul ce contine un astfel de program este cu cel putin 768 octeti mai mare decat programul executabil; insa, la incarcarea in memorie pentru executie, el va ocupa acelasi spatiu. Registrele DS si ES sunt initializate cu adresa de segment corespunzatoare inceputului de prefix de program; CS este initializat la inceputul programului, deci dupa prefix, si deci va fi cu 10H mai mare decat acestea. Registrele segment DS, ES si SS, precum si registrul SP, trebuiesc initializate de utilizator, conform programului.
Incheierea unui program .EXE se face prin executia unei instructiuni RET, in context FAR; aceasta va realiza un salt la prima instructiune din prefixul programului, adica se va executa inaintea instructiunii INT 20H.
Secventa de executie a instructiunilor dintr-un program este determinata de continutul registrului de segment de cod (CS) si de pointerul de instructiuni (IP). Instructiunile de transfer al controlului programului opereaza asupra lui IP si CS. La aparitia unui astfel de transfer, coada de instructiuni nu mai contine instructiunea urmatoare si EU va transmite noua adresa la BU, care va obtine instructiunea urmatoare direct din memorie, utilizand noile valori pentru CS:IP; instructiunea va fi transferata catre IU si UE pentru executie si BU, apoi incepe reumplerea cozii de la noua locatie.
Exista patru tipuri de instructiuni de transfer al controlului:
Forma generala a instructiunii este:
Instructiunile de transfer conditionat pot transfera sau nu controlul, in functie de indicatorii procesorului, in momentul executiei instructiunii. Cele 18 tipuri de instructiuni de salt conditionat trateaza o anumita configuratie de indicatori. Cand conditia este indeplinita (true) controlul este transferat la tinta specificata de instructiune. Toate salturile conditionate sunt de tip SHORT, adica tinta trebuie sa fie in segmentul de cod curent, in intervalul de [-128,+127] octeti fata de instructiunea de transfer (de exemplu JMP 00 realizeaza saltul la primul octet al urmatoarei instructiuni). La 386/486 aceste instructiuni permit si realizarea ununi salt de tip NEAR, adica in cadrul aceluiasi segment (64 Ko sau 4 Go in functie de atributul de dimensiune a adresei).
Deoarece asdresa de salt este determinata prin adunarea deplasamantului relativ al tintei la pointerul IP actualizat, toate salturile conditionate sunt auto-relative. Deplasamentul poate fi octet la 286 (la tipul SHORT), cuvant sau cuvant dublu la 386, si este considerat numar cu semn. In cazul cand se doreste un salt conditionat pe o distanta mai mare de 128 octeti, la 286, sau un salt conditionat (pentru conditia negata, de exemplu JE, pentru JNE), in intervalul [-128,+127], iar, imediat dupa instructiunea de salt conditionat, o instructiune de salt neconditionat pe distanta dorita.
Instructiunile de salt conditionat se utilizeaza dupa o instructiune aritmetica sau logica, care modifica indicatorii conform rezultatului. De cele mai multe ori, ele se utilizeaza dupa o instructiune de comparare: cmp (d),(s).
Instructiunile de salt conditionat sunt listate in tabela urmatoare:
Instructiunile listate ca perechi reprezinta aceleasi instructiuni; asamblorul furnizeaza mnemonici alternative pentru o mai mare claritate in cadrul programului. Aceste mnemonici pot fi determinate relativ usor deoarece ele utilizeaza anumite litere cu o semnificatie predefinita astfel:
A - provine de la Above, adica mai mare (deasupra);
B - provine de la Below, adica mai mic (dedesupt);
G - Greater, deci mai mare, si
L - Less, deci mai mic.
Primele doua (A si B) se refera la relatia dintre doua valori fara semn, in timp ce ultimele doua (G si L) se refera la relatia dintre doua valori cu semn.
Ultima instructiune J(E)CXZ (salt daca ECX sau CX=0) se utilizeaza de obicei la inceputul unei bucle software, penru a sari peste ciclul respectiv, in cazul in care inca de la inceput (E)CX=0, altfel ciclul respectiv (cu instructiunea LOOP) s-ar efectua de 64 K ori (sau la 386/486 de 4 G ori). Pentru aceasta instructiune, deplasamentul nu poate fi precizat decat pe 8 biti atat pentru 286, cat si pentru 386; deci si in cazul lui 386/486 saltul realizat de aceasta instructiune este de tip SHORT.
Instructiunea de comparare a doua valori pozitioneaza, bineinteles, toti indicatorii, dar in functie de interpretarea data de utilizator celor doua valori, sunt semnificativi numai anumiti indicatori, in functie de tipul numerelor:
In compararea a doua numere, in scopul de a realiza saltul pentru o anumita conditie data, se vor folosi urmatoarele instructiuni:
APLICATIE PRACTICA
*** Sa se gaseasca maximul intr-un sir de numere intregi, cu semn, reprezentate pe cate un octet:
.model small ; precizeaza un model de memorie
.stack 10h ; definire segment de stiva
.data
sir db 10, 20, -30, 100, -100, 200 ; definire
lung dw $-sir ; segment
maxim dw ? ; de
mes_sir_vid db 'sir vid de valori$' ; date
.code
mov ax,@data ; initializare registru segment
mov ds,ax ; setarea registrului DS ca pointer la seg. date
mov cx,lung ; contor numar de valori din sir
jcxz sir_vid ; daca sirul este vid se tipareste mesaj
lea si,sir ; index elemente din sir
cld ; directia de parcurgere
mov b1,[si] ; se initializeaza valoarea maxima din sir
inc si ; actualizare index elemente
dec cx ; actualizare contor
jcxz gata ; daca a fost un singur element s-a terminat
iar: lodsb ; citeste element curent din sir
cmp b1,a1 ; se compara cu maximul curent
jge urm ; daca maximul > decat valoarea curenta se
; trece la elementul urmator
mov b1,a1 ; se actualizeaza valoarea maxima
urm: loop iar ; se reia ciclul daca mai sunt elemente in sir
gata: mov maxim,b1 ; se depune valoarea maxima
aut: mov ax,4c00h ; revenire in DOS
int 21h ; terminarea programului
sir_vid: lea dx, mes_sir_vid ; se tipareste mesajul
mov ah,9 ; 'sir vid de valori'
int 21h ; afisarea mesajului
jmp aut ; revenire in DOS
end
permite introducere comentariu
OBS: Programul poate fi rulat, editandu-se si salvandu-se mai intai in editorul de DOS. De la prompterul DOS se vor introduce liniile de comanda: 1 tasm (cale ~ nume fisier), 2 tlink (cale ~ nume fisier), 3 td (permite vizualizarea si corectarea erorilor).