Assemblage,l'édition des liens et la compilation

L'objectif

Il est de constater qu'un programme écrit en assembleur fait la même chose qu'un programme écrit en C. Nous allons aussi voir les notions de point d'entrée d'un programme et les différentes phases de compilation. Ce tp comporte trois programmes, hello1.s, hello2.s et hello3.c qui affichent à l'écran le message "hello world !". Vous allez devoir constater les principes de l'assemblage, l'édition des liens et de la compilation

Etape 1

Saisir le programme suivant

hello1.s

  1. .text
  2. message :
  3. .ascii " hello world ! \0 "
  4. .align 4
  5. .global main
  6. main :
  7. pushl %ebp
  8. movl %esp,%ebp
  9. pushl $message
  10. call puts
  11. addl $4,%esp
  12. movl %ebp,%esp
  13. popl %ebp
  14. ret

L'assembler en tapant la commande suivante :

$as hello1.s -o hello1.o

Lancer la commande ls et constater la présence du fichier hello1.o, qui est un fichier binaire compréhensible par le microprocesseur. Faire l'édition des liens en tapant la commande suivante :

$gcc hello1.o -o hello1

Lancer la commande ls et constater la présence du fichier hello1 .

Il était aussi possible de réaliser l'assemblage en tapant la commande :

$gcc -c hello1.s -o hello1.o

Lancer le programme hello1 , il doit vous afficher le message : "hello world !".

Saisir le programme suivant à l'aide de éditeur de texte vim !

hello2.s

  1. .text
  2. message :
  3. .ascii "hello world ! \12\0 "
  4. .align 4
  5. .global _pointdentree
  6. _pointdentree:
  7. movl $4,%eax
  8. movl $1,%ebx
  9. movl $message,%ecx
  10. movl $15,%edx
  11. int $0x80
  12. movl $1,%eax
  13. movl $0,%ebx
  14. int $0x80

L'assembler en tapant la commande suivante :

$as hello2.s -o hello2.o

Lancer la commande ls et constater la présence du fichier hello2.o.
Faire l'édition des liens en tapant la commande suivante :

$ld -o hello2 -e _pointdentree hello2.o

Lancer la commande ls et constater la présence du fichier hello2.
Lancer le programme hello2, il doit vous afficher le message : "hello world !".
Comparer la taille des deux fichiers hello1 et hello2. Nous verrons un peu plus loin le pourquoi de cette différence de taille.

Saisir le programme suivant :

hello3.c

  1. int main( )
  2. {
  3. printf("Hello world !\n");
  4. }

la commande suivante permet la saisie directe

cat > hello.c (taper CTRL C pour sortir de l'édition!)

Le compiler en tapant la commande suivante :

$gcc hello3.c -o hello3

Lancer la commande ls et constater la présence du fichier hello3.
Lancer le programme hello3, il doit vous afficher le message : "hello world !".
Traduire le fichier C hello3.c en langage d'assemblage en tapant la commande suivante :

$gcc -S hello3.c -o hello3.s

Comparer les deux fichiers hello1.s et hello3.s en les éditant.

Copier le fichier hello1.s dans le fichier hello4.s . Remplacer dans le fichier hello4.s puts par printf et \0 par \12\0. Réaliser l'exécutable, Lancer et conclure. Dans hello4.s, enlever \12, refaire l'exécutable, le relancer et constater.

Nous allons voir maintenant qu'il est possible d'obtenir un exécutable des deux programmes hello1 et hello2 en utilisant ld pour le premier et gcc pour le second.

Pour le fichier : hello1.s : Faire l'édition des liens de hello1 en tapant la commande suivante :

$ld -o hello1 hello1.o

Vous devez obtenir le message suivant :

ld: warning: cannot find entry symbol _start; defaulting to 08048074 (ou une adresse) hello1.O(.text+0x19): undefined reference to 'puts'

$ld -o hello1 /lib/libc.so.6 hello1.o -lc

Pour le fichier : hello2s :

Compiler le programme hello2.s en tapant la commande suivante :

$gcc hello2.s -o hello2

Vous devez obtenir le message suivant :

/usr/lib/crt1.o(.text+0x18): undefined reference to `main'

Explication : le problème, vient de ce que gcc cherche le point d'entrée main et ne le trouve. Par contre si vous lancez la commande suivante :

$gcc -S hello2.s -o hello2

Cela revient à faire en sorte que gcc ne s'occupe pas du point d'entrée lors de l'assemblage, puisqu'il ne fait pas l'édition des liens.

Modifier hello2.s en remplaçant _pointdentree par main et relancer gcc. A partir de là tout doit bien se passer.

Encore plus loin : DDD

Compiler le fichier hello.c avec l'option -g et lancer ddd.

$gcc -g -o hello hello.c & ddd ./hello

Visualiser le code assembleur. Pour une utilisation de ddd voir lien.