User Tools

Site Tools


laboratoare:laborator-12

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
laboratoare:laborator-12 [2016/01/13 16:28]
razvan.deaconescu [Reprezentarea numerelor în virgulă mobilă]
laboratoare:laborator-12 [2016/01/15 19:25] (current)
razvan.deaconescu [[2p] 4. Extragere parte întreagă și fracționară]
Line 15: Line 15:
 Pentru a reprezenta valorile fracționare vom folosi **Reprezentarea în virgulă mobilă** (**Floating Point Representation**). În această reprezentare,​ numerele au următoarea structură: Pentru a reprezenta valorile fracționare vom folosi **Reprezentarea în virgulă mobilă** (**Floating Point Representation**). În această reprezentare,​ numerele au următoarea structură:
  
-{{:​laboratoare:​lab12-equation1.png?​500|}}+{{ :​laboratoare:​lab12-equation1.png?​500 |}}
  
 După cum putem observa mai sus, valorile trebuie transformate astfel încât partea întreagă să fie 1. Această formă poartă ​ După cum putem observa mai sus, valorile trebuie transformate astfel încât partea întreagă să fie 1. Această formă poartă ​
Line 21: Line 21:
  
 În forma binară, valorile se reprezintă astfel: În forma binară, valorile se reprezintă astfel:
-{{:​laboratoare:​2000px-ieee_754_double_floating_point_format.png?​600|}}+{{ :​laboratoare:​2000px-ieee_754_double_floating_point_format.png?​600 |}}
  
 **Semnul** este dat de primul bit din reprezentarea binară: 1 = negativ, 0 = pozitiv.\\ **Semnul** este dat de primul bit din reprezentarea binară: 1 = negativ, 0 = pozitiv.\\
Line 33: Line 33:
 Cele mai folosite standarde de reprezentare în virgulă mobilă sunt cu precizie simplă (**Single Precision**) și cu precizie dublă (**Double Precision**). Cele mai folosite standarde de reprezentare în virgulă mobilă sunt cu precizie simplă (**Single Precision**) și cu precizie dublă (**Double Precision**).
  
-Reprezentarea cu **precizie simplă** presupune folosirea a 32 de biți și corespunde valorilor float din limbajul C. În acest caz baza folosită este 2, exponentul are 8 biți, iar restul de 23 de biți corespund ​exponentului.+Reprezentarea cu **precizie simplă** presupune folosirea a 32 de biți și corespunde valorilor float din limbajul C. În acest caz baza folosită este 2, exponentul are 8 biți, iar restul de 23 de biți corespund ​mantisei.
  
-Reprezentarea cu **precizie dublă** presupune folosirea a 64 de biți și corespunde valorilor de tip double. În acest caz, baza este 2, exponentul are 11 biți, iar ultimii ​52 de biți sunt folosiți pentru exponent.+Reprezentarea cu **precizie dublă** presupune folosirea a 64 de biți și corespunde valorilor de tip double. În acest caz, baza este 2, exponentul are 11 biți, iar restul de 52 de biți corespund mantisei.
  
 <​note>​ <​note>​
 În ambele cazuri, exponentul folosit în calcul nu este cel extras din numărul în forma binară, ci este calculat astfel: În ambele cazuri, exponentul folosit în calcul nu este cel extras din numărul în forma binară, ci este calculat astfel:
-* În precizie simplă, exponentul este dat de valoarea (exponentul pe 23 de biți) - 127 +* În precizie simplă, exponentul este dat de valoarea ​''​(exponentul pe de biți) - 127''​ (adică se scade o valoare fixă din valoarea efectivă a exponentului) 
-* În precizie dublă, exponentul este dat de valoarea (exponentul pe 52 de biți) - 1023+* În precizie dublă, exponentul este dat de valoarea ​''​(exponentul pe 11 de biți) - 1023''​ (adică se scade o valoare fixă din valoarea efectivă a exponentului)
  
 </​note>​ </​note>​
Line 55: Line 55:
 ===== Unitatea de calcul în virgulă mobilă ==== ===== Unitatea de calcul în virgulă mobilă ====
  
-În procesoarele vechi, calculele matematice erau efectuate pe un chip separat, numit **coprocesor matematic** care comunica cu procesorul principal. Procesoarele moderne au acest chip încorporat sub forma Floating Point Unit, care le permite să efectueze eficient calcule matematice cu numere ​reale folosind un set separat de instrucțiuni.+În procesoarele vechi, calculele matematice erau efectuate pe un chip separat, numit **coprocesor matematic** care comunica cu procesorul principal. Procesoarele moderne au acest chip încorporat sub forma Floating Point Unit, care le permite să efectueze eficient calcule matematice cu numere ​fracționare ​folosind un set separat de instrucțiuni
 + 
 +Unitatea de calcul în virgulă mobilă deține o stivă proprie pe care o folosește pentru a citi operanzii și a stoca rezultatele operațiilor.
  
-Unitatea de calcul în virgulă mobilă deține o stivă proprie pe care o folosește pentru a citi operanzii și a stoca rezultatele operațiilor.\\ 
 De exemplu, o instrucțiune de tip adunare scoate primele două valori de pe această stivă, efectuează operația de adunare și pune rezultatul înapoi în vârful stivei. Deci, înainte de efectuarea oricărei operații va trebui să punem operanzii necesari pe stivă și, după efectuarea operației, vom obține rezultatul folosind o instrucțiune de tip pop. De exemplu, o instrucțiune de tip adunare scoate primele două valori de pe această stivă, efectuează operația de adunare și pune rezultatul înapoi în vârful stivei. Deci, înainte de efectuarea oricărei operații va trebui să punem operanzii necesari pe stivă și, după efectuarea operației, vom obține rezultatul folosind o instrucțiune de tip pop.
  
Line 76: Line 77:
  
 ^ Instrucțiune ​     ^ Descriere ​         ^ ^ Instrucțiune ​     ^ Descriere ​         ^
-| fstp DWORD [registru] | Citește o valoare de tip float (octeți) din vârful stivei și o salvează la adresa indicată de registru. Valoarea este eliminată de pe stivă. |+| fstp DWORD [registru] | Citește o valoare de tip float (octeți) din vârful stivei și o salvează la adresa indicată de registru. Valoarea este eliminată de pe stivă. |
 | fst DWORD [registru] ​ | Similar cu instrucțiunea anterioară,​ dar valoarea rămâne în vârful stivei. | | fst DWORD [registru] ​ | Similar cu instrucțiunea anterioară,​ dar valoarea rămâne în vârful stivei. |
 | fstp QWORD [registru] ​ | Citește o valoare de tip double (8 octeți) din vârful stivei și o salvează la adresa indicată de registru, eliminând valoarea de pe stivă | | fstp QWORD [registru] ​ | Citește o valoare de tip double (8 octeți) din vârful stivei și o salvează la adresa indicată de registru, eliminând valoarea de pe stivă |
Line 90: Line 91:
 | ficom word [registru] | Compara prima valoare de pe stivă cu un număr întreg pe 2 octeți de la adresa indicată de registru | | ficom word [registru] | Compara prima valoare de pe stivă cu un număr întreg pe 2 octeți de la adresa indicată de registru |
 | ficom dword [registru] | Compară prima valoare de pe stivă cu un număr întreg pe 4 octeți de la adresa indicată de registru | | ficom dword [registru] | Compară prima valoare de pe stivă cu un număr întreg pe 4 octeți de la adresa indicată de registru |
-ficomp dword [registru] | Compară prima valoare de pe stivă cu un număr întreg pe octeți de la adresa indicată de registru | +ficom qword [registru] | Compară prima valoare de pe stivă cu un număr întreg pe octeți de la adresa indicată de registru | 
-| ficomp dword/word [registru] | Similar cu instrucțiunile anterioare, dar elimină și prima valoare de pe stivă |+| ficomp ​word/dword/qword [registru] | Similar cu instrucțiunile anterioare, dar elimină și prima valoare de pe stivă |
 | ftst | Compară prima valoare de pe stivă cu 0.0. | | ftst | Compară prima valoare de pe stivă cu 0.0. |
  
Line 146: Line 147:
  
     fld qword [n1]     fld qword [n1]
-    ​fld qword [n2]+    ​fadd qword [n2]
  
     sub esp, 8      ; rezervă loc pe stivă pentru rezultat, pasat ca argument funcției printf.     sub esp, 8      ; rezervă loc pe stivă pentru rezultat, pasat ca argument funcției printf.
-    fadd 
     fstp qword [esp]; mută rezultatul adunării în spațiul rezervat.     fstp qword [esp]; mută rezultatul adunării în spațiul rezervat.
  
Line 219: Line 219:
 ==== [1p] 1. Tutorial: Suma unui vector de numere fracționare ==== ==== [1p] 1. Tutorial: Suma unui vector de numere fracționare ====
  
-În fișierul ''​suma.asm''​ din directorul ​''​ex1''​ găsiți un exemplu de adunare a valorilor dintr-un vector de numere fracționare. La final, rezultatul este afișat folosind ''​printf''​. ​+În fișierul ''​suma.asm''​ din subdirectorul ​''​ex1/''​ găsiți un exemplu de adunare a valorilor dintr-un vector de numere fracționare. La final, rezultatul este afișat folosind ​funcția ​''​printf''​. ​
  
 Parcurgeți și înțelegeți exemplul dat. Deschideți-l folosind SASM și rulați-l. Parcurgeți și înțelegeți exemplul dat. Deschideți-l folosind SASM și rulați-l.
Line 227: Line 227:
 ==== [1p] 2. Media unui vector de numere fracționare ==== ==== [1p] 2. Media unui vector de numere fracționare ====
  
-Acum că am văzut cum putem calcula suma elementelor unui vector, ne propunem să calculăm media acestora. Pentru aceasta trebuie să calculăm mai întai suma (vă puteți inspira din exemplul anterior) și să împărțim la numărul de elemente.  +Acum că am văzut cum putem calcula suma elementelor unui vector, ne propunem să calculăm media acestora. Pentru aceasta trebuie să calculăm mai întai suma (vă puteți inspira din exemplul anterior) și să împărțim la numărul de elemente. 
-Urmăriți comentariile marcate cu TODO din fișierul ''​media.asm''​ din directorul ​''​ex2''​.+  
 +Urmăriți comentariile marcate cu ''​TODO'' ​din fișierul ''​media.asm''​ din subdirectorul ​''​ex2/''​ și completați corespunzător pentru calcularea mediei vectorului de elemente ''​vector''​.
  
 <note tip> <note tip>
-Împărțirea se face la un număr întreg. Folosiți instrucțiunea ''​fidiv''​ pentru a împărți valoarea din vârful stivei FPU la un număr cu reprezentare de număr întreg.+Împărțirea se face la un număr întreg ​(adică se împarte la lungimea vectorului ''​vector''​). Folosiți instrucțiunea ''​fidiv''​ pentru a împărți valoarea din vârful stivei FPU la un număr cu reprezentare de număr întreg.
 </​note>​ </​note>​
 ==== [1p] 3. Împărțirea a două numere întregi cu rezultat fracționar ==== ==== [1p] 3. Împărțirea a două numere întregi cu rezultat fracționar ====
  
-În fișierul ''​integer-div.asm''​ din directorul ​''​ex3'',​ completați locurile marcate cu TODO pentru a efectua împărțirea numerelor întregi n1 și n2, iar rezultatul să fie un număr fracționar. La final, afișați rezultatul.+În fișierul ''​integer-div.asm''​ din subdirectorul ​''​ex3/'',​ completați locurile marcate cu ''​TODO'' ​pentru a efectua împărțirea numerelor întregi ​''​n1'' ​și ''​n2''​, iar rezultatul să fie un număr fracționar. La final, afișați rezultatul.
  
 <note tip> <note tip>
Line 245: Line 246:
 ==== [2p] 4. Extragere parte întreagă și fracționară ===== ==== [2p] 4. Extragere parte întreagă și fracționară =====
  
-Completați secțiunile marcate cu TODO din fișierul ''​extract.asm''​, directorul ​''​ex4'',​ pentru a extrage partea întreagă și partea fracționară a numărului fracționar ''​n''​.+Completați secțiunile marcate cu ''​TODO'' ​din fișierul ''​extract.asm'' ​din subdirectorul ​''​ex4/'',​ pentru a extrage partea întreagă și partea fracționară a numărului fracționar ''​n''​.
  
 <note tip> <note tip>
-Pentru a extrage partea întreagă puteți folosi instrucțiunea ''​FISTTP ​dword <​adresa>'',​ care extrage prima valoare din vârful stivei FPU, o trunchiază și o stochează ca un întreg la adresa specificată.+Pentru a extrage partea întreagă puteți folosi instrucțiunea ''​fisttp ​dword <​adresa>'',​ care extrage prima valoare din vârful stivei FPU, o trunchiază și o stochează ca un întreg la adresa specificată
 +</​note>​ 
 + 
 +<note tip> 
 +Instrucțiunea ''​fisttp''​ este o instrucțiune validă, chiar dacă nu este colorată în ''​SASM''​. 
 +</​note>​ 
 + 
 +<note tip> 
 +Instrucțiunea ''​fisttp''​ face și pop la valoarea din vârful stivei FPU. De aceea, pentru obținerea părții fracționare,​ va trebui să reîncărcați valoarea numărului fracționar ''​n''​ (folosind ''​fld''​) înainte de scădea valoarea întregii din acesta folosind instrucțiunea ''​fisub''​.
 </​note>​ </​note>​
 ==== [2p] 5. Media unui vector de întregi cu rezultat fracționar ==== ==== [2p] 5. Media unui vector de întregi cu rezultat fracționar ====
  
-Similar cu exercițiul 2, ne propunem să calculăm media unui vector de elemente, dar în acest caz valorile sunt întregi. Rezultatul trebuie, bineînțeles,​ să fie fracționar. Completați locurile marcate cu TODO din fișierul ''​media-int.asm'',​ directorul ''​ex5''​.+Similar cu exercițiul 2, ne propunem să calculăm media unui vector de elemente, dar în acest caz valorile sunt întregi. Rezultatul trebuie, bineînțeles,​ să fie fracționar. Completați locurile marcate cu ''​TODO'' ​din fișierul ''​media-int.asm'',​ directorul ''​ex5''​.
  
 <note tip> <note tip>
Line 263: Line 272:
 ==== [2p] 6. Maximul dintr-un vector de numere fracționare ==== ==== [2p] 6. Maximul dintr-un vector de numere fracționare ====
  
-Completați fișierul ''​max.asm''​ din directorul ​''​ex6''​ pentru a afla valoarea maximă din vector. Parcurgerea elementelor și comparația cu valoarea maximă este implementată. Urmăriți comentariile ce conțin TODO.+Completați fișierul ''​max.asm''​ din subdirectorul ​''​ex6/''​ pentru a afla valoarea maximă din vector. Parcurgerea elementelor și comparația cu valoarea maximă este implementată. Urmăriți comentariile ce conțin ​''​TODO''​. 
 + 
 +<note tip> 
 +Pentru a determina instrucțiunea de jump folosită după ''​fcomip''​ urmăriți răspunsul de [[http://​stackoverflow.com/​a/​7057771|aici]]. 
 +</​note>​
  
 <note tip> <note tip>
 Pentru a scoate prima valoare de pe stiva FPU fără a o stoca la o adresă, puteți folosi instrucțiunea ''​fstp ST0''​. Pentru a scoate prima valoare de pe stiva FPU fără a o stoca la o adresă, puteți folosi instrucțiunea ''​fstp ST0''​.
 +</​note>​
 +
 +<note tip>
 +Valoarea variabilei ''​max''​ trebuie să ajungă pe stivă. Întrucât valoarea are 8 octeți sunt necesare două operații de tip ''​%%push dword ...%%''​. Întâi faceți push la ultimii 4 octeți ai valorii variabilei ''​max''​ și apoi la primii 4 octeți. Astfel vârful stivei va referi primii 4 octeți ai valorii variabilei ''​max''​ urmați de ultimii 4 octeți.
 </​note>​ </​note>​
 ==== [2p Bonus] 7. Implementare arcsin ==== ==== [2p Bonus] 7. Implementare arcsin ====
  
-În fișierul ''​arcsin.asm''​ din directorul ​''​ex7'',​ calculați valoarea unghiului pentru care funcția sin întoarce valoarea din variabila ''​valoare_sin''​.\\+În fișierul ''​arcsin.asm''​ din subdirectorul ​''​ex7/'',​ calculați valoarea unghiului pentru care funcția sin întoarce valoarea din variabila ''​valoare_sin''​. 
 Pentru rezolvare veți căuta în intervalul [0, pi/2], folosind metoda bisecției: la fiecare pas calculați valoarea funcției sin în valoarea de la jumătatea intervalului și alegeți jumătatea de interval în care se găsește valoarea căutată (funcția este crescătoare pe intervalul [0, pi/2]). Algoritmul se va opri atunci când eroarea este mai mică decât ''​0.0005''​ (diferența între valoarea obținută și valoarea căutată). Pentru rezolvare veți căuta în intervalul [0, pi/2], folosind metoda bisecției: la fiecare pas calculați valoarea funcției sin în valoarea de la jumătatea intervalului și alegeți jumătatea de interval în care se găsește valoarea căutată (funcția este crescătoare pe intervalul [0, pi/2]). Algoritmul se va opri atunci când eroarea este mai mică decât ''​0.0005''​ (diferența între valoarea obținută și valoarea căutată).
laboratoare/laborator-12.1452695284.txt.gz · Last modified: 2016/01/13 16:28 by razvan.deaconescu