|
|
səhifə | 4/10 | tarix | 16.12.2017 | ölçüsü | 1,03 Mb. | | #35021 |
| begin
y:=256;
writeln('Numarul initial este: ',y);
y:=Saltexp(y);
writeln('Numarul returnat este: '.y);
end.
Atribuiti diverse valori lui y si observati ca rezultatul final va fi
egal cu y*2*2*2*2*2 (salt binar stanga de 5 ori).
Procedurile se definesc si se apeleaza la fel ca cele din Pascal,dar,
datorita faptului ca nu returneaza valori,este bine ca rezultatul ope-
ratiilor efectuate sa fie finalizat in interiorul procedurii.O aplicatie
foarte frecventa este apelarea unei intreruperi DOS cu ajutorul unei
instructiuni INT.Atunci cand intreruperea solicitata are sub-functii,se
va transfera initial in registrul AH numarul subfunctiei,dupa care se va
putea apela nivelul de intrerupere si se vor colecta din regisrii datele
returnate (Exemplu: INT 21 h are aproape 100 de subfunctii apelabile).
-21-
EXEMPLU: program assmb4;
uses WinCRT;
var zi,luna:byte;
an:word;
ora,min,sec:byte;
procedure datasistem;
begin
asm
mov AH,2ah
int 21h
mov zi,DL
mov luna,DH
mov an,CX
mov AH,2ch
int 21h
mov ora,CH
mov min,CL
mov sec,DH
end;
end;
begin
datasistem;
writeln('data curenta este: ',zi,' :',luna,' :',an);
writeln('este ora: ',ora,' :',min,' :',sec);
end.
In exemplul de mai sus,am scris o procedura care citeste data si ora sis-
temului.Pentru a citi data am apelat intreruperea DOS 21,2A iar pentru a
citi ora am apelat intreruperea 21,2C.Observati ca apelul intreruperii se
face in doua etape:in prima etapa se transfera in registrul AH numarul
suf-functiei DOS (mov AH,2ah sau mov AH,2ch),iar in etapa a doua se ape-
leaza intreruperea (INT 21h).Remarcati si faptul ca intreruperile DOS
sunt notate hexazecimal,motiv pentru care este extrem de important ca
numarul intreruperii si cel al subfunctiei sa fie urmat de litera h.In
caz contrar,valorile vor fi interpretate decimal (BCD=binary coded deci-
mals) si rezultatul intreruperii va fi complet diferit de cel scontat.
Intreruperea 21h,cu subfunctiile sale permite o gama extrem de larga de
operatii si este extrem de uzitata in assembler.Pentru a putea apela
corect nivelurile de intrerupere,trebuie sa aveti un tabel cu intrerupe-
rile DOS(sunt cateva sute de subfunctii),care poate fi descarcat si de
pe Internet.
Cu notiunile prezentate pana acum puteti deja sa proiectati si sa
editati o serie de functii,necesare pentru proiectele d-voastra.Prin
apelul nivelurilor de intrerupere DOS,se pot exploata practic toate
resursele sistemului de operare,direct,eficient si rapid si se pot tran-
sfera in mediul de operare Windows date preluate din sistemul de operare
DOS.Este insa foarte important sa aveti permanent in atentie formatul
datelor cu care lucreti.In assembler,fiecare expresie utilizata are
asociat un tip.Tipul expresiei este o valoare care exprima dimensiunea
memoriei ocupate de expresia respectiva.Dimensiunea de masoara in bytes.
Principalele tipuri predefinite sunt: BYTE 1,WORD 2,DWORD 4,QWORD 8,
TBYTE 10,NEAR 0FFFEH si FAR 0FFFFH.
-22-
Este bine sa existe intotdeauna o corespondenta directa intre tipul
de data al adresei sursa si tipul de data al adresei de destinatie.
Daca utilizati totusi tipuri de data diferite,trebuie ca adresa de
destinatie sa poata prelua datele(Exemplu: o data de tip byte poate
fi transferata intr-un registru de tip word,dar o data de tip word nu
poate fi transferata intr-un registru de tip byte).
EXEMPLU: program assmb5;
uses WinCRT;
var nr1,nr2:byte;
suma:word;
begin
asm
mov ax,9
mov nr1,al
mov bx,5
mov nr2,bl
add al,bl
mov suma,ax
end;
writeln('nr1= ',nr1);
writeln('nr2= ',nr2);
writeln('suma= ',suma);
end.
Observati ca am transferat in registrul ax o valoare numerica,apoi am
transferat valoarea respectiva intr-o variabila de tip byte.
Valorile numerice imediate nu au un tip definit,dar imediat dupa ce au
fost utilizate intr-o expresie,primesc tipul expresiei respective.Astfel,
valorile mai mici de 255 vor genera expresii de tip BYTE iar cele mai
mari vor genera expresii de tip WORD,etc.
Tabelul de corespondenta dintre datele de tip Pascal si cele de tip
assembler este urmatorul:
PASCAL ASSEMBLER
byte byte
shortint byte
word word
integer word
longint dword
string dword
record dword
array dword
pointer dword
real qword
In acest manual,vom utiliza doar date de tip byte si word,si instructiuni
8086,dar este extrem de important sa retineti si sa evaluati corect
tipul datelor,pentru a putea evolua la nivele superioare de procesare.
Atunci cand proiectati o functie noua,trebuie sa aveti in vedere atat
formatul datelor utilizat intern de algoritmul scris in assembler,cat si
formatul datelor de tip Pascal,care vor prelua valorile rezultate in
urma procesarii (Exemplu: data si ora din exemplul precedent.Uneori datele
vor fi citite din intregul registru: CX returneaza anul,iar alte ori se
vor citi dintr-un subregistru: DL returneaza ziua iar DH returneaza luna).
-23-
Regula generala de utilizare a registrilor,in interiorul unei bucle de
tip asm...end este urmatoarea: bucla trebuie sa conserve registrii BP,SP,
SS si DS (pointerii de stiva si registrul pentru cod si data) dar poate
sa modifice fara restrictii registrii AX,BX,CX,DX,SI,DI,ES si Flags.Ca
rezultat,la intrarea intr-o bucla asm...end,compilatorul va cunoaste
doar valoarea registrilor BP,SP,SS si DS dar nu va avea nici un fel de
informatii referitoare la ceilalti registri (care pot avea valori varia-
bile).Din acest motiv,este bine si prudent ca fiecare bucla asm...end sa
fie urmata de o procedura de eliberare a registrilor si de terminare a
executiei.La intrarea intr-o bucla asm...end,valoarea registrilor generali
poate fi diferita de zero.Este bine sa resetati registri la valoarea utila
fara sa apelati valoarea implicita.Pentru terminarea unui program,se poate
solicita un apel la un nivel de intrerupere DOS de tip 21h,cu una dintre
subfunctiile 0-Program Terminate sau 4c-Terminate Process With Return
Code.
EXEMPLU: program assmb6;
uses WinCRT;
var numar,x,y:word;
function multiplu9(x:word):word;assembler;
asm
mov ax,x
mov bx,9
mul bx
mov numar,ax
end;
procedure sfarsit;assembler;
asm
mov ah,4ch
mov al,00
int 21h
end;
begin
for x:=1 to 9 do
writeln('numarul rezultat este: ',multiplu9(x));
writeln('Tastati ENTER !');
readln;
sfarsit;
end.
In exemplul de mai sus,am declarat si definit o functie si o procedura.
Functia calculeaza un multiplu de noua,iar procedura executa terminarea
programului prin apelul unei intreruperi 21,4Ch.
Valorile registrilor generali nu se conserva la iseirea din bucla.In
exemplul de mai sus,dupa iesirea din functia multiplu9(x),valoarea regis-
trului AX va fi zero.Ca rezultat,nu se pot utiliza valorile registrilor
generali decat in interiorul buclei asm...end aflata in executie.
Pentru a evita coruperea datelor,este bine sa executati o procedura
de terminare a executiei,dupa epuizarea operatiilor efectuate intr-o
bucla asm...end sau dupa o suita de functii si proceduri.In acest manual,
pentru a simplifica la maximum exercitiile,si din economie de spatiu,nu
se vor executa buclele de terminare a exemplelor,decat in situatiile in
care este absolut indispensabil.
-24-
DECLARATII
Programul assembler inclus in Pascal accepta trei tipuri de declaratii
pentru variabile si constante.Acestea sunt:DB(define byte),DW(define word)
si DD(define double word).DB genereaza un byte si poate accepta orice
valoare cuprinsa intre -128 si 255,respectiv orice caracter ASCII.DW ge-
nereaza un word si poate accepta orice valoare cuprinsa intre -32768 si
65535 sau o adresa de offset(pointer de tip NEAR).DD genereaza doua cu-
vinte(double word) si poate accepta valori cuprinse intre -2147483648 si
4294967295 sau o adresa de offset(pointer de tip FAR).
Datele generate cu DB,DW si DD vor fi stocate intotdeauna in segmentul
de cod al programului(ocupa din spatiul rezervat programului).
EXEMPLE:
Declaratie Operand Rezultat
DB 0FFH un byte
DB 7,33 doi bytes diferiti
DB 'A' Ord('A')=codul numeric al caracterului
DB 'Hello..',0DH,0AH Un sir + CR/LF
DB 12,"Turbo Pascal" un sir de tip Pascal
DW 0FFFFH un cuvant(doi bytes)
DW 7,3333 doua cuvinte
DW 'A' este identic cu DB 'A',0= Ord('A'),0
DW 'AB' este Ord('A'),Ord('B') adica DB 'A','B'
DW variabila offset-ul variabilei
DW proces offset-ul procesului
Pentru aplicatiile care utilizeaza in Pascal functii si proceduri scrise
in assembler,este mai simplu sa declarati variabilele si constantele cu
ajutorul conventiilor de tip Pascal(adica in afara buclelor asm...end in
sectiunea de interfata a programului).Variabilele si constantele de tip
Pascal pot fi declarate si neinitializate si vor fi stocate in segmentul
de date al programului(nu afecteaza segmentul de cod).
Registrele nu pot prelua sirurile de caractere,dar pot opera cu adresa
variabilei care le contine.
EXEMPLU: program assmb7;
uses WinCRT;
var text1:string;
adr,sg1:word;
pt1:PChar;
begin
text1:='Limbajul de programare Assembler';
asm
mov ax,OFFSET text1
mov bx,SEG text1
mov dx,ax
mov adr,dx
mov sg1,bx
end;
pt1:=ptr(sg1,adr);
writeln(pt1);
end.
In mod normal,assembler nu poate opera cu date de tip string,dar prin
acest mic artificiu se pot face operatii asupra sirurilor de caractere.
-25-
EXEMPLU: program assmb8;
uses WinCRT;
var text1:string;
adr,sg1:word;
pt1:Pchar;
begin
text1:='Limbajul de programare Assembler';
asm
mov ax,OFFSET text1
add ax,24
mov bx,SEG text1
mov dx,ax
mov adr,dx
mov sg1,bx
end;
pt1:=ptr(sg1,adr);
writeln(pt1);
end.
Exercitiul este identic cu precedentul,dar am efectuat in offset-ul
adresei un salt de 24 de bytes.In ambele exercitii,am utilizat in bucla
asm...end doar adresa sirului de caractere,impartita in doua variabile
de tip word,care contin segmentul si respectiv offset-ul variabilei.
Dupa ce am efectuat eventualele operatii asupra adresei,am reconstituit
un pointer de tip PChar din segmentul si offset-ul variabilei.
Deoarece operatiile cu adresele variabilelor sunt extrem de importante
este utila o sinteza a principalelor elemente.
1. -registrii procesorului 8086 pot accepta valori de maximum 2 bytes
2. -procesorul 8086 segmenteaza memoria in 65536 de segmente,fiecare seg-
ment avand atasat un fragment de 65536 de bytes de memorie.Adresa din
interiorul fiecarui segment poarta numele de OFFSET si poate lua orice
valoare intre 0 si 65536.
3. -ca rezultat,procesorul 8086 poate opera cu date incluse in memorie,pe
o extindere maxima de 65536 x 65536 = 4294967296 bytes(4 Gb).
4. -adresele pot fi reprezentate binar,octal,decimal sau hexazecimal,dar
cea mai frecventa reprezentare este cea in format hexazecimal
EXEMPLU: SEGMENT OFFSET
binar 00000000 00000001 00000000 00000001
hexazecimal 1 : 1
sau :
decimal 15: 65536
hexazecimal 1F: 0FFFFH
Rezulta un format pe 32 de biti,unde atat valoarea segmentului cat si cea a
offset-ului poate fi cuprinsa intre 0 si 65536,in reprezentarea decimala
sau respectiv 00000H si 0FFFFH in reprezentarea hexazecimala.
5. -pentru a efectua operatii asupra adreselor trebuie ca adresele sa fie
reprezentate in acelasi format,si este necesar ca formatul respectiv
sa poata fi acceptat de registrii de procesor.
EXEMPLE: procesorul 8086 nu poate accepta adrese cu format mai mare de
32 de biti,deoarece registii au maxim 16 biti (2 x 16 = 32 )
procesorul 80386 are registrii de 32 de biti si ca rezultat
poate opera cu adrese de 64 de biti (32/segment + 32/offset)
-26-
6. -pentru a efectua operatii cu adrese,trebuie ca formatul adresei sa
fie acceptat de catre programul assembler cu care se apeleaza.
Adresele de 16 biti se pot utiliza exclusiv pentru programe mai
mici de 64 K.Adresele de 32 de biti,sunt adresele curente si sunt
acceptate de toate compilatoarele si aproape toate tipurile de
procesoare actuale.
Pentru a opera cu adrese mai mari,teoretic adresele se pot frag-
menta astfel incat sa fie cuprinse in patru registrii.Astfel,o
adresa poate fi subimpartita astfel:
Base + Index + Scale + Displacement
unde: Base este un registru de 32 de biti,Index este tot un registru
de 32 de biti(cu exceptia ESP),Scale este 1,2,4 sau 8 iar Displace-
ment este tot un registru de 32 de biti (offset-ul).
Pentru incepatori,nu este recomandabil sa opereze decat cu adrese
de 32 de biti.
7. -limitele operatiilor posibile sunt determinate de procesorul instalat
sistemul de operare instalat si programul assembler utilizat.
ETICHETE (Labels)
Se utilizeaza pentru a putea efectua salturi in program.Sunt formate din
identificator urmat de doua puncte.Exemple: NUME1: Nume2: AB1_3: etc.
Etichetele locale,pot fi utilizate doar in interiorul buclelor asm...end,
incep cu semnul @ si se termina cu :.Identificatorul se poate forma din
orice combinatie de litere(A..Z),cifre(0..9),semne _ sau @.
EXEMPLU: program assmb9;
uses WinCRT;
var nr,zz:word;
begin
nr:=7;
writeln('Valorile initiale sunt: ',nr,' si : ',zz);
asm
mov ax,nr
inc ax
jmp @@nume1
add ax,9
mov bx,nr
@@nume1:
add ax,2
mov nr,ax
jmp @@nume2
dec ax
mov bx,ax
@@nume2:
add ax,10
mov bx,ax
mov zz,bx
end;
writeln('Valorile finale sunt: ',nr,' si : ',zz);
end.
Pentru a evalua rezultatul salturilor puteti include instructiunile de
salt (jmp) intre acolade (astfel bucla se va executa fara nici un salt).
-27-
Etichetele locale nu pot fi utilizate in afara buclelor asm...end,
deoarece ar fi interpretate ca fiind adresele unor variabile.In afara
buclelor asm...end,se vor utiliza etichetele de tip Pascal (declarate cu
label+identificator).
Chiar si in interiorul buclelor,este bine sa se utilizeze doua sau
mai multe semne @ inaintea identificatorului,pentru a putea distinge de
la prima vedere locatia etichetelor in program.In plus,compilatoarele si
emulatoarele sau programele de analiza automata pot contine functii care
nu fac distinctia dintre buclele begin...end si cele de tip asm...end si
vor interpreta eronat valoarea identificatorului.
Este bine sa aveti o conventie proprie de formare a denumirilor,astfel
incat sa le regasiti cat mai usor in etapa de depanare a programului.
OPERANZI SI OPERATORI
Pentru formarea expresiilor,am utilizat in exemplele precedente doar
instructiuni 8086,registri si/sau valori imediate.
Pentru formarea expresiilor,assembler-ul integrat in Pascal recunoaste
toate tipurile de date de tip Pascal:constante,variabile,arii de date,
structuri,functii si proceduri,unitati,etichete etc. la care se adauga
si BYTE,WORD,DWORD,QWORD,TBYTE,NEAR,FAR(tipuri assembler predefinite).
In plus,recunoaste si trei constante speciale: @Code(returneaza adresa
segmentului de cod),@Data(returneaza adresa segmantului de date) si
@Result(returneaza offset-ul variabilei rezultate dupa evaluarea unei
functii-nu se poate utiliza in afara functiilor).
Nu se pot utiliza urmatoarele tipuri de date:
-functiile si procedurile standard din unitati (Exemplu: writeln() )
-ariile speciale Mem,MemW,MemL,Port,PortW
-sirurile,numerele in virgula mobila si constantele de setare
-functiile si procedurile declarate cu inline
-etichetele declarate in alt modul de program (Exemplu: in unitati)
-simbolul @Result nu se poate utiliza in afara unei functii
Toate variabilele declarate cu VAR,vor fi interpretate de catre assembler
ca pointeri spre adrese in format de 32 de biti,iar dimensiunea lor va fi
intotdeauna 4(adresa de 4 bytes=doi registri de 16 biti=32 biti).
Pentru a accesa continutul unei variabile,trebuie sa incarcati pointerul
sau si apoi sa accesati adresa spre care pointeaza.
Pentru datele structurate sub forma de inregistrari,structuri si obiecte,
se vor accesa membrii structurilor la fel ca si in Pascal,cu ajutorul ope-
ratorului de selectie (.).
Regulile de formare a expresiilor nu sunt rigide.Daca se respecta regulile
de mai sus,se pot forma expresii diferite ca forma,dar care determina
exact acelasi rezultat:
EXEMPLU: asm
mov AX,(Rect PTR ES:[DI]).B.X
mov AX,Rect(ES:[DI]).B.X
mov AX,ES:Rect[DI].B.X
mov AX,Rect[ES:DI].B.X
mov AX,ES:[DI].Rect.B.X
end;
Toate expresiile din bucla de mai sus genereaza acelasi cod masina si au
aceeasi semnificatie: incarca in AX continutul din ES,membrul X din Rect.B
-28-
Pentru formarea expresiilor din exemplul precedent,s-au utilizat si o
serie de simboluri,denumite operatori,care efectueaza un anumit tip de
operatie asupra datelor.Operatorii acceptati de assemblerul Pascal sunt:
CATEGORIE OPERATOR REZULTAT (ce face)
precedenta & -inlocuieste un identificator
( ) -include o subexpresie
[ ] -marcheaza o adresa de memorie
. -selecteaza un membru al structurii
unari HIGH -returneaza byte-ul cel mai inalt
LOW -returneaza byte-ul inferior
+ -plus unar
- -minus unar
: -inlocuieste un segment
OFFSET -returneaza offset-ul adresei
SEG -returneaza segmentul adresei
TYPE -returneaza tipul(dimensiunea)
PTR -determina tipul
* -multiplicator
/ -divizor
MOD -divide cu rest (modul din x)
Dostları ilə paylaş: |
|
|