CATEGORII DOCUMENTE |
In continuare se prezinta acele componente ale unui procesor care sunt vizibile si accesibile pentru un programator in limbaj de asamblare. Astfel, un procesor dispune de un set de registre interne folosite pentru pastrarea temporara a datelor, a adreselor sau a instructiunilor. Exista registre generale folosite in majoritatea operatiilor aritmetico-logice si registre speciale, care au o destinatie speciala.
La arhitectura ISA x86 pe 16 biti exista 8 registre generale pe 16 biti, registre denumite in felul urmator: AX, BX, CX, DX, SI, DI, BP, SP. Dintre acestea primele patru se folosesc cu precadere in operatii aritmetico-logice pentru pastrarea operanzilor, iar urmatoarele patru mai ales pentru pastrarea si calculul adreselor de operanzi. Primele patru registre se pot adresa si pe jumatate, adica la nivel de octet. Astfel fiecare registru are o parte superioara 'HIGH' (bitii D15-D8) si o parte inferioara 'LOW' (bitii D7-D0). Denumirea lor este AH si AL pentru registrul AX, BH si BL pentru registrul BX si asa mai departe.
La procesoarele pe 32 de biti (incepand de la '386) aceste registre s-au extins la 32 de biti. Astfel registrele pot fi adresate pe 32 de biti (cu denumirile EAX,EBX, ECX, ESP) sau in mod uzual pe 16 sau 8 biti. Partea superioara a unui registru pe 32 de biti (D31-D16) nu se poate adresa individual.
In principiu registrele generale respecta principiul de ortogonalitate, adica pentru majoritatea operatiilor oricare registru este utilizabil. La unele procesoare (ex: procesoarele Motorola) acest principiu este respectat strict. In cazul procesoarelor Intel anumite operatii speciale impun utilizarea anumitor registre, ceea ce inseamna ca exista o oarecare specializare intre registre. Aceasta specializare decurge de multe ori si din denumirea registrelor. Astfel:
registrul AX (EAX in varianta pe 32 de biti) - se foloseste ca registru 'acumulator' in majoritatea operatiilor aritmetice si logice, adica pastreaza unul dintre operanzi si apoi rezultatul operatiei; la operatiile de inmultire si impartire in mod obligatoriu primul operand si rezultatul se pastreaza in acest registru
registrul BX (EBX) - se foloseste pentru in operatii aritmetico-logice sau pentru calculul adresei operandului la 'adresarea bazata'
registrul CX (ECX) - se foloseste pentru operatii aritmetico-logice sau in mod implicit, la anumite instructiuni (ex: instructiuni de buclare), pe post de contor
registrul DX (EDX) - se foloseste pentru operatii aritmetico-logice sau pentru pastrarea adresei porturilor la instructiunile de intrare/iesire; de asemenea la operatiile de inmultire si impartire se foloseste ca extensie a registrului acumulator
registrele SI si DI (ESI, EDI) - denumite si registre index, se folosesc cu precadere pentru calculul adresei operanzilor la 'adresarea indexata'; SI adreseaza elementele sirului sursa (source index), iar DI elementele sirului destinatie (destination index)
registrul BP (EBP) - se foloseste cu precadere pentru calculul adresei operanzilor la 'adresarea bazata', alaturi de registrul BX
registrul SP (ESP) - se foloseste aproape in exclusivitate pentru adresarea stivei (stack pointer); continutul registrului se incrementeaza si se decrementeaza automat la orice operatie cu stiva
In afara registrelor generale un procesor mai are si registre speciale sau de control. La procesoarele Intel numai o parte din aceste registre sunt vizibile si accesibile pentru programator. Aceste registre controleaza regimul de lucru al procesorului, sau permit efectuarea unor operatii speciale de manipulare a spatiului de memorie.
Arhitectura ISA x86 opereaza cu urmatoarele registre speciale:
registrul PC - 'program counter' - pastreaza adresa instructiunii care urmeaza; nu este adresabil direct (prin nume) dar continutul sau se poate modifica prin executia instructiunilor de salt
registrul PSW - 'program status word' - pastreaza indicatorii de stare ai procesorului;
o o parte din indicatori caracterizeaza rezultatul obtinut in urma unei anumite instructiuni:
ZF - rezultat 0,
SF - semnul rezultatului
OF - 'overflow' indica o depasire de capacitate la ultima operatie aritmetica
PF - indicator de paritate (arata paritatea rezultatului)
CF - indicator de transport ('carry'), arata daca s-a generat un transport
AC - indicator de transport auxiliar, arata daca dupa primii 4 biti s-a generat un transport
o o parte din indicatori controleaza modul de lucru al procesorului:
IF - indicator de intrerupere (interrupt'), daca este setat (1 logic) atunci se blocheaza toate intreruperile mascabile, in caz contrar (0 logic) se valideaza
DF - indicatorul de directie, arata directia de parcurgere a sirurilor de caractere la instructiunile pe siruri (in ordine ascendenta sau descendenta a adreselor)
registrele de segment - se utilizeaza pentru calculul adresei operanzilor si a instructiunilor; cu ajutorul lor memoria este divizata in segmente; exista 4 registre segment in versiunea initiala ISA x86 si 6 registre segment in versiunea pe 32 de biti:
o registrul CS - registrul segment de cod, folosit pentru adresarea instructiunilor (a codurilor); acest registru pastreaza adresa de inceput (descriptorul in varianta extinsa) pentru segmentul de cod (segmentul unde se afla programul)
o registrul DS - registrul segment de date, folosit pentru adresarea operanzilor din memorie; acest registru pastreaza adresa de inceput (sau descriptorul) pentru segmentul de date
o registrul SS - registrul segment de stiva, folosit pentru adresarea memoriei stiva; pastreaza adresa de inceput (descriptorul) segmentului unde se afla organizata stiva
o registrul ES - registrul extra-segmentului de date, folosit pentru pastrarea adresei celui de al doilea segment de date
o registrele FS si GS - registre segment introduse incepand de la versiunea '386 si care se folosesc pentru adresarea operanzilor
Versiunile mai noi de procesoare contin si alte registre speciale, dar acestea au o importanta mai mica pentru un programator obisnuit. Ele vor fi introduse pe parcurs in momentul in care acest lucru va fi necesar.
Arhitectura ISA x86 promoveaza o modalitate originala de organizare a memoriei. Spatiul de memorie este divizat in regiuni de numite segmente, iar adresa unei locatii de memorie se exprima printr-o pereche de adrese: <adresa de segment>:<adresa de offset>. Adresa de segment indica punctul de inceput al unei zone de memorie, iar adresa de offset adresa relativa a locatiei cautate in raport cu inceputul de segment. La aceasta solutie s-a ajuns atat datorita unor cauze obiective cat si datorita unor limitari tehnologice care ulterior au fost depasite (ex: generarea unei adrese pe 20 de biti folosind doar registre pe 16 biti).
Adresarea pe segmente a memoriei are urmatoarele avantaje:
adresa relativa in cadrul segmentului (adresa de offset) se exprima pe un numar mai mic de biti; astfel instructiunile care contin adrese sunt mai scurte
incarcarea si reamplasarea programelor si a datelor este mai simpla deoarece adresele relative raman aceleasi
exista posibilitatea protejarii diferitelor zone de memorie pe baza de continut si functie de drepturile de acces
se pot incarca in memorie numai acele segmente ale unei aplicatii care sunt strict necesare
un sistem de operare de tip multi-tasking sau multi-utilizator are nevoie in mod obligatoriu de un sistem de partajare si de protectie a zonelor de memorie
La ISA x86 tehnica de segmentare folosita depinde de modul de lucru al procesorului: modul real sau modul protejat. La primele variante de procesoare exista numai modul real; ulterior, pentru a oferi suport pentru multitasking si pentru a creste spatiul de adresare s-a introdus modul protejat. In majoritatea cazurilor programele scrise de programatorii obisnuiti folosesc modelul initial de segmentare, desi procesorul lucreaza in modul protejat. Acest lucru este posibil prin faptul ca programul poate sa ruleze intr-un al treilea mod, modul virtual, care este o simulare a modului real pe un procesor aflat in modul protejat. In mod uzual operatiile care afecteaza functionarea in modul protejat sunt efectuate numai de rutine ale sistemului de operare. Mai mult alocarea memoriei este responsabilitatea sistemului de operare. utilizatorul obisnuit are senzatia lucrului in modul real, mod care este mult mai simplu.
In modul real spatiul maxim de adresare al memoriei este de 1Moctet. Aceasta memorie este impartita in segmente de lungime fixa de 64Kocteti. Adresa de inceput a unui segment se pastreaza in unul din cele patru registre segment. Deoarece un registru segment are doar 16 biti, in el se pastreaza doar partea mai semnificativa a adresei de segment, ultimii 4 biti considerandu-se in mod implicit 0. Adresa fizica a unei locatii de memorie se calculeaza ca o suma intre adresa de segment si o adresa de offset. Adresa de segment se obtine prin multiplicarea continutului registrului segment cu 16 (deplasarea la stanga cu 4 pozitii binare). Adresa de ofset se calculeaza pe baza modului de adresare si eventual a adresei continute in codul de instructiune. Prin adunare se obtine o adresa fizica pe 20 de biti, suficienta pentru adresarea unui spatiu de 1 Mocteti (1M=220). In exemplul de mai jos, pentru claritate, valorile de adrese sunt exprimate in hexazecimal.
Adresa de segment
Acest mod de calcul a adresei fizice are cateva consecinte:
spatiul maxim de adresare este 1Mo
un segment trebuie sa inceapa la o adresa multiplu de 16
un segment are maxim 64ko
segmentele se pot suprapune partial sau total
aceeasi locatie fizica se poate exprima prin mai multe variante de perechi de adrese (segment:offset)
exista putine posibilitati de protejare a zonelor de memorie
orice program poate adresa orice locatie de memorie, neputandu-se impune restrictii (lucru nedorit intr-un sistem multitasking)
Cele patru registre segment se utilizeaza in mod implicit functie de tipul de informatie care se adreseaza:
CS - pentru adresarea instructiunilor
DS - pentru adresarea datelor
SS - pentru adresarea stivei
ES - in anumite cazuri speciale pentru adresarea sirurilor
Programatorul poate solicita in mod explicit utilizarea unui anumit registru segment prin amplasarea unui prefix cu numele registrului (ex: ES:) in fata operandului adresat. In mod uzual insa compilatorul este cel care detecteaza daca utilizarea explicita a unui registru segment este necesara (de exemplu o variabila nu se afla in segmentul indicat de registrul DS).
Modul protejat s-a introdus odata cu procesorul '386 si apoi s-a perfectionat la procesorul '486. Acest mod a fost necesar pentru a solutiona limitarile modului real, in special in ceea ce priveste spatiul limitat de adresare si posibilitatile reduse de protectie.
In modul protejat exprimarea adresei se face la fel prin adresa de segment si adresa de offset, insa cu anumite amendamente:
un registru segment pastreaza un selector de segment si nu adresa de inceput a segmentului;
selectorul este un indicator care arata locul unde se afla o structura de date care descrie un segment si care poarta numele de descriptor de segment
un descriptor de segment contine: adresa segmentului (pe 32 de biti) lungimea segmentului (pe 20 de biti), indicatori pentru determinarea drepturilor de acces si indicatori care arata tipul si modul de utilizare a segmentului
adresa de offset se exprima pe 32 de biti
Aceste modificari genereaza urmatoarele consecinte:
spatiul maxim de adresare al memoriei se extinde la 4Gocteti (4G = 232)
un segment are o lungime variabila, in interval larg de la 1 octet la 4Gocteti
se definesc trei nivele de protectie (0, cel mai prioritar)
un segment este accesibil numai taskului alocat si eventual sistemului de operare
anumite segmente pot fi blocate la scriere (ex: segmentele de cod)
rezulta un mecanism complex de alocare si de protectie a zonelor de memorie
Scopul lucrarii este prezentarea formatului instructiunilor in limbaj de asamblare, a principalelor pseudoinstructiuni pentru lucrul cu segmente si rezervare a datelor precum si a structurii programelor executabile de tip .COM si .EXE
Formatul instructiunilor
O instructiune se poate reprezenta pe o linie de maxim 128 caractere, avand forma generala:
[<eticheta>:] [<codop>[<operanzi>][;<comentarii>]]
unde:
<eticheta> un nume, maxim 31 caractere (litere, cifre sau caractere speciale _,?,@,..), primul caracter fiind litera sau unul din caracterele speciale. Fiecare eticheta are asociata o valoare si anume adresa relativa in segmentul din care face parte
<codop> mnemonica instructiunii
<operanzi> operandul (sau operanzii) asociat instructiunii conform sintaxei cerute de aceasta. Poate fi o constanta, un simbol sau expresii continand acestea
<comentarii> un text oarecare precedat de caracterul ";"
Este permisa inserarea de linii goale si a unui numar oarecare de spatii. Aceste facilitati se folosesc pentru asigurarea lizibilitatii programului
Specificarea constantelor
Constante numerice - se prezinta sub forma unui sir de cifre, prima fiind intre 0 si 9 (daca de exemplu numarul este in hexa si incepe cu un caracter, se va pune un zero in fata acestuia). Baza numarului se specifica printr-o litera la sfarsitul numarului (B pentru binar, Q pentru octal, D pentru zecimal si H pentru hexa; fara o specificatie explicita, numarul se considera in zecimal).
Exemple: 010010100B, 26157Q (octal), 7362D (sau 7362), 0AB3H.
Constantele caracter sau siruri de caractere se specifica intre ghilimele sau apostrof.
Exemple: "sir de caractere", 'sir de caractere'
Etichete
Etichetele (label) se pot defini numai pe zona de program si pot fi operanzi la instructiunile CALL sau JMP
Atributele etichetelor sunt:
segmentul (de regula CS) este adresa paragrafului unde incepe segmentul care contine eticheta. Cand se face referire la eticheta, valoarea se gaseste in CS (valoarea efectiva se stie numai in timpul rularii)
offset-ul este distanta in octeti a etichetei fata de inceputul segmentului in care acesta a fost definit
tipul determina modul de referire la eticheta; exista doua tipuri: NEAR si FAR. Referirea de tip NEAR este in segment (numai offset) iar cea de tip FAR precizeaza si segmentul (segment : offset).
Etichetele se definesc la inceputul liniei sursa. Daca dupa eticheta urmeaza caracterul ":" atunci va fi de tip near.
Variabile
Definirea variabilelor (eticheta de date) se poate face cu pseudooperatori de rezervare a spatiului.
Atributele variabilelor sunt:
- Segment si offset - ca si la etichete, cu deosebirea ca pot fi si alte registre segment
- tipul - este o constanta care arata lungimea (in octeti) a zonei rezervate:
BYTE(1), WORD(2), DWORD(4), QWORD(8), TWORD(10), STRUC (definita de utilizator), RECORD (2).
Exemple:
mov al,dat ; al<-0fh
mov ax,datw ; al<-0fh, ah<-07h
mov ax,dat ; eroare de tip
Expresii
Expresiile se definesc prin constante, simboluri, pseudooperatori si operatori (pentru variabile se considera numai adresa si nu continutul, deoarece la compilare se cunoaste doar adresa)
Pseudoinstructiuni de lucru cu segmente
Orice segment este identificat de un nume si o clasa, ambele specificate de utilizator. La definire segmentele primesc o serie de atribute care specifica pentru asamblor si editorul de legaturi relatiile dintre segmente.
Definirea segmentelor se face cu secventa:
nume_seg SEGMENT [align_type] [combine type] ['class']
nume_seg ENDS
unde:
nume_seg - este numele segmentului ales de utilizator. (numelui i se asociaza o valoare - la executie - corespunzator pozitiei segmentului in memorie)
align_type - este tipul de aliniere a segmentului (in memorie). Poate sa ia valorile
PARA (aliniere la paragraf, multiplu de 16 octeti)
BYTE (aliniere la octet)
WORD (aliniere la cuvant)
PAGE (aliniere la pagina - multiplu de 256 octeti)
combine_type - este de fapt tipul segmentului si reprezinta o informatie pentru link-editor specificand in ce raport sunt segmentele cu acelasi nume. Poate fi:
PUBLIC - specifica concatenarea
COMMON - specifica suprapunerea
AT expr - specifica incarcarea segmentului la adresa expr*16
STACK - arata ca segmentul curent va face parte din segmentul stiva
MEMORY - specifica asezarea acestui segment ca ultimul segment din program
'class' - este clasa segmentului; editorul de legaturi dispune continuu segmentele cu aceeasi clasa in ordine aparitiei. Se recomanda utilizarea claselor 'code', 'data', 'constant', 'memory', 'stack'.
Desemnarea segmentului activ
Intr-un program pot fi definite mai multe segmente (de date si de cod). Asamblorul verifica daca datele sau instructiunile adresate pot fi atinse cu registrul segment avand un anumit continut. Pentru a se realiza acest lucru in conditii bune trebuie sa se comunice asamblorului segmentul activ, adica in registrul segment sa fie adresa segmentului incarcat
ASSUME <reg-seg>:<nume-seg>, <reg_seg>:<nume-seg>
reg-seg - registrul segment
nume-seg - segmentul care va fi activ cu registrul segment respectiv
Exemplu:
ASSUME CS:prg, DS:date1, ES:date2
Observatii:
- pseudoinstructiunea NU pregateste registrul segment ci doar comunica asamblorului in ce segment trebuie cautate simbolurile
- se recomanda ca DS sa fie initializat la inceputul programului si acest lucru sa fie anuntat asamblorului cu secventa tipica:
ASSUME DS:nume_seg_date
MOV AX, nume_seg_date
MOV DS, AX
- CS nu trebuie initializat dar trebuie activat cu ASSUME inainte de prima eticheta
- in loc de nume-seg din ASSUME se poate folosi identificatorul NOTHING daca nu dorim sa asociem registrului nici un segment
Rezervarea zonei de date
De regula datele sunt definite intr-un segment de date. Pseudoinstructiunea de definitie are forma:
<nume> <tip> [lista expresii] [<factor> DUP (<lista expresii>)]
unde:
nume - este numele simbolului (a etichetei de date)
tip este tipul simbolului:
DB - pentru rezervare de octet
DW - pentru rezervare de cuvant (2 octeti)
DD - pentru rezervare de cuvant dublu (4 octeti)
DQ - pentru rezervare de cuvant cvadruplu (8 octeti)
DT - pentru rezervare de 10 octeti
lista expresii - o expresie cu rezultatul careia se initializeaza zona rezervata; se scrie caracterul "?" daca zona nu se va initializa
factor - o constanta care arata de cate ori se repeta expresia de dupa DUP
Exemple:
DAT db 45
dat1 db 45h, 'a', 'A", 85h
dat2 db 'abcdefghi' ; se genereaza textul
lg_dat2 db $-dat2 ; lungimea sirului dat2 ($ este contorul locatiei curente)
aa db 100 dup(56h) ; 100 de octeti cu valoarea 56h
bb db 20 dup (?) ; 20 de octeti neinitializati
ad dw dat1 ; contine adresa (offset-ul) variabilei dat1
adr dd dat1 ; contine adresa (offset + segment) variabilei dat1
var1 db 12h,5, 33, 10101111b
x dw 1234h, 0ff00h
litera byte 'A'
text byte 'TEXT'
dublu dd 12345678h
Corespunzator acestor declaratii, in memorie se vor regasi urmatoarele date:
Lucrarea de laborator
1.Programul trebuie sa calculeze suma unui sir de numere aflat la adresa SIR si lungime specificata in variabila LGSIR; rezultatul va fi in locatia SUMA. (Ex31.asm). Rectificati greseala in codul sursa de mai jos.
.model small
.data
sir db 1,2,3,4
lgsir db $-sir
suma db 0
.stack 512
.code
start: jmp eticheta1
eticheta1:
mov ch,0
mov cl,lgsir ; in cx (contor) lungimea sirului
mov al,0 ; initializarea registrului in care se calculeaza suma
mov si,0 ; initializarea indexului
next:
add al,sir[si] ; adunarea elementului curent
inc si ; trecerea la elementul urmator in sir
loop next ; decrementare cx si salt la urmatorul
; element daca cx diferit de 0
mov suma,al
mov ah,4ch ; terminare program
int 21h
end start
2.Precizati care este functionalitatea programului de mai jos Ex32.asm).
stiva segment stack
db 512 dup(?)
stiva ends
date segment
rez db 8 dup(?)
mes db 'introdu un numar mai mic decat 9 ptr calcul factorial:$'
a3 db 10,13,?,'!(factorial)=$'
date ends
cod segment
assume cs:cod,ds:date,ss:stiva
start:
mov ax,date
mov ds,ax
xor ax,dx
;afisare mesaj
mov ah,09h
lea dx,mes
int 21h
;citire de la tastatura a unui caracter
mov ah,01h ; codul ascii al caracterului introdus
int 21h ;se va regasi in al
mov a3+2,al
sub al,30h ; se obtine cifra tastata in hexazecimal
mov cl,al
mov ax,01
;calculare factorial in ax
et2:
mul cx ; se inmulteste ax cu cx si rezultatul va fi in dx si ax
loop et2 ; daca cx e diferit de 0 se repeta
xor si,si ; si devine 0
mov bx,0ah
et3:
div bx ;catul va fi in ax restul in dx
add dl,30h ;calcul in ascii a cifrei rezultate si transferarea in memorie
mov rez[si],dl ; utilizand adresarea indexata
inc si
xor dx,dx ; pregatire dx ptr urmatoarea impartire
cmp ax,0 ; conditia de sfarsit de algoritm
jne et3
;afisare rezultat
mov ah,09h ;apelarea functiei 09h ptr afisarea unui mesaj a carui adresa ;relativa e in dx
lea dx,a3
int 21h
et4:
dec si
mov ah,02h ; apelarea functiei 02h ptr afiaarea unui caracter a carui adresa relativa e in dl
mov dl,rez[si]
int 21h ;apelarea functiei 21h ptr afisarea prompt dos
cmp si,0
jne et4
mov ah,4ch
int 21h
cod ends
Exercitii
Precizati functionalitatea urmatorului program(Ex33.asm).
.model small
.data
nr dw 110
suma dw 0
.stack 1024
.code
start:
mov ax,@data
mov ds,ax
mov ax,nr
xor cx,cx
xor dx,dx
mov bx,10
salt1:
div bx
add cx,dx
xor dx,dx
cmp ax,0
jne salt1
mov suma,cx
mov ax,4c00h
int 21h
end start
Precizati functionalitatea urmatorului program(Ex34.asm).
dosseg
.model small
.stack 100h
.data
a dw 30
b dw 36
c dw 42
mesaj1 db 10,13,'Numerele sunt $'
mesaj2 db 10,13,'Numerele nu sunt .$'
.code
mov ax,@data
mov ds,ax
xor dx,dx
mov ax,a
add ax,c
mov bx,ax
mov cx,2
div cx
cmp ax,b
jne et1
jmp et2
et1:
mov dx,offset mesaj2
mov ah,09h
int 21h
jmp sfarsit
et2:
mov dx,offset mesaj1
mov ah,09h
int 21h
sfarsit:
mov ah,4ch
int 21h
end
Precizati functionalitatea urmatorului program(Ex35.asm).
.model small
.stack 50h
.data
a dw 1h
b dw 5h
.code
mov ax, @data
mov ds, ax
mov ax, a
mov bx, b
mov dl, bl
mov ah, 02h
int 21h
push ax
push bx
mov ax, bx
mov bx, 0
mov dl, bl
mov ah, 02h
int 21h
pop bx
pop ax
mov dl, bl
mov ah, 02h
int 21h
mov ax, 4C00h
int 21h
end start
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 2313
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved