Première séance machine Notions de base en langage d

publicité
Première séance machine
Notions de base en langage d’assemblage
Ensimag
2009
1
Accès à votre environnement
Les expérimentations se feront sur la machine telesun, votre machine habituelle.
2
2.1
Le travail à effectuer
PGCD
La séance a pour objectif de vous faire faire une première expérience d’exécution de programme assembleur et de se familiariser avec l’utilisation de l’outil de mise au point gdb sur des fichiers assembleur. Cette
expérience se fera en exécutant un programme élémentaire calculant le pgcd de deux nombres.
Commencez par télécharger l’archive LdB-pgcd-seance-5.tgz depuis EnsiWiki, puis décompressezlà :
telesun> tar xzvf LdB-pgcd-seance-5.tgz
telesun> cd LdB-pgcd-seance-5
Vous trouverez un fichier pgcd.s. Ouvrez-le dans une nouvelle fenêtre (utilisez un l’éditeur de texte
de votre choix si vous le préférez à Emacs) :
telesun> emacs &
En conservant la fenêtre emacs dans un coin de l’écran, vous produirez ensuite un listing d’assemblage
et un fichier exécutable en utilisant la commande (attention pas d’espace avant le -a) :
gcc -Wa,-a pgcd.s -o pgcd > pgcd.l
(si on n’a pas besoin du listing d’assemblage, on peut aussi faire simplement gcc pgcd.s -o pgcd)
Ouvrez le listing d’assemblage dans un éditeur de texte. Ce listing vous détaille le travail qu’a fait
l’assembleur, il affiche le contenu binaire généré (en hexa) pour chaque ligne de code, et termine par un
récapitulatif des symboles définis.
Vous chargerez ensuite le programme dans gdb au moyen de la commande :
gdb pgcd
La première chose à faire consiste à poser un point d’arrêt au début du programme par la commande
br main. Il est possible de lancer l’exécution du programme (run), qui s’arrêtera à main, puis d’exécuter
l’ensemble du programme pas à pas au moyen des commandes si ou ni (équivalentes pour ce programme).
1
Au cours de cette exécution on surveillera l’évolution des registres eax et ecx dans lesquels se font les
calculs (commandes : display $eax et display $ecx ou commande : i reg eax ecx).
Pour l’instant, nous avons compilé notre programme sans l’option -g, donc gdb n’a pas toutes les informations de retour aux sources. Mais nous pouvons tout de même suivre la progression dans le programme toujours visible dans la fenêtre emacs - « à la main » en traçant la (les) prochaine(s) instruction(s) à exécuter
au moyen de la commande :
display /xi $eip, avec x=1 pour une instruction par exemple.
Les deux dernières instructions (leave, ret) redonnent le contrôle à l’environnement et provoquent l’exécution d’instructions qui ne font pas partie du programme et sont donc incompréhensibles pour nous. Il n’y
a plus lieu de continuer en “pas à pas” et il vaut mieux relancer l’exécution (cont).
Cependant après exécution d’une itération de la boucle pas à pas, il est possible d’accélérer le déroulement du programme tout en suivant son évolution en insérant deux nouveaux points d’arrêt (br iter et
br fin). Une fois ces points d’arrêts posés on relance l’exécution par la commande gdb cont. Il est ainsi
possible de connaître le résultat du calcul lors du passage sur le second d’entre eux. Il est aussi possible de
calculer d’autres valeurs de pgcd en modifiant les registres concernés à l’emplacement approprié ou encore
de modifier le programme source pgcd.s afin d’effectuer, de façon analogue, d’autres calculs de pgcd. On
pourra en outre, lors du passage sur le point d’arrêt fin, modifier les registres eax, ecx ainsi que le registre
pointeur d’instructions eip avant de relancer l’exécution.
PGCD de 256 et de 1024 code machine
.text
# Sera expliqué ultérieurement
.global main
# Sera expliqué ultérieurement
main :
pushl %ebp
# Sera expliqué ultérieurement
movl %esp,%ebp
# Sera expliqué ultérieurement
movl $256, %eax
# Chargement de la valeur 256 dans le registre eax
movl $1024, %ecx # Chargement de la valeur 1024 dans le registre eax
iter :
cmpl %eax, %ecx # Comparaison de eax et ecx
je fin
# Saut à fin en cas d’égalite
jl suite
# Saut à suite si ecx est plus petit que eax
subl %eax, %ecx
# Calcul de ecx - eax, resultat dans ecx
jmp iter
# Saut inconditionnel à iter
suite : subl %ecx, %eax
# Calcul de eax - ecx, resultat dans eax
jmp iter
fin :
leave
# Sera expliqué ultérieurement
ret
# Sera expliqué ultérieurement
2.2
Mieux utiliser gdb
Ce que vous avez déjà vu sur gdb lors des séances sur le langage C s’applique aussi ici. En compilant
avec -g, vous pourrez utiliser l’interface de votre choix. Un récapitulatif des commandes utiles, et quelques
commandes plus utiles en assembleur est disponible sur EnsiWiki (gdb.pdf), et plus d’informations sont
données à la fin du sujet.
2
2.3
Multiplication
On trouve bien évidemment dans le langage assembleur x86 des instructions pour multiplier deux
nombres. L’exercice consiste ici à écrire sa propre multiplication en utilisant l’instruction d’addition. En
d’autres termes, pour multiplier un entier A par un entier B, il suffit de faire “A fois” la somme de B.
Vous conserverez le même début de programme jusqu’au chargement des registres contenant les nombres
à multiplier et vous utiliserez l’instruction d’addition que l’on trouve dans le programme du pgcd. D’autres
registres peuvent être utilisés si besoin est : les registres edx, edi et esi. Le registre ebx qui est aussi
utilisable est déconseillé à ce stade de vos connaissances car son utilisation « naïve » provoque des erreurs
lors du rappel du système à la fin d’exécution du programme.
Quelques instructions peuvent vous être utiles comme :
inc %reg # ajoute 1 à la valeur du registre reg
dec %reg # diminue de 1 la valeur du registre reg
2.4
2.4.1
Interfaces plus conviviales pour gdb
Informations de debug : option -g pour gcc
Savoir utiliser un debugger sur un programme exécutable quelconque est parfois utile. Mais quand on
sait qu’on va utiliser un debugger sur un programme, on peut dire au compilateur de générer des informations
de retour aux sources en plus (fichier et numéro de ligne correspondant à chaque instruction entre autres).
Pour gcc, c’est l’option -g.
Essayez de recompiler pgcd en ajoutant -g sur la ligne de commande de compilation, puis recommencez quelques unes des manipulations précédentes. Quand on s’arrête sur un point d’arrêt ou quand on
fait du pas à pas, gdb donne directement le nom du fichier source, et le numéro de la ligne que l’on est
en train d’exécuter. La commande list de gdb permet d’afficher une portion du code source autour de
l’instruction courante.
L’option -g est quasi indispensable pour utiliser ddd et Emacs dans les sections suivantes.
2.4.2
ddd : DataDisplay Debugger
ddd est une interface graphique (« front-end ») qui utilise gdb comme back-end. Pour le lancer, taper
ddd pgcd dans un terminal.
ddd ouvre alors deux fenêtres. L’une affiche le code source, l’autre quelques boutons correspondant à
des commandes gdb. On peut poser un point d’arrêt en double-cliquant sur une ligne. A noter que cette
interface ne vous empêche pas d’utiliser directement les commandes gdb, puisque vous avez une console
gdb en dessous de l’affichage du code source.
2.4.3
Emacs
Utiliser gdb depuis Emacs est également très pratique, mais un peu plus compliqué (donc, vraiment
intéressant pour vous seulement si vous connaissez déjà un peu Emacs. Cela permet en particulier de rester
dans le même environnement pour éditer et débuger des programmes).
Pour lancer gdb, depuis Emacs, faites M-x gdb RET, c’est à dire « Alt-x, puis gdb, puis Entrée ».
Emacs vous demande la commande à exécuter pour lancer gdb. Pour vous, ça sera gdb --anotate=3 pgcd
(qui est le défaut en principe).
3
Ensuite, on a une ligne de commande gdb comme celle que l’on aurait obtenue depuis le terminal, avec
deux choses en plus :
– Un curseur suit l’exécution du programme dans les sources,
– Depuis un fichier source, C-x SPC (« Control-x, puis Espace ») place un point d’arrêt sur cette ligne
du programme.
4
Téléchargement