Architecture des ordinateurs TP5 – La famille Intel 80x86 et NASM (2 séances) Ce TP utilise le processeur Intel de votre ordinateur. On utilise la commande nasm pour assembler les fichiers assembleurs et la commande ald pour le débogage. Une documentation sur nasm est disponible à http://deptinfo.unice.fr/~fmallet/archi/nasmdoc.pdf, cette documentation contient également la liste des instructions Intel que nous pouvons utiliser ainsi qu'une courte description de leur fonctionnement et des modes d'adressage autorisés. La commande nasm est directement accessible sur vos machines. La commande ald quant à elle n'est pas accessible directement, vous devez la copier sur votre compte depuis ~fmallet/bin/ald. Modifier éventuellement votre variable PATH pour y accéder plus facilement. La commande ald lance un environnement textuel interactif qui permet de déboguer des fichiers exécutables. Sous cet environnement taper help pour avoir la liste de toutes les commandes disponibles. Ce TP permet essentiellement la prise en main des outils ald et nasm. Exercice 5.1 – Mon premier programme On veut écrire un programme simple qui effectue l'opération arithmétique 8+5+3*2. 1. Dans une première version, on n'utilisera que les modes d'adressage par registre et immédiat (pas de mode d'adressage direct). Consulter la documentation (nasm) pour les instructions add, mul et mov afin de réaliser ce programme. On considère que 3, 2, 5 et 8 sont des octets (8 bits) non signés. 2. Taper votre programme dans le fichier premier.asm sans oublier de déclarer la section .text et de rendre global le label _start. Compiler votre programme par : nasm -f elf premier.asm. Faire l'édition de lien par : ld -o premier premier.o. Vérifier que le fichier exécutable premier a bien été créé. 3. Exécuter le programme premier, que se passe-t-il ? Expliquer. 4. Charger le programme premier avec le débogueur ald : ald premier. Utiliser la commande file pour déterminer l'adresse de la première instruction du programme. On pourra pour cela utiliser file secinfo pour déterminer la taille et l'adresse de début des sections. Mais rien ne garantie que le programme commence au début de la section .text. On peut alors utiliser la commande file header pour déterminer le point d'entrée effectif (entry point). 5. Utiliser la commande examine (exam comme raccourci) pour examiner sous forme hexadécimale la section .text de la mémoire. Cette forme est bien entendue très peu lisible. On pourra l'utiliser pour examiner les sections de données, on utilisera en revanche la commande disassemble (disass comme raccourci) pour examiner les sections de programme. Une façon plus agréable de dé-assembler une section donnée est : disass -section .text. 6. Constater la taille très variable des instructions. 7. Utiliser la commande register pour voir l'état des registres (tous ou 1 en particulier) ou modifier leur valeur. Quel est le registre qui indique l’adresse de la prochaine instruction à exécuter ? Comment faire pour recommencer un programme au début ? 8. Utiliser la commande step pour exécuter votre programme pas à pas et vérifier qu'il réalise le comportement souhaité. Où est la fin du programme ? 9. Établir un point d’arrêt (commande break) après la dernière instruction valide de votre programme, ré-exécuter votre programme avec la commande continue. Ce serait bien plus facile si on avait des labels ? Ajoutez-en un, recompilez ! Frédéric Mallet Licence Informatique L3 2006/2007 Architecture des ordinateurs Exercice 5.2 – Modes d'adressage direct et section de données. On veut maintenant exécuter le même programme avec des valeurs différentes. 1. Essayer d'utiliser la commande enter pour modifier directement dans le programme une des valeurs (ex., on effectuera 8+3+5x2 au lieu de 8+5+3x2). 2. Proposer une solution, en réalisant un autre programme assembleur qui utilise une section de donnée et les modes d'adressage direct. Comparer la taille des instructions utilisées avec la solution précédente. On mémorisera le résultat dans la mémoire (section de données non initialisées .bss). On utilisera la commande file secinfo pour déterminer l'adresse des zones de données et vérifier que le programme fait bien ce qu'il est supposé faire. 3. On pourra constater que ça n'a pas l'air de fonctionner correctement, désassembler votre programme pour identifier le bug de ald et constater que le résultat est en réalité correct. 4. Ré-exécuter plusieurs fois le même programme avec des valeurs différentes sans sortir de l'environnement ald (commande enter). On essaiera en particulier d'exécuter l'opération 8 + 5 + 3 x -2. Que se passe-t-il? 5. Proposer une solution qui utilise l'instruction imul. 6. Pour mettre en évidence l'importance de faire la différence entre mul et imul on réalisera un programme qui effectue l'opération (3x-2)/2 en utilisant l'instruction div puis l'instruction idiv. Exercice 5.3 – Calcul du maximum dans un tableau On veut maintenant réaliser un programme qui calcule la valeur maximum dans un tableau d'octets. 1. Écrire un programme assembleur qui réalise ce comportement, on utilisera les instructions loop, cmp et js. Tester votre programme avec le tableau 0x43, 0x56, 0x5, 0x60, 0x80, 0x12, 0x9. 2. Utiliser la directive de compilation $ pour calculer la taille du tableau sans effort. 3. Tester votre programme avec le tableau 0x43, 0x56, 0x5, 0x60, 0x-80, 0x12, 0x9. Quel est le résultat obtenu ? 4. Corriger votre programme pour qu'il accepte des nombres négatifs. Quels sont les avantages et inconvénients de faire ça ? Exercice 5.4 – L'unité nombres réels (FPU) On veut réaliser un programme qui utilise le FPU pour calculer le cosinus et le sinus de PI et PI/2. Ne pas oublier d’initialiser le FPU avec l’instruction FINIT avant toute opération. 1. Réaliser un premier programme qui réalise le calcul sur PI, en utilisant les instructions FLDPI, FSIN, FCOS et FSTP pour faire le calcul et mémoriser le résultat dans la mémoire. Attention à manipuler des données de la bonne taille. Commenter sur la précision obtenue pour sinus de PI. 2. Modifier ce programme pour réaliser le calcul sur PI/2. Utiliser la commande examine pour vérifier que le codage de 2 est correct. On utilisera successivement FDIV et FIDIV. 3. Améliorer votre programme en utilisant la commande FSINCOS. 4. On veut maintenant comparer le gain obtenu. Pour cela il faut répéter les opérations plusieurs fois (plus de 16 millions de fois sur mon ordinateur) pour obtenir une différence significative. On terminera le programme par : MOV EAX,1 MOV EBX,0 INT 0x80 pour le rendre exécutable sans l'utilisation de ald (on expliquera ce bout de code au prochain TP). 5. Utiliser la commande unix time pour comparer les performances des 2 solutions. Frédéric Mallet Licence Informatique L3 2006/2007