User Tools

Site Tools


laboratoare:laborator-05

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-05 [2015/11/11 07:59]
razvan.deaconescu [Tutorial: Suma elementelor într-un vector reprezentate pe un octet]
laboratoare:laborator-05 [2016/01/09 18:27] (current)
razvan.deaconescu [[2p] 10. Bonus: Numărul de numere pare și impare dintr-un vector]
Line 92: Line 92:
 <​code>​ <​code>​
  
-mov BYTE PTR [ebx], 2  ; Move 2 into the single byte at memory location EBX +mov byte [ebx], 2  ; Move 2 into the single byte at memory location EBX 
-mov WORD PTR [ebx], 2  ; Move the 16-bit integer representation of 2 into the 2 bytes starting at+mov word [ebx], 2  ; Move the 16-bit integer representation of 2 into the 2 bytes starting at
                        ; address EBX                        ; address EBX
-mov DWORD PTR [ebx], 2 ; Move the 32-bit ​+mov dword [ebx], 2 ; Move the 32-bit ​
  
 </​code>​ </​code>​
Line 105: Line 105:
 Descărcați arhiva, decomprimați-o și accesați directorul aferent. Descărcați arhiva, decomprimați-o și accesați directorul aferent.
  
-==== Tutorial: Înmulțire două numere reprezentate pe un octet ====+==== [0.5p] 1. Tutorial: Înmulțire două numere reprezentate pe un octet ====
  
 Parcurgeți rulați și testați codul  din fișierul ''​multiply.asm''​. În cadrul programului înmulțim două numere definite ca octeți. Pentru a le aputea accesa folosimo construcție de tipul ''​byte [register]''​. Parcurgeți rulați și testați codul  din fișierul ''​multiply.asm''​. În cadrul programului înmulțim două numere definite ca octeți. Pentru a le aputea accesa folosimo construcție de tipul ''​byte [register]''​.
  
 Atunci cănd facem înmulțire procesul este următorul, așa cum este descris și [[https://​en.wikibooks.org/​wiki/​X86_Assembly/​Arithmetic|aici]]:​ Atunci cănd facem înmulțire procesul este următorul, așa cum este descris și [[https://​en.wikibooks.org/​wiki/​X86_Assembly/​Arithmetic|aici]]:​
-  - Plasăm ​înmulțitorul ​în registrul ​''​AL''​ (pentru ​operații pe un byte), registrul ''​AX'' ​(pentru ​operații ​pentru ​cuvânt ​16 biți, 2 octeți) și registrul ''​EAX''​' (pentru ​operații pe dublu cuvânt ​32 de biți, 4 octeți). +  - Plasăm ​deînmulțitul în registrul ​de deînmulțit,​ adică: 
-  - Deînmulțitul este transmis ca argument mnemonicii ''​mul''​.+    - dacă facem operații pe un byte (8 biți, un octet), plasăm deînmulțitul în registrul ''​AL''​
 +    - dacă facem operații ​pe un cuvânt ​(16 biți, 2 octeți, plasăm deînmulțitul în registrul ''​AX''​
 +    - dacă facem operații pe un dublu cuvânt ​(32 de biți, 4 octeți), plasăm deînmulțitul în registrul ''​EAX''​
 +  - Înmulțitorul ​este transmis ca argument mnemonicii ''​mul''​. Înmulțitorul trebuie să aibă aceeași dimensiune ca deînmulțitul.
   - Rezultatul este plasat în două registre (partea //high// și partea //low//).   - Rezultatul este plasat în două registre (partea //high// și partea //low//).
  
 Testați programul. Încercați alte valori pentru ''​num1''​ și ''​num2''​. Testați programul. Încercați alte valori pentru ''​num1''​ și ''​num2''​.
  
-==== Înmulțire două numere ====+==== [2p] 2. Înmulțire două numere ====
  
 Actualizați zona marcată cu ''​TODO''​ în fișierul ''​multiply.asm''​ pentru a permite înmulțirea și a numelor de tip ''​word''​ și ''​dword'',​ adică ''​num1_dw''​ cu ''​num2_dw'',​ respectiv ''​num1_dd''​ și ''​num2_dd''​. Actualizați zona marcată cu ''​TODO''​ în fișierul ''​multiply.asm''​ pentru a permite înmulțirea și a numelor de tip ''​word''​ și ''​dword'',​ adică ''​num1_dw''​ cu ''​num2_dw'',​ respectiv ''​num1_dd''​ și ''​num2_dd''​.
Line 122: Line 125:
 <note tip> <note tip>
 Pentru înmulțirea numerelor de tip ''​word''​ (pe 16 biți), componentele sunt dispuse astfel: Pentru înmulțirea numerelor de tip ''​word''​ (pe 16 biți), componentele sunt dispuse astfel:
-  * În registrul ''​AX''​ se plasează ​înmulțitorul+  * În registrul ''​AX''​ se plasează ​deînmulțitul
-  * Argumentul instrucțiunii ''​mov''​ (posibil un alt registru) este pe 16 biți (fie valoare fie un registru precum ''​BX'',​ ''​CX'',​ ''​DX''​).+  * Argumentul instrucțiunii, înmulțitorul, ​''​mul''​ (posibil un alt registru) este pe 16 biți (fie valoare fie un registru precum ''​BX'',​ ''​CX'',​ ''​DX''​).
   * Rezultatul înmulțirii este dispus în perechea ''​DX:​AX'',​ adică partea "​high"​ a rezultatului în registrul ''​DX'',​ iar partea "​low"​ a rezultatului în registrul ''​AX''​.   * Rezultatul înmulțirii este dispus în perechea ''​DX:​AX'',​ adică partea "​high"​ a rezultatului în registrul ''​DX'',​ iar partea "​low"​ a rezultatului în registrul ''​AX''​.
 +
 +Pentru înmulțirea numerelor de tip ''​dword''​ (pe 32 biți), componentele sunt dispuse astfel:
 +  * În registrul ''​EAX''​ se plasează deînmulțitul.
 +  * Argumentul instrucțiunii,​ înmulțitorul,​ ''​mul''​ (posibil un alt registru) este pe 32 biți (fie valoare fie un registru precum ''​EBX'',​ ''​ECX'',​ ''​EDX''​).
 +  * Rezultatul înmulțirii este dispus în perechea ''​EDX:​EAX'',​ adică partea "​high"​ a rezultatului în registrul ''​EDX'',​ iar partea "​low"​ a rezultatului în registrul ''​EAX''​.
  
 </​note>​ </​note>​
  
-==== Ridicare număr la puterea a treia ====+<​note>​ 
 +La afișarea rezultatului folosiți două instrucțiunii ''​PRINT_UDEC''​ pentru a afișa cele două registre care conțin rezultatul:​ 
 +  * Registrele ''​DX''​ și ''​AX''​ pentru înmulțirea numerelor de tip ''​word''​. 
 +  * Registrele ''​EDX''​ și ''​EAX''​ pentru înmulțirea numerelor de tip ''​dword''​. 
 + 
 +</​note>​ 
 +==== [1p] 3. Ridicare număr la puterea a treia ====
  
 Realizați un program în limbajul de asamblare care ridică un număr la puterea a treia (adică ''​num * num * num''​). Realizați un program în limbajul de asamblare care ridică un număr la puterea a treia (adică ''​num * num * num''​).
Line 138: Line 152:
 Nu definiți un număr foarte mare, pentru a putea fi vizualizat rezultatul înmulțirii în registrul ''​eax''​. Nu definiți un număr foarte mare, pentru a putea fi vizualizat rezultatul înmulțirii în registrul ''​eax''​.
  
-==== Tutorial: Suma elementelor dintr-un vector reprezentate pe un octet ====+==== [0.5] 4. Tutorial: Suma primelor N numere naturale ==== 
 + 
 +În programul ''​sum_n.asm''​ din [[http://​elf.cs.pub.ro/​asm/​res/​laboratoare/​lab-05-tasks.zip|arhiva laboratorului]] este calculată suma primelor ''​num''​ numere naturale. 
 + 
 +Urmăriți codul, observați construcțiile și registrele specifice pentru lucru cu bytes. Rulați codul. 
 + 
 +<note important>​ 
 +Treceți la următorul pas doar după ce ați înțeles foarte bine ce face codul. Vă va fi greu să faceți următorul exercițiu dacă aveți dificultăți în înțelegerea exercițiului curent. 
 +</​note>​ 
 + 
 +==== [1.5p] 5. Suma pătratelor primelor N numere naturale ==== 
 + 
 +Porniți de la programul ''​sum_n.asm''​ și creați un program ''​sum_n_square.asm''​ care să calculeze suma pătratelor primelor ''​num''​ numere naturale. 
 + 
 +<note tip> 
 +Registrele ''​eax''​ și ''​edx''​ le veți folosi la înmulțirea pentru ridicarea la putere (în instrucțiunea ''​mul''​). Astfel că nu veți mai putea folosi (ușor) registrul ''​eax''​ pentru stocarea sumei pătratelor. Pentru a reține suma pătratelor aveți două variante: 
 +  - (mai simplu) Folosiți registrul ''​ebx''​ pentru a reține suma pătratelor. 
 +  - (mai complicat) Înainte de a opera registrul ''​eax''​ salvați valoarea sa pe stivă (folosind instrucțiunea ''​push''​),​ apoi faceți operațiile necesare și apoi restaurați valoarea salvată (folosind instrucțiunea ''​pop''​). 
 + 
 +</​note>​ 
 + 
 +<​note>​ 
 +Pentru verificare, suma pătratelor primelor ''​100''​ de numere naturale este ''​338350''​. 
 +</​note>​ 
 +==== [1p] 6. Tutorial: Suma elementelor dintr-un vector reprezentate pe un octet ====
  
 În programul ''​sum_array.asm''​ din [[http://​elf.cs.pub.ro/​asm/​res/​laboratoare/​lab-05-tasks.zip|arhiva laboratorului]] este calculată suma elementelor unui vector (//array//) de octeți (//bytes//, reprezentare pe 8 biți). În programul ''​sum_array.asm''​ din [[http://​elf.cs.pub.ro/​asm/​res/​laboratoare/​lab-05-tasks.zip|arhiva laboratorului]] este calculată suma elementelor unui vector (//array//) de octeți (//bytes//, reprezentare pe 8 biți).
Line 148: Line 186:
 </​note>​ </​note>​
  
- +==== [2p] 7. Suma elementelor ​dintr-un vector ====
-==== Suma elementelor ​într-un vector ====+
  
 În zona marcată cu ''​TODO''​ din fișierul ''​sum_array.asm''​ completați codul pentru a realiza suma vectorilor cu elemente de tip word (16 biți) și de tip dword (32 de biți); este vorba de vectorii ''​word_array''​ și ''​dword_array''​. În zona marcată cu ''​TODO''​ din fișierul ''​sum_array.asm''​ completați codul pentru a realiza suma vectorilor cu elemente de tip word (16 biți) și de tip dword (32 de biți); este vorba de vectorii ''​word_array''​ și ''​dword_array''​.
Line 164: Line 201:
 </​note>​ </​note>​
  
-==== Suma pătratelor ​elementelor ​într-un vector ====+<​note>​ 
 +Suma elementelor ​celor trei vectori trebuie să fie: 
 +  * ''​sum(byte_array):​ 575''​ 
 +  * ''​sum(word_array):​ 65799 ''​ 
 +  * ''​sum(dword_array):​ 74758117''​
  
-TODO+</​note>​
  
-==== Numărul de numere negative și pozitive ​într-un vector ====+==== [1.5p] 8. Suma pătratelor elementelor dintr-un vector ==== 
 + 
 +Pornind de la programul de la exercițiul anterior, calculați suma pătratelor elementelor dintr-un vector. 
 + 
 +<​note>​ 
 +Puteți folosi vectorul ''​dword_array''​ dar ar trebui să fie mai mici valorile elementelor ca să nu treacă pătratele valorilor acestora de reprezentarea pe 32 de biți. 
 +</​note>​ 
 + 
 +<​note>​ 
 +Dacă folosiți construcția de mai jos (vector cu ''​10''​ elemente)<​code>​ 
 +    dword_array dd 1392, 12544, 7992, 6992, 7202, 27187, 28789, 17897, 12988, 17992 
 +</​code>​ 
 +suma pătratelor va fi ''​2704560839''​. 
 +</​note>​ 
 +==== [1.5p] 9. Bonus: ​Numărul de numere negative și pozitive ​dintr-un vector ==== 
 + 
 +Creați un program care afișează numărul de numere negative, respectiv numărul de numere pozitive dintr-un vector. 
 + 
 +<​note>​ 
 +Definiți un vector care să conțină atât numere negative cât și numare pozitive. 
 +</​note>​ 
 + 
 +<note tip> 
 +Folosiți intrucțiunea ''​cmp''​ și mnemonici de salt condițional. Urmăriți detalii [[https://​en.wikibooks.org/​wiki/​X86_Assembly/​Control_Flow|aici]]. 
 +</​note>​ 
 + 
 +<note tip> 
 +Intrucțiunea ''​inc''​ urmată de un registru incrementează cu ''​1''​ valoarea stocată în acel registru. 
 +</​note>​ 
 + 
 +==== [2p] 10. Bonus: Numărul de numere pare și impare dintr-un vector ==== 
 + 
 +Creați un program care afișează numărul de numere pare, respectiv numărul de numere impare dintr-un vector. 
 + 
 +<note tip> 
 +Puteți folosi instrucțiunea ''​div''​ pentru a împărți un număr la ''​2''​ și pentru a compara apoi restul împărțirii cu ''​0''​. Urmăriți detalii [[https://​en.wikibooks.org/​wiki/​X86_Assembly/​Arithmetic|aici]]. 
 + 
 +Va trebui să folosiți trei registre pentru împărțire:​ ''​EDX''​ și ''​EAX''​ pentru deîmpărțit,​ un alt registru pentru împărțitor (probabil ''​EBX''​). Ceea ce înseamnă că va trebui să salvați pe stivă, înaintea operației de împărțire,​ valorile celor două registre în care rețineți numărul de numere pare și numărul de numere impare. 
 +</​note>​ 
 + 
 +<​note>​ 
 +Pentru testare folosiți un vector doar cu numere pozitive. Pentru numere negative trebuie să faceți extensie de semn; ar merge și fără pentru că ne interesează doar restul, dar nu am fi riguroși :-) 
 +</​note>​
  
-TODO+===== Soluții =====
  
-==== Numărul de numere pare și impare într-un vector ====+[[http://​elf.cs.pub.ro/​asm/​res/​laboratoare/​lab-05-sol.zip|Soluții de referință pentru exercițiile ​de laborator]]
  
-TODO 
laboratoare/laborator-05.1447221577.txt.gz · Last modified: 2015/11/11 07:59 by razvan.deaconescu