This shows you the differences between two versions of the page.
alf:laboratoare:12 [2021/05/23 21:57] diana.ghindaoanu [Exercises] |
alf:laboratoare:12 [2021/05/30 23:54] (current) diana.ghindaoanu |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== TP 12 - WebAssembly ====== | + | ====== TP 12 - WebAssembly 2 ====== |
- | ===== Syntax - forme text ===== | + | ===== was ===== |
- | 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]]. | + | was est un utilitaire de ligne de commande pour assembler des fichiers wasm. Il transforme les fichiers texte wat en fichiers binaires wasm. |
- | 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]] | + | La documentation de was est disponible a [[https://github.com/alexandruradovici/was|github]] |
- | ===== Utilisation de Web Assembly ===== | + | ===== Utilisation de was ===== |
- | 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]] | + | Pour installer was, vous devez: |
- | Si vous choisissez de créer votre propre projet, tout d'abour vous devez suivre ces étapes: | + | * Exécuter la commande <code>npm install -g was</code> |
+ | * Cloner le [[https://github.com/diana-ghindaoanu/was|github repository]]. | ||
+ | * Entrer dans le dossier **was** de votre PC et en utilisant la ligne de commande, exécuter:<code>npm install</code> | ||
- | 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 }} | ||
- | Dans le fichier ''main.wat'', vous allez trouver le code suivant : | + | ===== Assembler un programme ===== |
- | {{ :alf:laboratoare:tp12-3.jpg?500 }} | + | |
- | + | ||
- | 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'' | + | |
+ | Pour assembler un programme, utilisez la commande: | ||
- | <note> | + | <code> |
- | Après avoir modifié le contenu d’un fichier, vous devez sauvegarder les changements (Ctrl+S ou le bouton **Save**). | + | ./was/assemble.js nom_du_fichier.wat |
- | </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> | ||
- | <code wat> | + | <note important> |
- | (module | + | Pour exécuter cette commande sans erreurs, vous devez télécharger le repository dans le dossier ou se trouve aussi le programme ''.wat''. |
- | (func $start | + | </note> |
- | ) | + | Cela va générer un programme nommé //nom_du_fichier.wasm//. |
- | (start $start) | + | |
- | ) | + | |
- | </code> | + | |
- | ==== Fonction ==== | + | ===== Exécuter un programme de Web Assembly ===== |
- | <code c> | + | Pour exécuter un programme d'assemblage Web, utilisez la commande: |
- | int sum (int a, int b) | + | |
- | { | + | |
- | } | + | |
- | </code> | + | |
- | <code wat> | + | <code> |
- | (module | + | was run program.wasm |
- | (func $sum (param $a i32) (param $b i32) (result i32) | + | |
- | local.get $a | + | |
- | local.get $b | + | |
- | i32.add | + | |
- | return | + | |
- | ) | + | |
- | ) | + | |
</code> | </code> | ||
- | ==== Attribution de variable local ==== | + | ===== Définir une mémoire ===== |
- | <code c> | + | Pour exécuter un programme de Web Assembly avec une mémoire, utilisez la commande suivante: |
- | int name () | + | |
- | { | + | |
- | int a; | + | |
- | a = 0; | + | |
- | return a; | + | |
- | } | + | |
- | </code> | + | |
- | <code wat> | + | <code> |
- | (module | + | was run program.was -m 1:1 |
- | (func $name (local $a i32) (result i32) | + | |
- | i32.const 0; | + | |
- | local.set $a | + | |
- | local.get $a | + | |
- | return | + | |
- | ) | + | |
- | ) | + | |
</code> | </code> | ||
- | ==== Import function ==== | + | Ceci lancera le programme avec une mémoire de minimum 1 page et maximum 1 page. |
- | + | ||
- | <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 ==== | ||
- | 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]]. | + | - Installez "was". Montrer l'aide de "was". (**1p**) |
- | + | - Ecrivez un programme wat qui importe les fonctions readint et writeint à partir du module "io". Utilisez les fonctions et lisez un numéro du clavier et affichez sa deuxième puissance. (**1p**) | |
- | <note info>Veuillez utiliser Firefox ou Chrome.</note> | + | - Désassemblez le programme précédent dans un fichier nommé program_disassemble.wat. Essayez de faire la même chose en utilisant les options --debug, --names et --fold. (note: assembler le fichier program.wat en utilisant l'option --debug). (**1p**) |
- | + | - Écrivez un programme qui lit un caractère en minuscule du clavier et affiche son caractère majuscule. (**1p**) | |
- | <note important> | + | - Ecrivez un programme qui importe une mémoire avec 1 page. En utilisant l'instruction //data//, ajoutez votre groupe à la mémoire à la position 0 suivi d'un 0 (\00). Utilisez la fonction //writestr// de la bibliothèque //io// pour imprimer votre nom. (**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''. | + | - Ecrivez une fonction "afficher" qui fait la même chose que la fonction //writestr//. Elle obtient un paramètre, l'adresse où un string est situé dans la mémoire. (indice: commencez à la position initiale et écrivez des caractères de la mémoire jusqu'à ce que vous trouviez un 0) (**2p**) |
- | </note> | + | - Écrivez un programme qui lit une adresse mémoire (sous forme de nombre), lit une chaîne à cette adresse mémoire (maximum 10 caractères) et imprime la chaîne à l'aide de la fonction de l'exercice précédent. (**1p**) |
+ | - Ecrivez une fonction de lecture qui fait la même chose que //readstr//. La fonction prend comme premier paramètre l'adresse mémoire où il doit lire la chaîne et un autre paramètre avec la longueur maximale de la chaîne. (**2p**) | ||
- | - Ecrivez dans un fichier **ex1.txt** le code WebAssembly pour le calcul de l'expression 5-4*2/(1+3).(**1p**) | ||
- | - 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//. (**1p**) | ||
- | - 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]. (**1p**) | ||
- | - 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. (**1p**) | ||
- | <hidden> | ||
- | ==== Solutions ==== | ||
- | [[https://github.com/alexandruradovici/alf2018/tree/master/TP/TP11|Solutions]] | ||
- | </hidden> | ||