|
in stiva rezultatul si inlocuieste ST cu valoarea 1.Rezultatul
|
səhifə | 10/10 | tarix | 16.12.2017 | ölçüsü | 1,03 Mb. | | #35021 |
| in stiva rezultatul si inlocuieste ST cu valoarea 1.Rezultatul
trebuie recuperat din ST(1) (dupa o operatie FXCH).Rezultaul
este exprimat in radiani(valori intre 2**(-63) si 2**(63)).
FPATAN -Calculeaza arctangenta raportului y/x unde x este in ST si y
este valoarea din ST(1).Rezultatul in ST,exprimat in radiani.
Instructiunea F2XM1 este foarte usor de exploatat:
EXEMPLU: program assmb99;
{$N+)
uses WinCRT;
begin
a:=0.12345;
asm
FLD a
F2XM1
FST b
end;
writeln('2 la puterea (',a:2:4,'-1) este:',b:5:5);
end.
Pentru FYL2X si FYL2XP1 este importanta ordinea de transfer a valorilor:
EXEMPLU: program assmb100;
{$N+}
uses WinCRT;
var a,b,c:double;
begin
a:=7;
b:=5;
asm
FLD b
FLD 1
FYL2X
FST c
end;
writeln('rezultatul pentru 5x(log2 7) este: ',c:6:6);
end.
Instructiunea FYL2XP1 este identica dar adauga 1 la valoarea x.Astfel
FYL2XP1 cu x=7 si y=5 este identica cu FYL2X cu x=8 si y=5.Cele doua
instructiuni se pot utiliza si sinergic,pentru a calcula rezultatul
fata de puterea imediat urmatoare a lui x.Ambele sunt utile pentru
calculul logaritmic.
-86-
Pentru calculul tangentei si arctangentei,se poate utiliza un algoritm
elementar de genul:
EXEMPLU: program assmb101;
{$N+}
uses WinCRT;
var a,b,c,d:double;
begin
a:=17533.17;
b:=9339.23;
asm
FLD b
FLD a
FPTAN
FXCH
FST c
FLDZ
FLD b
FLD a
FPTAN
FST d
end;
writeln('Tangenta(b/a) este: ',c:8:8);
writeln('Arctangenta (b/a) este: ',d:8:8);
end.
Un alt set de instructiuni este utilizat pentru controlul ramificatiilor
din program (dar poate fi utilizat si pentru a compara doua valori cu
scopul de a le sorta,etc...).
In urma comparatiei dintre cele doua valori,se poate utiliza una dintre
instructiunile de salt conditionat.Instructiunile din acest set utili-
zeaza registrul de stare,respectiv grupurile de biti denumite C0,C1,C2 si
C3 (sau Z; C; A; si S; )-vezi tabelul prezentat la descrierea registrilor.
Procesorul 8087 nu contine nici o instructiune care sa permita accesul
la registrul de status.Din acest motiv,pentru a putea evalua valoarea
acestui registru,se apeleaza la instructiunea FSTW AX,care transfera
valoarea registrului de status 8087 in registrul AX 8086.Este singura
instructiune care permite schimbul de date dintre cele doua procesoare.
In rest,toate operatiile de transfer trebuiesc intermediate prin varia-
bile de memorie.Din AX,valoarea poate fi exploatata ca atrare,sau se
poate transfera byte-ul AH in registrul FLAGS cu ajutorul instructiunii
SAHF.In acest caz,bitul de control C0 8087 devine CF(carry flag) 8086,
CZ devine PF(parity flag) iar CA devine ZF(zero flag).Bitul de control
C1 nu este transferat si nici nu este necesar pentru evaluare.In conti-
nuare,flagurile 8086 pot fi utilizate pentru salturi conditionate cu
ajutorul instructiunilor ja,jae,jb,jbe,jz etc.
Deoarece acest gen de control al ramificatiilor din program implica
un numar destul de mare de operatii,este bine sa utilizati o schema
grafica in care sa marcati fiecare operatie efectuata (nu va bazati pe
memorie sau pe intuitie).Intr-o varianta mai simpla,controlul ramificatii-
lor din program se poate realiza si in functie de byte-ul superior din
valoarea transferata in AX (fara apel la flagurile 8086).
-87-
Instructiunile pentru compararea operanzilor sunt:
FCOM -Compara ST cu ST(1) (vezi tabelul de la pagina 75)
FCOM ST(nr) -Compara ST cu ST(nr)
FCOM mem -Compara ST cu mem
FICOM mem -Compara ST cu numarul intreg mem
FTST -Compara ST cu zero
EXEMPLU: program assmb102;
{$N+}
uses WinCRT,WinProcs;
var a:double;b:word;
begin
a:=1.17;
asm
FLD a
FLDPI
FCOM
FSTSW AX
mov b,AX
end;
writeln('Valoarea registrului de stare este: ');
writeln(LOBYTE(b),'-',HIBYTE(b));
end.
Valoarea returnata este 32-48,care in reprezentare binara este:
0010 0000 - 0011 0000 .Se observa ca flagurile CF,PF si ZF au valoarea
zero,deci valoarea din ST este mai mare decat cea comparata din ST(1).
(se evalueaza bitii 0, 2 si 6 din valoarea byte-ului superior)
Pentru a efectua o ramificatie simpla se poate utiliza byte-ul superior:
EXEMPLU: program assmb102;
{$N+}
uses WinCRT,WinProcs;
var a:double;b:word;
begin
writeln('Introduceti un numar : ');
read(a);
asm
FLD a
FLDPI
FCOM
FSTSW AX
mov b,AX
end;
if HIBYTE(b) = 112 then
writeln('Numarul introdus este egal cu PI ');
if HIBYTE(b) = 49 then
writeln('Numarul introdus este mai mare decat PI');
if HIBYTE(b) = 48 then
writeln('Numarul introdus este mai mic decat PI');
end.
112 reprezentatr binar este 0111 0000 (adica C0 = 0, C2 = 0 si C3 = 1)
49 reprezentat binar este 0011 0001 (adica C0 = 1, C2 = 0 si C3 = 0)
Pentru a testa precizia,introduceti 3.14...si cat mai multe zecimale.
-88-
Registrul de STATUS are urmatoarea structura (pe biti):
B Z TOP C A S N * P U O Q D I
unde:
I -invalid operation
D -denormalized operand
Q -division of nonzero by zero
O -overflow
U -underflow
P -inexact (precision)
N -indicates a pending interrupt
iar C,A,Z si S sunt bitii de control C0,C1,C2 si C3
Registrul CONTROL are urmatoarea structura (pe biti):
x x x IC RC PC N x PM UM OM QM DM IM
unde:
IC -infinity control
RC -rounding control
PC -precision control
iar PM,UM,OM QM,DM si IM sunt controlul flagurilor din registrul STATUS
Pentru compararea operanzilor si extragerea stivei se pot utiliza urma-
toarele instructiuni:
FCOMP -Compara ST cu ST(1) si extrage ST
FCOMP ST(nr) -Compara ST cu ST(nr) si extrage ST
FCOMP mem -Compara ST cu mem si extrage ST
FICOMP mem -Compara ST cu numarul intreg mem si extrage ST
FICOMPP ST(nr) -Compara ST cu ST(nr) si apoi extrage din stive de doua
ori.Atat sursa cat si destinatia sunt distruse.
Se utilizeaza la fel ca si FCOM (vezi si tabelul de la pagina 75) dar
cu rezerva ca registrul ST este anulat prin extrgaerea din stiva.
Un alt set de instructiuni permite transferul datelor de control.Aceste
instructiuni sunt:
FLDCW mem2byte -Incarca cuvantul de control
FSTCW mem2byte -Memoreaza cuvantul de control
FSTSW mem2byte -Memoreaza cuvantul de stare
FLENV mem14byte -Incarca mediul
FSTENV mem14byte -Memoreaza mediul
FRSTOR mem94byte -Restaureaza starea
FSAVE mem94byte -Salveaza starea
FSTSW AX -memoreaza datele in registrul AX 8086
Aceste instructiuni se utilizeaza pentru controlul si/sau depanarea pro-
cesorului 8087.Nu sunt indicate incepatorilor.Pentru utilizarea lor
corecta este bine sa consultati si literatura de specialitate,sau cel
putin cateva articole de pe Internet.In principiu,cele notate cu mem2byte
utilizeaza variabile de tip word si opereaza cu un registru de stare sau
de control,cele notate mem14byte opereaza cu cei sapte registri de control
(STATUS,CONTROL,TAG,INSTRUCTION,ADDRESS,DATA,ADDRESS) iar cele notate cu
mem94byte opereaza cu toate datele din procesor (cei 8 registri generali
de cate 10 bytes si cei 7 registri de control de cate 2 bytes).
-89-
EXEMPLU: program assmb104;
{$N+}
uses WinCRT,WinProcs;
var a,b:word;
begin
a:=1133;
asm
FLDCW a
FST b
end;
writeln('Cuvantul de control este: ',b);
writeln('adica: ',LOBYTE(b),'-',HIBYTE(b));
end.
Pentru a controla modul de rotunjire a zecimalelor sau precizia de
calcul,trebuie sa alegeti cu atentie valoarea transferata in registrul
de control atfel incat bitii 8-9 si respectiv 10-11 din reprezentarea
binara a valorii respective sa respecte una dintre conditiile prezentate
la pagina 75.
In exemplul de mai sus,valoarea 109-4 in reprezentare binara este:
0110 1101 - 0000 0100
deci grupul de biti 8-9 este 1 0 adica precizia este de 53 de biti
iar grupul de biti 10-11 este 1 1 adica rotunjirea este prin trunchiere
Alte instructiuni 8087 sunt:
FINIT -Repozitiveaza coprocesorul si restaureaza conditiile implicite
FCLEX -Sterge toate flagurile si indicatoarele busy
FINCSTP -adauga 1 la pointerul de stiva din cuvantul de stare
FDECSTP -scade 1 din pointerul de stiva din cuvantul de stare
FFREE ST(nr) -marcheaza registrul respectiv ca fiind gol.Valoarea nu este
stearsa dar nu mai poate fi accesata
FNOP -copiaza ST in ST(opratie nula),determina o intarziere
EXEMPLU: program assmb105;
{$N+}
uses WinCRT;
var a,b:double;
begin
a:=133.775;
asm
FLD a
FNOP
FFREE ST(0)
FST b
FCLEX
FINIT
end;
writeln(b);
end.
In exemplu de mai sus,FFREE blocheaza registrul ST si determina o eroare,
dar FCLEX sterge flag-ul iat FINIT restaureaza conditia implicita.FNOP
determina doar o intarziere de un ciclu (nu afecteaza registrii).In
absenta instructiunii FCLEX,programul returneaza un mesaj de eroare.
-90-
UNITATI SI BIBLIOTECI DLL
-se editeaza si exploateaza la fel cu cele editate in Pascal.
EXEMPLU: unit asmunit1;
INTERFACE
{$N+}
uses WinCRT;
var raza,rezultat,xxx,yyy:double;
function arie(xxx:double):double;
function volum(xxx:double):double;
IMPLEMENTATION
function arie(xxx:double):double;
begin
writeln('Introduceti raza: ');
read(raza);
xxx:=2;
asm
FLD raza
FMUL raza
FLDPI
FMUL
FLD xxx
FMUL
FST rezultat
end;
writeln('Aria hemisferei este: ',rezultat:15:10);
end;
function volum(xxx:double):double;
begin
writeln('Introduceti raza: ');
read(raza);
xxx:=4;
yyy:=6;
asm
FLD reza
FMUL raza
FMUL raza
FLDPI
FMUL
FLD xxx
FMUL
FLD yyy
FDIV
FST rezultat
end;
writeln('Volumul hemisferei este: ',rezultat:15:10);
end;
begin
end.
Dupa compilare,cele doua functii din unitatea asmunit1 pot fi apelate
dupa ce unitatea a fost introdusa in memorie cu USES...Observati ca nu
mai sunt necesare unitatile WinTypes si WinProcs.
-91-
Pentru exploatarea unitatii se poate utiliza un algoritm de genul:
EXEMPLU: program assmb106;
{$N+}
uses WinCRT,asmunit1;
var valoare1:double;
begin
valoare:=arie(valoare1);
valoare1:=volum(valoare1);
end.
Nu uitati sa compilati unitatea inainte de a o apela.Daca nu aveti
nici pana acum o unitate de functii proprii,este bine sa incercati sa
scrieti prima functie sau procedura.Unitatile cu functii si proceduri
editate in assembler prezinta o serie de avantaje.In primul rand se
reduce spatiul ocupat in memoria de operare de unitatile accesorii din
Pascal.In al doilea rand,creste viteza de executie.Pentru a executa o
singura operatie,aceasta optimizare este absolut insesizabila (cateva
nanosecunde),dar in cazul in care operatia respectiva este repetata de
cateva milioane de ori (cum este cazul browserelor de Internet),optimi-
mizarea este substantiala si se masoara in secunde sau chiar zeci de
secunde.In al treilea rand,editarea de unitati proprii asigura un grad
foarte mare de flexibilitate,pentru probleme si situatii extrem de dife-
rite.
In cazul in care editati unitati exclusiv pentru uzul personal,puteti
sa aplicati orice metode de programare doriti,cu conditia sa va puteti
rezolva problema propusa.In cazul in care doriti a unitatile respective
sa poata fi utilizate si de altii,trebuie sa respectati cu strictete
toate regulile de format si exprimare incluse in standardele IEEE pentru
Pascal si respectiv pentru Assembler.Este bine ca unitatile sa poarte
denumiri cat mai simple,clare si sugestive.Pentru a simplifica munca de
depanare,insotiti unitatea furnizata si de fila .pas din care a fost
generata.Daca unitatea contine un numar mare de functii,este bine sa
fie insotita si de o fila de sinteza in care sunt prezentate pe scurt
doar functiile existente si conventiile de apelare a lor.Daca unitatile
contin functii mai greu de evaluat la prima vedere,este bine sa editati
si o fila de tip text,in care sa explicati detaliat modul de exploatare
al fiecarei functii,domeniul de reprezentare,principalele tipuri de
aplicatii,descrierea mediului (enviroment) in care trebuie apelata pentru
performante optime,modul de apelare,eventualele limite sau exceptii ne-
rezolvate,etc.
Pentru variabilele utilizate in unitati este bine sa utilizati iden-
tificatori cu nume cat mai lung si explicit,pentru a evita supraincarcarea
identificatorilor (Exemplu: daca doua sa mai multe unitati utilizeaza
variabile denumite x si y,incarcarea acestor unitati in cadrul unui
singur program va genera conflicte de identificator,sau va executa ope-
ratiile dupa un algoritm eronat,bazat pe proximitatea identificatorului).
In cazul unitatilor,toate variabilele declarate in modulul denumit INTER-
FACE vor fi transferate in memoria de operare in etapa de compilare a
programului care apeleaza uniatatea respectiva,si vor ramane in memoria
de operare pana la sfarsitul programului.Din acest motiv,este bine sa
va limitati la variabilele absolut necesare pentru executia functiilor.
-92-
In unitati,functiile si procedurile pot fi ordonate si sistematizate sub
forma de obiecte,care vor fi utilizate apoi sub forma de module.
EXEMPLU:
unit asmunit2;
INTERFACE
{$N+)
uses WinTypes,WinProcs,OWindows,ODialogs,WinCRT,Strings;
type PTW = ^TW;
TW = object(TWindow)
ED1,ED2:PEdit;
BT1:PButton;
PS1,PS2:PStatic;
constructor Init(AParent: PWindowsObject;ATitle:PChar);
procedure Buton(var Msg: TMessage);virtual id_First + 10;
end;
TDlgApp = object(TApplication)
procedure InitMainWindow;virtual;
end;
IMPLEMENTATION
constructor TW.Init(AParent: PWindowsObject; ATitle: PChar);
begin
inherited Init(AParent,ATitle);
PS1:=New(PStatic,Init(@Self,201,'Introduceti raza:',30,50,150,20,0));
PS2:=New(PStatic,Init(@Self,202,'Aria cercului este:',330,50,150,20,0));
ED1:=New(PEdit,Init(@Self,301,'',30,90,140,30,30,False));
ED2:=New(PEdit,Init(@Self,302,'',330,90,140,30,30,False));
BT1:=New(PButton,Init(@self,101,'Calculeaza',200,200,90,20,True));
end;
procedure TW.Buton(var Msg:TMessage);
var text:PChar;nrx:double,n:integer;sss:string;
begin
text:=' ';
ED1^.GetLine(text,30,0);
Val(text,nrx,n);
asm
FLD nrx
FMUL nrx
PLDPI
FMUL
FST nrx
end;
Str(nrx:15:6,sss);
StrPCopy(text,sss);
ED2^.SetText(text);
end;
procedure TDlgApp.InitMainWindow;
begin
MainWindow :=New(PTW,Init(nil,'Aria cercului:'));
end;
begin
end.
-93-
Obiectul din unitatea asmunit2 poate fi apelat astfel:
EXEMPLU: program assmb107;
{$N+}
uses asmunit2;
var cerc:TDlgApp;
begin
cerc.Init(nil);
cerc.Run;
cerc.Done;
end.
Observati nu mai este necesara nici o alta unitate Pascal Standard.
Obiectul din unitatea editata,este executabil ca un modul independent.
Pentru a edita biblioteci DLL,regulile sunt la fel ca in Pascal:
EXEMPLU: library asmDLL1;
{$N+}
function sfera(raza1:double):double;export;
var n1,n2,volum:double;
begin
n1:=4;
n2:=3;
asm
FLD raza1
FMUL raza1
FMUL raza1
FLDPI
FMUL
FLD n1
FMUL
FLD n2
FDIV
FST volum
end;
sfera:=volum;
end;
exports
sfera index 1;
begin
end.
Dupa compilare,biblioteca nou creata poate fi utilizata,cu conditia sa
fie arhivata in acelasi director cu programul din care a fost apelata.
Bibliotecile DLL editate in assembler prezinta toate avantajele pe care
le ofera bibliotecile DLL in general,la care se adauga supletea si
viteza de executie generata de apelul direct al procesorului.
In exemplul de mai sus,puteti observa faptul ca nu am apelat la nici
o bibliotecta Pascal Standard.Cu exceptia diractivei de precompilare
{$N+} necesara pentru activarea procesorului 8087 si implicit a for-
matelor de numere reale,nu a fost necesara incarcarea bibliotecilor
clasice WinCRT,WinTypes si WinProcs.Se realizeaza astfel o economie
semnificativa de memorie.In plus,definitia functiei nu se incarca in
memorie decat in momentul declaratiei.
-94-
In continuare,biblioteca se apeleaza la fel ca orice biblioteca DLL.
Astfel in cadrul unui program oarecare,se declara functia in mod identic
cu cel in care a fost declarata in biblioteca DLL,iar in locul definitiei
se utilizeaza cuvantul cheie EXTERNAL urmat de numele filei care contine
biblioteca DLL.
EXEMPLU: program assmb108;
{$N+}
uses WinCRT;
var x:double;
function sfera(raza1:double):double;external 'asmDLL1.dll';
begin
writeln('Introduceti raza sferei:');
Read(x);
writeln('Volumul sferei este:',sfera(x):15:6);
end.
Sunt posibile toate cele trei tipuri de apel:prin nume,prin index sau
prin denumirea alias (prin numele alternativ al functiei declarate).
Pentru detalii despre modul de editare si apelare al bibliotecilor DLL
din Pascal,consultati bibliografia acestui limbaj.
Observati ca fila assmb108.pas ocupa 224 de bytes,in timp ce fila
asmDLL1.dll ocupa 3214 bytes iar fila executabila assmb108.exe ocupa
57171 bytes de memorie.
Bibliotecile de functii DLL (biblioteci alocate dinamic) sunt foarte
utile atunci cand se lucreaza cu un numar foarte mare de functii,care
daca ar fi incarcate simultan ar depasi spatiul de memorie de operare.
Cu ajutorul bibliotecilor DLL,functiile se incarca in memorie secvential,
doar in momentul in care sunt necesare in program,dupa care memoria este
eliberata pentru a permite executia unei alte functii.In plus,mai multe
programe sau chiar mai multi utilizatori pot partaja simultan aceasi
biblioteca de functii DLL.Pentru detalii,consultati literatura de spe-
cialitate,si limbajele Pascal,C++,Delphi etc.
Cu aceste notiuni elementare,se incheie acest abecedar.Notiunile
prezentate sunt departe de a fi exhaustive,dar sunt suficiente pentru
a va simplifica munca de editare a unor programe si aplicatii simple.
Doritorii vor explora pe cont propriu seturile de instructiuni implementa-
te in procesoarele moderne (80386,80486 si urmatoarele),precum si modul
in care pot fi utilizate pentru a realiza cooperarea dintre doua sau
mai multe procesoare,procesarea paralela a datelor etc.Dar nu uitati:
de cele mai multe ori,solutia cea mai buna este si cea mai simpla.Nu
cautati solutii savante atunci cand exista o solutie elementara la
indemana.Nu are rost sa scrieti in assembler functii care au fost deja
implementate in Pascal.Cautati intotdeauna solutia cea mai simpla.Nu va
complicati cu sisteme de protectie prea sofisticate (o analiza statistica
a demonstrat ca proprietarul casei este cel care sare cel mai des peste
gardul de la gradina).Daca puteti,aveti in vedere dictonul latinesc:
NON MULTA,SED MULTUM
*** S F A R S I T ***
Dostları ilə paylaş: |
|
|