TP 1 de programmation en assembleur i386 avec NASM sous Linux

Présentation
Les programmes en assembleur des TP seront compilés avec NASM en 32 bits, ils utiliseront donc exclusivement la syntaxe Intel x86 avec les registres 32 bits (EAX, EBX,...) et les instructions compatibles. Un programme assembleur présent dans un fichier éditable nommé programme.asm sera ainsi compilé en deux étapes avec les options correspondant à ce choix :
  nasm -f elf programme.asm (création d'un fichier intermédiaire programme.o)
  ld -m elf_i386 -o exec.elf programme.o (création de l'exécutable exec.elf)
Pour des précisions techniques, consulter autant que de besoin la Foire Aux Questions et le site web de NASM. Les programmes présentés ont été testés sous Debian 2.6 sur machine AMD64.
Un soin particulier devra être apporté à la rédaction et à la mise en page des programmes que vous concevrez, afin d'en faciliter la lecture et la réutilisation.


Exercice 1   (section, global, mov, int 80h)
1. Saisir le programme ci-dessous dans un fichier bonjour1.asm puis compiler pour obtenir un exécutable bonjour1.elf et le lancer dans un terminal (commande : ./bonjour1.elf).
Que fait ce programme ?
lignes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
; PROGRAMME 1
section .data
  message : db 'bonjour',10
  t_message : equ $-message
section .text
global _start
_start :
  mov eax, 4
  mov ebx, 1
  mov ecx, message
  mov edx, t_message
  int 80h
  ; ---
mov eax, 1
mov ebx, 0
int 80h
2. Enlever les trois derniers caractères de la ligne 2 et recompiler. Que se passe-t-il à l'exécution ? Pourquoi ?
Revenir pour la suite à la version initiale du programme.
3. Dans la ligne 3, remplacer equ $-message par equ 8 et vérifier que l'exécution est identique. Supprimer ensuite la ligne 3 et dans la ligne 10 remplacer t_message par 8 ; vérifier que l'exécution est identique.
Que se passe-t-il si on remplace ensuite dans la ligne 10 la valeur 8 par 7 ? par 4 ? par 15 ? En déduire les rôles de $-message et equ.
4. Trouver deux manières différentes de modifier le programme afin qu'il affiche deux lignes de message : "Bonjour" puis "chez vous !".
5. Vous pourrez créer un dictionnaire d'instructions pour NASM, y placer les mots-clés : db, equ, mov, eax et le symbole $  avec leur définition précise et concise. Dans ce dictionnaire, vous indiquerez aussi le rôle des différentes sections et leur caractère obligatoire ou facultatif. En complétant ce document au fil des TP avec les nouvelles instructions apprises, vous pourrez disposer d'un aide-mémoire précis.

Exercice 2   (db, equ, $-)
1. Dans les programmes ci-dessous, pourquoi est-il inutile d'ajouter une instruction  t_message1 : equ $-message1 ?  Quels sont les avantages et inconvénients de cette manière de procéder ?
2. Comment expliquer les différences de comportement de ces trois programmes ?
; PROGRAMME 2.1
section .data
  message1 : db 'ici '
  message2 : db 'ou la-bas',10
  t_message2 : equ $-message2
section .text
global _start
_start :
  mov eax, 4
  mov ebx, 1
  mov ecx, message1
  mov edx, 4
  int 80h
  ; ---
  mov eax, 4
  mov ebx, 1
  mov ecx, message2
  mov edx, t_message2
  int 80h
  ; ---
mov eax, 1
mov ebx, 0
int 80h
; PROGRAMME 2.2
section .data
  message1 : db 'ici '
  message2 : db 'ou la-bas',10
  t_message2 : equ $-message2
section .text
global _start
_start :
  mov eax, 4
  mov ebx, 1
  mov ecx, message1
  mov edx, 4
  int 80h
  mov eax, 1
  mov ebx, 0
  int 80h
  ; ---
  mov eax, 4
  mov ebx, 1
  mov ecx, message2
  mov edx, t_message2
  int 80h
  ; ---
mov eax, 1
mov ebx, 0
int 80h
; PROGRAMME 2.3
section .data
  message1 : db 'ici '
  message2 : db 'ou la-bas',10
  t_message2 : equ $-message2
section .text
global _start
_start :
  mov eax, 4
  mov ebx, 1
  mov ecx, message1
  mov edx, 4
  int 80h
  ; ---
  mov ecx, message2
  mov edx, t_message2
  int 80h
  ; ---
mov eax, 1
mov ebx, 0
int 80h

Exercice 3   (jmp, call, ret)
1. Faire tourner le programme 3.1 et saisir une chaine de cinq caractères.
Que se passe-t-il si la taille de la chaine de caractère saisie est quatre ? inférieure à quatre ? supérieure à cinq ?
; PROGRAMME 3.1
section .bss
  chaine : resb 5
  t_chaine : equ $-chaine
section .text
global _start
_start :
  mov eax, 3
  mov ebx, 0
  mov ecx, chaine
  mov edx, t_chaine
  int 80h
  ; ---
  mov eax, 4
  mov ebx, 1
  mov ecx, chaine
  mov edx, t_chaine
  int 80h
  ; ---
mov eax, 1
mov ebx, 0
int 80h
; PROGRAMME 3.2
section .bss
  chaine : resb 5
  t_chaine : equ $-chaine
section .text
global _start
_start :
  jmp _Entree
_EE :
  jmp _Sortie
_SS :
  jmp _Fin
_Entree :
  mov eax, 3
  mov ebx, 0
  mov ecx, chaine
  mov edx, t_chaine
  int 80h
  jmp _EE
_Sortie :
  mov eax, 4
  mov ebx, 1
  mov ecx, chaine
  mov edx, t_chaine
  int 80h
  jmp _SS
_Fin :
mov eax, 1
mov ebx, 0
int 80h
; PROGRAMME 3.3
section .bss
  chaine : resb 5
  t_chaine : equ $-chaine
section .text
global _start
_start :
  call _Entree
  call _Sortie
  jmp _Fin
_Entree :
  mov eax, 3
  mov ebx, 0
  mov ecx, chaine
  mov edx, t_chaine
  int 80h
  ret
_Sortie :
  mov eax, 4
  mov ebx, 1
  mov ecx, chaine
  mov edx, t_chaine
  int 80h
  ret
_Fin :
mov eax, 1
mov ebx, 0
int 80h
; PROGRAMME 3.4
section .bss
  chaine : resb 5
  t_chaine : equ $-chaine
section .text
global _start
_start :
  call _Entree
  call _Sortie
  jmp _Fin
_Fin :
  mov eax, 1
  mov ebx, 0
  int 80h
_Entree :
  mov eax, 3
  mov ebx, 0
  mov ecx, chaine
  mov edx, t_chaine
  int 80h
  ret
_Sortie :
  mov eax, 4
  mov ebx, 1
  mov ecx, chaine
  mov edx, t_chaine
  int 80h
  ret
2. Vérifier qu'il n'y a aucune différence de comportement entre les programmes 3.1, 3.2, 3.3 et 3.4.
Quel est l'inconvénient du programme 3.2 ? l'avantage du programme 3.3 ?
3. Supprimer les instructions ret des programmes 3.3 et 3.4. Pourquoi le programme 3.3 est-il préférable au programme 3.4 ?
4. Créer un programme qui saisit un caractère et l'affiche.
5. Si on voulait créer un programme qui place un chiffre dans un registre et l'affiche, quelle pourrait être la difficulté ?
6. Sur le modèle du programme 3.3, créer un programme qui saisit une chaine de caractère et l'affiche, puis recommence une fois.

Exercice 4   (resb, push, pop, cmp, jbe, dec)
1. Comment expliquer l'affichage produit par le programme 4.1 ?
2. Comment expliquer l'affichage produit par le programme 4.2 quand l'utilisateur saisit des chaines de caractères de longueurs différentes ?
3. Pour chacun de ces deux programmes, réaliser un programme équivalent en C, avec l'instruction de choix multiple (switch).
N.B. Cette question vérifie notamment la bonne compréhension des instructions conjointes cmp et jbe. On pourra ajouter les instructions de comparaisons au dictionnaire assembleur créé.
; PROGRAMME 4.1
section .data
  sans : db 'sans ! '
  t_sans : equ $-sans
  avec : db 'avec ! '
  t_avec : equ $-avec
  fin : db 10,'fin',10
  t_fin : equ $-fin
section .text
global _start
_start :
  call _Sans
  call _Avec
  call _Suite
  jmp _Fin
_Avec :
  mov eax, 4
  mov ebx, 1
  mov ecx, avec
  mov edx, t_avec
  int 80h
_Sans :
  mov eax, 4
  mov ebx, 1
  mov ecx, sans
  mov edx, t_sans
  int 80h
  ret
_Suite :
  mov eax, 4
  mov ebx, 1
  mov ecx, fin
  mov edx, t_fin
  int 80h
  ret
_Fin :
mov eax, 1
mov ebx, 0
int 80h
; PROGRAMME 4.2
section .bss
  chaine : resb 9
  t_chaine : equ $-chaine
section .data
  nl : db 10
section .text
global _start
_start :
  mov eax, 3
  mov ebx, 0
  mov ecx, chaine
  mov edx, t_chaine
  int 80h
  mov ecx, chaine
  mov edx, t_chaine
_debut :
  cmp edx, 0
  jbe _fin
  push edx
  call _allez
  push ecx
  call _etpuis
  pop ecx
  pop edx
  dec edx
  inc ecx
  jmp _debut
_allez :
  mov eax, 4
  mov ebx, 1
  mov edx, 1
  int 80h
  ret
_etpuis :
  mov eax, 4
  mov ebx, 1
  mov ecx, nl
  mov edx, 1
  int 80h
  ret
_fin:
mov eax, 1
mov ebx, 0
int 80h
4. Créer un programme qui saisit un chiffre et l'affiche, puis recommence tant que le caractère saisi est un chiffre.

Exercice 5.   (jae)
1. Que fait le programme ci-dessous ? Pourquoi l'instruction  "push ecx"  est-elle indispensable ?
2. Ecrire l'algorithme correspondant à ce programme, puis structurer le programme en faisant appel (call) à des fonctions : _EcrireTexte, _EcrireLigne, etc.
; PROGRAMME 5
section .data
N : equ 5
char : db '#'
nl : db 10
section .txt
global _start
_start :
mov ecx, 0
debut :
  cmp ecx, N
  jae fini
  push ecx
   mov eax, 4
   mov ebx, 1
   mov ecx, char
   mov edx, 1
   int 80h
  pop ecx
  inc ecx
  jmp debut
fini :
   mov eax, 4
   mov ebx, 1
   mov ecx, nl
   mov edx, 1
   int 80h
mov eax, 1
mov ebx, 0
int 80h
3. Modifier enfin le programme structuré afin que le nombre N de répétition soit saisi par l'utilisateur et compris entre 0 et 9.
4. Créer un programme assembleur structuré qui affiche un rectangle de longueur n et de hauteur p dont les bords sont constitués du caractère '#' et l'intérieur est rempli de caractères '-', les valeurs n et p étant comprises entre 1 et 10 (10 ?!).
N.B. il n'est pas inutile d'écrire d'abord l'algorithme correspondant.
→ Pour cette question, un essai de fonctionnement pourra être demandé.

Exercice 6
1. En assembleur, dans quelle mesure les notions suivantes ont-elles un sens :
  – constante et variable,
  – typage des données,
  – fonction et/ou procédure.
2. Intégrer ces réponses dans le dictionnaire assembleur en liaison avec les mots-clés associés.
© 2011-2016 – A. Guitton & A. Sigayret – 2016-09-21