This shows you the differences between two versions of the page.
alf:laboratoare:11 [2020/04/27 22:16] alexandru.radovici |
alf:laboratoare:11 [2021/05/25 00:37] (current) diana.ghindaoanu |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== TP 11 - Assembly ====== | + | ====== TP 11 - WebAssembly ====== |
- | In acest laborator vom folosi simulatorul pentru limbaj de asamblare [[https://schweigi.github.io/assembler-simulator/]]. Acesta simuleaza un procesor cu urmatoarele caracteristici: | + | ===== Syntax - forme text ===== |
- | * 4 Hz | + | |
- | * 4 registre de uz general A, B, C si D | + | |
- | * un registru pentru instructiunea curenta IP | + | |
- | * un regsitru pentru varful stivei SP | + | |
- | * 256 B RAM | + | |
- | * 24 B memorie video (ultimii bytes din memoria RAM) | + | |
- | ===== Setul de instructiuni ===== | + | Avant de commencer le TP, lisez le tutoriel suivant: [[https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format|Mozilla Web Assembly Tutorial]]. |
- | Setul de instructiuni reprezinta comenzile pe care un procesor le poate executa. Acest procesor stie urmatoarele instructiuni: | + | Pour plus d'informations, la documentation de Web Assembly est disponible ici: [[https://webassembly.github.io/spec/core/index.html|WebAssembly Specification]] et [[https://webassembly.github.io/spec/core/appendix/index-instructions.html|Index of Instructions]] |
- | * mov - atribuire de date | + | |
- | * add - adunare | + | |
- | * sub - scadare | + | |
- | * inc - incrementare | + | |
- | * dec - decrementare | + | |
- | * mul - inmultire | + | |
- | * div - impartire | + | |
- | * and - si pe biti | + | |
- | * or - sau pe biti | + | |
- | * xor - xor pe biti | + | |
- | * not - negarea bitilor | + | |
- | * shl - sifatre la stanga (echivalent cu inmultirea cu 2) | + | |
- | * shr 0 siftare la dreapta (echivalent cu impartirea cu 2) | + | |
- | * cmp - comparare | + | |
- | * jmp - salt | + | |
- | * j.. - salt (aici sunt mai multe instructiuni) | + | |
- | * call - apel de functie | + | |
- | * ret - intarcere din functie | + | |
- | * hlt - oprirea procesorului | + | |
- | * push - punerea pe stiva | + | |
- | * pop - stergerea de pe stiva si punerea intr-un registru | + | |
- | Setul de instructiuni cu descrierea lor este disponibil pe site-ul simulatorului [[https://schweigi.github.io/assembler-simulator/instruction-set.html]]. | + | ===== Utilisation de Web Assembly ===== |
+ | Pour tester les exemples présentés dans ce TP, on va utiliser la page destinée a Web Assembly: [[https://webassembly.studio/|Web Assembly Studio]] | ||
+ | Si vous voulez commencer votre travail a partir d'un programme deja créé, vous pouvez accéder a ce [[https://webassembly.studio/?f=9o45ipku27|lien]] | ||
+ | |||
+ | Si vous choisissez de créer votre propre projet, tout d'abour vous devez suivre ces étapes: | ||
+ | |||
+ | Sélectionnez l’option **Empty Wat Project** et appuyez sur **Create**: | ||
+ | {{ :alf:laboratoare:tp12-1.jpg?500&nolink }} | ||
+ | |||
+ | Dans la nouvelle fenetre ouverte, vous pouvez modifier les fichiers qui se trouvent dans le dossier //src//. Pour la partie JavaScript, vous allez modifier le code source du fichier ''main.js'', en le remplacant comme dans l'exemple suivant : | ||
+ | {{ :alf:laboratoare:tp12-2.jpg?500&nolink }} | ||
+ | |||
+ | Dans le fichier ''main.wat'', vous allez trouver le code suivant : | ||
+ | {{ :alf:laboratoare:tp12-3.jpg?500&nolink }} | ||
+ | |||
+ | Ici, on a créé une fonction qui réalise l’opération d’addition entre 2 numéros donnés comme paramètres et qui retourne le résultat (la somme). L’appel de cette fonction a été realisé précédemment dans le fichier ''main.js'' | ||
+ | |||
+ | |||
+ | <note> | ||
+ | Après avoir modifié le contenu d’un fichier, vous devez sauvegarder les changements (Ctrl+S ou le bouton **Save**). | ||
+ | </note> | ||
+ | |||
+ | Pour exécuter le programme, vous devez appuyer sur le bouton **Build&Run** et le résultat de votre programme sera affiché dans la section **Output**. | ||
+ | |||
+ | ===== Translation de code en Web Assembly ==== | ||
+ | |||
+ | ==== Program Principal ==== | ||
+ | |||
+ | <code c> | ||
+ | int main () | ||
+ | { | ||
+ | return 0; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code wat> | ||
+ | (module | ||
+ | (func $start | ||
+ | ) | ||
+ | (start $start) | ||
+ | ) | ||
+ | </code> | ||
+ | |||
+ | ==== Fonction ==== | ||
+ | |||
+ | <code c> | ||
+ | int sum (int a, int b) | ||
+ | { | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code wat> | ||
+ | (module | ||
+ | (func $sum (param $a i32) (param $b i32) (result i32) | ||
+ | local.get $a | ||
+ | local.get $b | ||
+ | i32.add | ||
+ | return | ||
+ | ) | ||
+ | ) | ||
+ | </code> | ||
+ | |||
+ | ==== Attribution de variable local ==== | ||
+ | |||
+ | <code c> | ||
+ | int name () | ||
+ | { | ||
+ | int a; | ||
+ | a = 0; | ||
+ | return a; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code wat> | ||
+ | (module | ||
+ | (func $name (local $a i32) (result i32) | ||
+ | i32.const 0; | ||
+ | local.set $a | ||
+ | local.get $a | ||
+ | return | ||
+ | ) | ||
+ | ) | ||
+ | </code> | ||
+ | |||
+ | ==== Import function ==== | ||
+ | |||
+ | <code wat> | ||
+ | (module | ||
+ | (import "io" "print" (func $print (param i32))) | ||
+ | (func $start | ||
+ | i32.const 120 | ||
+ | call $print) | ||
+ | (export "start" (func $start)) | ||
+ | ) | ||
+ | </code> | ||
+ | |||
+ | === Structure du fichier Javascript pour afficher la valeur sur l'ecran=== | ||
+ | |||
+ | <code javascript> | ||
+ | fetch('../out/main.wasm').then(response => | ||
+ | response.arrayBuffer() | ||
+ | ).then(bytes => WebAssembly.instantiate(bytes, { | ||
+ | io: { | ||
+ | print: console.log | ||
+ | } | ||
+ | })).then(results => { | ||
+ | let instance = results.instance; | ||
+ | // instance is your webassembly module | ||
+ | let asm = instance.exports; | ||
+ | // asm is an object with all the items that you exported | ||
+ | console.log (asm.start()); | ||
+ | }).catch(console.error); | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== if ==== | ||
+ | |||
+ | <code c> | ||
+ | if (a>b) | ||
+ | { | ||
+ | print (a); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | print (b); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code wat> | ||
+ | ;; import the print function | ||
+ | local.get $a | ||
+ | local.get $b | ||
+ | i32.gt | ||
+ | if | ||
+ | local.get $a | ||
+ | call $print | ||
+ | else | ||
+ | local.get $b | ||
+ | call $print | ||
+ | end | ||
+ | </code> | ||
+ | |||
+ | ==== while ==== | ||
+ | |||
+ | <code c> | ||
+ | a=1; | ||
+ | while (a<120) | ||
+ | { | ||
+ | print (a); | ||
+ | a=a+1 | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code wat> | ||
+ | ;; import the print function | ||
+ | i32.const 1 | ||
+ | set_local $a | ||
+ | block $endwhile | ||
+ | loop $while | ||
+ | local.get $a | ||
+ | i32.const 120 | ||
+ | i32.gt | ||
+ | br_if $endwhile | ||
+ | local.get $a | ||
+ | call $print | ||
+ | local.get $a | ||
+ | i32.const 1 | ||
+ | i32.add | ||
+ | local.set $a | ||
+ | br $while | ||
+ | end $while | ||
+ | end $endwhile | ||
+ | </code> | ||
+ | |||
+ | ==== for ==== | ||
+ | |||
+ | <code c> | ||
+ | for (i=1; i<120; i++) | ||
+ | { | ||
+ | print (a); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code wat> | ||
+ | ;; import the print function | ||
+ | i32.const 1 | ||
+ | local.set $i | ||
+ | block $endfor | ||
+ | loop $for | ||
+ | local.get $i | ||
+ | i32.const 120 | ||
+ | i32.gt | ||
+ | br_if $endfor | ||
+ | local.get $i | ||
+ | call $print | ||
+ | local.get $i | ||
+ | i32.const 1 | ||
+ | i32.add | ||
+ | local.set $i | ||
+ | br $for | ||
+ | end $for | ||
+ | end $endfor | ||
+ | </code> | ||
+ | |||
+ | ==== do-while ==== | ||
+ | |||
+ | <code c> | ||
+ | a=1; | ||
+ | do | ||
+ | { | ||
+ | print (a); | ||
+ | a=a+1 | ||
+ | } while (a<=120); | ||
+ | </code> | ||
+ | |||
+ | <code wat> | ||
+ | ;; import the print function | ||
+ | i32.const 1 | ||
+ | local.set $a | ||
+ | loop $dowhile | ||
+ | local.get $a | ||
+ | call $print | ||
+ | local.get $a | ||
+ | i32.const 1 | ||
+ | i32.add | ||
+ | local.set $a | ||
+ | local.get $a | ||
+ | i32.const 120 | ||
+ | i32.le | ||
+ | br_if $dowhile | ||
+ | end $dowhile | ||
+ | </code> | ||
==== Exercises ==== | ==== Exercises ==== | ||
- | - Rulati programul initial si incercati sa va dati seama cum sa va scrieti numele la output (**2p**) | + | Pour les exercices suivants, vous pouvez écrire et envoyer le code source dans des fichiers texte. Vous devez ajouter aussi le code WAT, que le code JavaScript. Pour tester la validité de vos programmes, vous devez utiliser [[https://webassembly.studio/?f=9o45ipku27|le project]]. |
- | - Scrieti un program care pune in registrele A, B, C si D numerele 1, 3, 5 si 7 (**1p**) | + | |
- | - Scrieti codul pentru a calcula restul impartirii valorii din registrul A la valoarea din registrul B (**1p**) | + | <note info>Veuillez utiliser Firefox ou Chrome.</note> |
- | - Scrieti care afiseaza in output 0 de atatea ori cat valoarea din registru A. (**2p**) | + | |
- | - Scrieti un program si o functie care calculeaza restul impartirii a doua variabile. Trimitei parametrii functiei folosind registre registre (**1p**). | + | <note important> |
- | - Scrieti un program si o functie care calculeaza restul impartirii a doua variabile. Trimitei parametrii functiei folosind stiva (**1p**). | + | Pour ces exercices que vous allez résoudre en Web Assembly Studio, vous allez utiliser ''get_local'' et ''set_local'' au lieu de ''local.get'' et ''local.set''. |
- | - Scrieti un program si o functie care calculeaza dimensiunea unui string stocat sub forma unei variabile. Puteti incepe de la exemplul din primul program. Functia trebuie sa fie reapelabila din interiorul ei. (**2p**) | + | </note> |
- | - **Bonus** Scrieti un program si o functie care calculeaza sirul a(n) = a(n-1)*a(n-2), a(0) este 1 si a(1) este 2. (**2p**) | + | |
+ | - Ecrivez dans un fichier **ex1.txt** le code WebAssembly pour le calcul de l'expression 5-4*2/(1+3).(**1.5p**) | ||
+ | - Ecrivez un programme (//wat// et //js//) qui a une fonction de démarrage //start// et affiche sur l'écran le numéro correspondant a votre date de naissance. Utilisez [[https://webassembly.studio/?f=lmyi28gq7it|l'exemple]]. (**1p**) | ||
+ | - Ecrivez un programme qui initialise 3 variables **locales** avec les valeurs 4, 5 et 6 dans la fonction //start// et calcule le résultat de l'expression ''a+b%c''. (**1p**) | ||
+ | - Ecrivez un programme avec qui inclut la déclaration d'une fonction qui calcule et affiche la moyenne arithmétique des 3 numéros donnés comme parametres. Appelez la fonction dans la fonction //start//. (**1.5p**) | ||
+ | - Ecrivez une fonction qui calcule de reste de la disivion de son parametre par 5. Dans la fonction //start//, appelez la fonction //is_divisible// avec le parametre 25. (**1p**) | ||
+ | - Ecrivez une fonction qui affiche sur l'ecran le cube de chaque nombre de l'intervalle [1, 10]. (**2p**) | ||
+ | - Ecrivez une fonction //sq_sum// qui calcule la somme des racines carrées des nombres //pairs// d'un intervalle donné. La fonction reçoit deux paramètres qui représentent les limites de l'intervalle et affiche sur l'écran le résultat. Dans la fonction //start//, appelez la fonction //sq_sum// avec les parametres 0 et 3. (**2p**) | ||
+ | - Ecrivez une fonction qui vérifie si un nombre est premier et affichez 1 si le nombre est premier et 0 dans le cas contraire. (**2p**) | ||
<hidden> | <hidden> |