joi, 14 iulie 2016

Definirea segmentelor in asamblare.

Forma completă de definire a segmentelor

Se utilizează o declaraţie de forma:
 nume_seg SEGMENT [tip_aliniere][tip_combinare][clasa_seg]
 …
 nume_seg ENDS
Iniţializarea unui registru de segment (DS, ES sau SS) cu un segment declarat trebuie facută de utilizator în
mod explicit în cadrul programului, utilizând pentru aceasta numele segmentului respectiv:
 mov ax, nume_seg
 mov ds, ax
• tip_aliniere - poate fi BYTE, WORD, PARA, PAGE (implicit este PARA), şi arată că adresa de
început a zonei de memorie rezervată segmentului este divizibilă cu 1/2/16/256.
• tip_combinare - este o informaţie pentru editorul de legături care indică raportul dintre acest segment şi
segmente definite în alte module obiect. Acest parametru poate fi:
PUBLIC - arată că acest segment va fi concatenat cu alte segmente cu acelaşi nume, din alte module
obiect, rezultând un singur modul cu acest nume;
COMMON - precizează că acest segment şi alte segmente cu acelaşi nume din alte module vor fi
suprapuse, deci vor începe de la aceeaşi adresă. Lungimea unui astfel de segment va fi lungimea celui
mai mare segment dintre cele suprapuse;
AT <expresie> - segmentul va fi încărcat în memorie la adresa fizică absolută de memorie reprezentată
de valoarea expresiei, care este o valoare de 16 biţi;
MEMORY - segmentul curent de acest tip va fi aşezat în memorie în spaţiul rămas disponibil după
aşezarea celorlalte segmente;
STACK - va concatena toate segmentele cu acelaşi nume, pentru a forma un segment unic; referirea
acestui segment se va face prin SS:SP. Registrul SP va fi iniţializat automat cu lungimea stivei.
• clasa_seg - este un nume cuprins între apostrofuri. Rolul este de a permite stabilirea modului în care se
aşează în memorie segmentele unui program. Două segmente cu aceeaşi clasă vor fi aşezate în memorie
la adrese succesive.
Asocierea segmentelor cu registrele de segment se realizează cu pseudoinstrucţiunea ASSUME:
 ASSUME reg_seg : nume_seg
Unde reg_seg poate fi unul dintre registrele CS, DS, ES sau SS, iar nume_seg este numele unui segment sau
al unui grup de segmente, care va fi adresat de registrul respectiv.
Definirea grupurilor de segmente se realizează cu directiva GROUP, care are următoarea formă:
 nume_grup GROUP lista_nume_segmente
unde nume_grup este numele grupului de segmente, ce va fi folosit pentru a determina adresa de segment
utilizată pentru referirea în cadrul grupului de segmente, iar lista_nume_segmente poate conţine 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.
Exemplu:
 data1 segment
 v1 db 5
 data1 ends
 data2 segment
 v2 dw 25
 data2 ends
 data3 segment
 v3 dw 100
 data3 ends
 dgrup group data1, data2
 cod segment
 assume cs:cod, ds:dgrup, es:data3
 start: mov ax, dgrup
 mov ds, ax
 mov ax, data3
 mov es, ax
 ;referiri la date
 mov bx, v1 ;se utilizează DS pentru ca a fost asociat cu dgrup
 add v3, bx ;se utilizează ES pentru ca a fost asociat cu segmentul data3
 cod ends
 end start

2. Forma simplificată de definire a segmentelor

Această modalitate de definire a segmentelor respectă acelaşi format ca şi la programele dezvoltate în
limbaje de nivel înalt.
.MODEL tip_model
Prin această directivă se specifică dimensiunea şi modul de dispunere a segmentelor în memorie. Modelul
de memorie poate fi:
- tiny - toate segmentele (date, cod, stivă) formează un singur segment de cel mult 64KB. Apelurile de
procedură şi salturile sunt de tip NEAR şi se folosesc adrese efective (offset) pentru accesarea
datelor;
- small - datele şi stiva formează un segment şi codul un alt segment. Fiecare din acestea va avea
dimensiunea maxima de 64KB. Apelurile de procedură şi salturile sunt de tip NEAR şi se folosesc
adrese efective (offset) pentru accesarea datelor;
- medium - datele şi stiva sunt grupate într-un singur segment (cel mult egal cu 64KB), dar codul poate
fi în mai multe segmente, deci poate depăşi 64KB. Apelurile de procedură şi salturile sunt implicit de
tip FAR şi se folosesc adrese efective (offset) pentru accesarea datelor;
- compact - codul generat ocupă cel mult 64KB, dar datele şi stiva pot fi în mai multe segmente (pot
depăşi 64KB). Apelurile de procedură şi salturile sunt de tip NEAR şi se folosesc adrese complete
(segment şi offset) pentru accesarea datelor aflate în alte segmente;
- large - atât datele cât şi codul generat pot depăşi 64KB. Apelurile de procedură şi salturile sunt
implicit de tip FAR şi se folosesc adrese complete (segment şi offset) pentru accesarea datelor aflate
în alte segmente;
- huge - este asemănător modelului large, dar structurile de date pot depăşi 64KB. La modelele
compact şi large, o structură compactă de date (de tip tablou) nu poate depăşi limitele unui segment
fizic (64KB); la modelul huge, această restricţie dispare.
.STACK [dimensiune]
Această directivă alocă o zonă de memorie de dimensiune specificată pentru segmentul de stivă. Dacă nu se
specifică parametrul dimensiune, aceasta va fi implicit de 1KB.
.CODE [nume]
Această directivă precede segmentul de cod. Încărcarea adresei acestui segment în registrul CS se face
automat de către sistemul de operare, la încărcarea segmentului pentru execuţie. Opţional se pot asocia
nume (maxim 6 caractere) pentru segmentele de cod.
.DATA
Această directivă precede segmentul de date. Utilizatorul trebuie să iniţializeze, în mod explicit, registrul de
segment DS, cu adresa segmentului de date. Simbolul @data primeşte adresa segmentului de date după
linkeditare.

3. Definirea structurilor. Operaţii specifice

Structurile reprezintă colecţii de date plasate succesiv în memorie, grupate sub un unic nume sintactic.
Dimensiunea unei structuri este suma dimensiunilor câmpurilor componente. Forma generală este:
 nume_structura STRUC
 nume_membru definitie_date
 nume_structura ENDS
Tipul structurii se defineşte fără a se rezerva spaţiu de memorie. Numele membrilor structurii trebuie să fie
distincte, chiar dacă aparţin unor structuri distincte. Iată un exemplu de definiţie a unei structuri:
 alfa struc
 a db ?
 b dw 1111H
 c dd 1234
 alfa ends
O structură definită este interpretată ca un tip nou de date, care poate apoi participa la definiţii concrete de
date, cu rezervare de spaţiu de memorie. De exemplu, putem defini o structură de tipul alfa, cu numele x:
 x alfa <, , 777>
în care alfa este tipul de date, x este numele variabilei, iar între paranteze unghiulare se trec valorile iniţiale
ale câmpurilor structurii x. Prezenţa virgulelor din lista de valori iniţiale precizează că primii doi membrii
sunt iniţializaţi cu valorile implicite de la definiţia tipului alfa , iar al treilea membru este iniţializat cu
valoarea 777. Astfel, definiţia variabilei x este echivalentă cu secvenţa de definiţii:

 a db ?
 b dw 1111H
 c dd 777
Principalul avantaj al structurilor este accesul la membri într-o formă asemănătoare limbajelor de nivel
înalt. De exemplu, pentru a încărca în SI câmpul b al structurii x, putem scrie:
 mov si, x.b
Putem acum defini un tablou de 5 structuri de tip alfa:
 tab alfa 5 dup (<, , 10>)
în care primii 2 membri sunt iniţializaţi cu valorile de la definiţia tipului structurii, iar al treilea cu valoarea

3.1 Având în vedere că o dată de tip alfa ocupă 7 octeţi:

- tab[0].a se referă la câmpul a al primei structuri;
- tab[7].c se referă la câmpul c al celei de-a doua structuri;
- tab[14].a se referă la câmpul a al celei de-a treia structuri;
- tab[21].b se referă la câmpul b al celei de-a patra structuri.

4. Definirea înregistrărilor. Operaţii specifice

Înregistrările corespund de fapt unor structuri împachetate din limbajele de nivel înalt. Concret, o
înregistrare este o definiţie de câmpuri de biţi de lungime maximă 8 sau 16. Forma generală este:
 nume_inregistrare RECORD nume_camp:valoare [= expresie], …
unde valoare reprezintă numărul de biţi pe care se memorează câmpul respectiv. Opţional poate fi folosită o
expresie a cărei valoare să fie asociată câmpului respectiv, pe numărul de biţi precizat. La fel ca la structuri,
numele câmpurilor trebuie să fie distincte, chiar dacă aparţin unor înregistrări diferite.
Să considerăm un exemplu:

 beta record x:7, y:4, z:5
prin care se defineşte un şablon de 16 biţi, x pe primii 7 biţi (mai semnificativi), y pe următorii 4 biţi, şi z pe
ultimii 5 biţi (mai puţin semnificativi). La fel ca la structuri, putem acum defini variabile de tipul
înregistrării beta:
 val beta <5, 2, 7>
în care valorile dintre parantezele unghiulare iniţializează cele trei câmpuri de biţi. Această definiţie este
echivalentă cu definiţia explicită:
 val dw 0000101001000111B
Operatorul MASK primeşte un nume de câmp şi furnizează o mască cu biţii 1 pe poziţia câmpului respectiv
şi 0 în rest. Astfel, expresia MASK y este echivalentă cu constanta binară 0000000111100000B.
Operatorul WIDTH primeşte un nume de înregistrare sau un nume de câmp şi întoarce numărul de biţi ai
înregistrării sau ai câmpului respectiv. De exemplu, secvenţa:
 mov al, width beta
 mov bl, width y
va încărca în AL 16 şi în BL valoarea 4.

5. Macroinstrucţiuni

Macroinstrucţiunile permit programatorului să definească simbolic secvenţe de program (instrucţiuni,
definiţii de date, directive, etc.), asociate cu un nume. Folosind numele macroinstrucţiunii în program, se va
genera întreaga secvenţă de program. În esenţă, este vorba de un proces de substituţie (expandare) în textul
programului, care se petrece înainte de asamblarea programului. Spre deosebire de proceduri,
macroinstrucţiunile sunt expandate la fiecare utilizare. Forma generală a unei macroinstrucţiuni este:
 nume_macro MACRO [p1, p2, …,pn]
 …
 ENDM
Opţional, macroinstrucţiunile pot avea parametri, în acest caz, p1, p2, …, pn sunt identificatori care
specifică parametrii formali. Apelul unei macroinstrucţiuni constă în scrierea în program a numelui
macroinstrucţiunii. Dacă macroinstrucţiunuea are parametri, apelul se face prin specificarea numelui,
urmată de o listă de parametri actuali:
 nume_macro x1, x2, …, xn
La expandarea macroinstrucţiunii, pe lângă expandarea propriu-zisă, se va înlocui fiecare parametru formal
cu parametrul actual corespunzător.

I. Aplicaţii
1. Se consideră următoarea definiţie de date:
alfa struc
 a1 db ?
 a2 db 21H
 a3 dw 5176H
alfa ends
tab alfa 10 dup (<3H, ?, 2252H>)
Care va fi conţinutul registrului AL după executarea următoarelor instrucţiuni?
a) mov al, byte ptr tab[12].a2
b) mov al, byte ptr tab[11].a2

2. Să se definească o macroinstrucţiune care realizează adunarea a două valori pe 32 de biţi. Să se scrie şi un exemplu de apelare al macroinstrucţiunii definite.

Niciun comentariu:

Trimiteți un comentariu