Site de Jean-Michel RICHER

Maître de Conférences en Informatique à l'Université d'Angers

Ce site est en cours de reconstruction certains liens peuvent ne pas fonctionner ou certaines images peuvent ne pas s'afficher.


2. TP 2
Squelette de programme

Dans ce TP nous allons créer un squelette de programme et nous intéresser, par la suite, à la traduction d'un if then else.

Commencez par créer un sous-répertoire qui contiendra l'ensemble des codes sources et appelez le par exemple assembleur.

2.1. Squelette de programme

Nous allons traduire le programme suivant, le fameux Hello World :

Afficher le code    assembly/programs/hello_world.c
  1. // ===================================================================
  2. // Program: hello_world.c
  3. // Date: July 2020
  4. // Author: Jean-Michel Richer
  5. // Email: jean-michel.richer@univ-angers.fr
  6. // ===================================================================
  7. // Description:
  8. //   This program is the classical 'Hello World" program.
  9. //
  10. //   It is intended to be translated in 32 bits x86 assembly
  11. //   language.
  12. // ===================================================================
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15.  
  16. /**
  17.  * main function
  18.  */
  19. int main(int argc, char *argv[]) {
  20.  
  21.   printf("Hello World!");
  22.  
  23.   return EXIT_SUCCESS;
  24. }
  25.  

Le code correspondant en nasm est le suivant :

Afficher le code    assembly/programs/hello_world_nasm.asm
  1. ; ===================================================================
  2. ; Program: hello_word_nasm.asm
  3. ; Date: July 2020
  4. ; Author: Jean-Michel Richer
  5. ; Email: jean-michel.richer@univ-angers.fr
  6. ; ===================================================================
  7. ; Description:
  8. ;   This program is an assembly translation of the C Hello World
  9. ; program.
  10. ; ===================================================================
  11. global main
  12. extern printf
  13.  
  14. ; ===================================================================
  15. ; #####     ##     #####    ##
  16. ; #    #   #  #      #     #  #
  17. ; #    #  #    #     #    #    #
  18. ; #    #  ######     #    ######
  19. ; #    #  #    #     #    #    #
  20. ; #####   #    #     #    #    #
  21. ; ===================================================================
  22. section .data
  23.  
  24.   message:  db "Hello World!", 10, 0
  25.  
  26.  
  27. ; ===================================================================
  28. ;  ####    ####   #####   ######
  29. ; #    #  #    #  #    #  #
  30. ; #       #    #  #    #  #####
  31. ; #       #    #  #    #  #
  32. ; #    #  #    #  #    #  #
  33. ;  ####    ####   #####   ######
  34. ; ===================================================================
  35. section .text
  36.  
  37. ; -------------------------------------------------------------------
  38. ; SUBPROGRAM
  39. ;
  40. ; int main(int argc, char *argv[])
  41. ;
  42. ; DESCRIPTION
  43. ;
  44. ; Main subprogram that prints the string 'message' on standard
  45. ; output
  46. ;
  47. ; PARAMETERS
  48. ;
  49. ; argc    int     number of arguments of the program
  50. ; argv    char *[]  array of arguments as strings
  51. ;
  52. ; RETURN VALUE
  53. ;
  54. ; 0   if everything is ok,
  55. ; >0  if error
  56. ;
  57. ; -------------------------------------------------------------------
  58. main:
  59.   push  ebp
  60.   mov   ebp, esp
  61.  
  62.   ;
  63.   ; Code of subprogram
  64.   ;
  65.   push  dword message
  66.   call  printf
  67.   add   esp, 4
  68.  
  69.   xor   eax, eax    ; 0 of return 0
  70.  
  71.   mov   esp, ebp
  72.   pop   ebp
  73.   ret
  74.  
  75.  

La compilation et la génération de l'exécutable en architecture 32 bits (sous un système 64 bits) sont réalisées grâce aux commandes suivantes :

richer@zentopia:\$nasm -f elf hello_world_nasm.asm
richer@zentopia:\$g++ -o hello_world_nasm.exe hello_world_nasm.o -m32

Attention : sous les dernières versions de Debian ou Ubuntu, il est parfois nécessaire d'ajouter un flag supplémentaire à gcc/g++ lors de la compilation : -no-pie. Vous devez donc compiler avec :

richer@zentopia:\$g++ -o hello_world_nasm.exe hello_world_nasm.o -m32 -no-pie

2.2. Automatisation de la compilation

Etant donné que nous aurons plusieurs programmes à compiler nous allons créer un makefile afin d'automatiser la compilation des programmes assembleur :

Vous pouvez récupérer le fichier suivant et l'enregistrer sous le nom makefile :

Afficher le code    assembly/programs/makefile.example
  1. # ===================================================================
  2. # Makefile for assembly programming
  3. # ===================================================================
  4. NASM_FLAGS= -f elf -g -F dwarf
  5. CXX_FLAGS= -Wall -m32 -ggdb
  6. OPT_FLAGS= -m32 -ggdb -O3 -mavx2 -ftree-vectorize -funroll-loops
  7.  
  8. .PRECIOUS: obj/%.o
  9. .SECONDARY: obj/%.o
  10.  
  11. all: setup_directories \
  12.   bin/hello_world.exe bin/hello_world_nasm.exe
  13.  
  14. setup_directories:
  15.   mkdir -p bin obj
  16.  
  17. # rules
  18. bin/%.exe: obj/%.o
  19.   g++ -o $@ $< $(OPT_FLAGS)
  20.  
  21. obj/%.o: %.asm
  22.   nasm $(NASM_FLAGS) $< -o $@
  23.  
  24. obj/%.o: %.c
  25.   gcc -c -o $@ $< $(OPT_FLAGS) $(CXX_FLAGS)
  26.  
  27. obj/%.o: %.cpp
  28.   g++ -c -o $@ $< $(OPT_FLAGS) $(CXX_FLAGS)
  29.  
  30. # clean
  31. clean:
  32.   rm -rf bin/*.exe obj/*.o
  33.  
  34.  
  35.  

2.3. If then else

2.3.1. Version basique

Traduire le programme suivant en assembleur 32 bits. On dispose de deux valeurs entières $a$ et $b$ et on veut afficher un message qui indique si $a$ est inférieur à $b$ ou si $a$ est supérieur ou égal à $b$ :

Afficher le code    assembly/programs/if_then_else_v1.c
  1. // ===================================================================
  2. // Program: if_then_else_v1.c
  3. // Date: July 2020
  4. // Author: Jean-Michel Richer
  5. // Email: jean-michel.richer@univ-angers.fr
  6. // ===================================================================
  7. // Description:
  8. //   This program shows how to code a if then else statement in C.
  9. //   It is intended to be translated in 32 bits x86 assembly
  10. //   language.
  11. // ===================================================================
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14.  
  15. // global integer variables
  16. int a = 1;
  17. int b = 2;
  18.  
  19. /**
  20.  * main function
  21.  */
  22. int main(int argc, char *argv[]) {
  23.  
  24.   // compare 'a' to 'b' and print message
  25.   if (a < b) {
  26.     printf("a < b\n");
  27.   } else {
  28.     printf("a >= b\n");
  29.   }
  30.  
  31.   return EXIT_SUCCESS;
  32. }
  33.  

Voici la traduction :

Afficher le code    assembly/programs/if_then_else_v1_nasm.asm
  1. ; ===================================================================
  2. ; Program: if_then_else_v1_nasm.asm
  3. ; Date: July 2020
  4. ; Author: Jean-Michel Richer
  5. ; Email: jean-michel.richer@univ-angers.fr
  6. ; ===================================================================
  7. ; Description:
  8. ;   This program shows how to code a if-then-else statement
  9. ;
  10. ; ===================================================================
  11. global main
  12. extern printf
  13.  
  14. ; ===================================================================
  15. ; #####     ##     #####    ##
  16. ; #    #   #  #      #     #  #
  17. ; #    #  #    #     #    #    #
  18. ; #    #  ######     #    ######
  19. ; #    #  #    #     #    #    #
  20. ; #####   #    #     #    #    #
  21. ; ===================================================================
  22. section .data
  23.  
  24.   a:      dd  1
  25.   b:      dd  2
  26.   msg_inf:  db "a < b", 10, 0
  27.   msg_supe: db "a >= b", 10, 0 
  28.  
  29. ; ===================================================================
  30. ;  ####    ####   #####   ######
  31. ; #    #  #    #  #    #  #
  32. ; #       #    #  #    #  #####
  33. ; #       #    #  #    #  #
  34. ; #    #  #    #  #    #  #
  35. ;  ####    ####   #####   ######
  36. ; ===================================================================
  37. section .text
  38.  
  39. ; -------------------------------------------------------------------
  40. ; SUBPROGRAM
  41. ;
  42. ; int main(int argc, char *argv[])
  43. ;
  44. ; DESCRIPTION
  45. ;
  46. ; Main subprogram that compares variables 'a' and 'b'
  47. ;
  48. ; PARAMETERS
  49. ;
  50. ; argc    int     number of arguments of the program
  51. ; argv    char *[]  array of arguments as strings
  52. ;
  53. ; RETURN VALUE
  54. ;
  55. ; 0   if everything is ok,
  56. ; >0  if error
  57. ;
  58. ; VARIABLES / REGISTERS
  59. ;
  60. ; a   int   first operand   eax
  61. ; b   int   second operand    ebx
  62. ;
  63. ; -------------------------------------------------------------------
  64. main:
  65.   push  ebp
  66.   mov   ebp, esp
  67.  
  68.   push  ebx
  69.  
  70.   mov   eax, [a]
  71.   mov   ebx, [b]
  72.  
  73. .if: 
  74.   cmp   eax, ebx
  75.   jge   .else
  76. .then: 
  77.   push  dword msg_inf
  78.   call  printf
  79.   add   esp, 4
  80.   jmp   .endif
  81. .else: 
  82.   push  dword msg_supe
  83.   call  printf
  84.   add   esp, 4
  85. .endif:
  86.  
  87.   pop   ebx
  88.  
  89.   xor   eax, eax    ; 0 of return 0
  90.  
  91.   mov   esp, ebp
  92.   pop   ebp
  93.   ret
  94.  
  95.  

2.3.2. Version avec affichage des valeurs

On reprend le programme précédent mais en affichant les valeurs de $a$ et $b$ :

Afficher le code    assembly/programs/if_then_else_v2.c
  1. // ===================================================================
  2. // Program: if_then_else_v2.c
  3. // Date: July 2020
  4. // Author: Jean-Michel Richer
  5. // Email: jean-michel.richer@univ-angers.fr
  6. // ===================================================================
  7. // Description:
  8. //   This program shows how to code a if-then-else statement in C
  9. //   and print the values of 'a' and 'b'.
  10. //   It is intended to be translated in 32 bits x86 assembly
  11. //   language.
  12. // ===================================================================
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15.  
  16. // global integer variables
  17. int a = 1;
  18. int b = 2;
  19.  
  20. /**
  21.  * main function
  22.  */
  23. int main(int argc, char *argv[]) {
  24.  
  25.   if (a < b) {
  26.     printf("%d < %d\n", a, b);
  27.   } else {
  28.     printf("%d >= %d\n", a, b);
  29.   }
  30.  
  31.   return EXIT_SUCCESS;
  32. }
  33.  

Dont la traduction en assembleur en 32 bits est :

Afficher le code    assembly/programs/if_then_else_v2_nasm.asm
  1. ; ===================================================================
  2. ; Program: if_then_else_v2_nasm.asm
  3. ; Date: July 2020
  4. ; Author: Jean-Michel Richer
  5. ; Email: jean-michel.richer@univ-angers.fr
  6. ; ===================================================================
  7. ; Description:
  8. ;   This program shows how to code a if then else statement.
  9. ;   This second version prints the values of variables 'a' and 'b'
  10. ; ===================================================================
  11. global main
  12. extern printf
  13.  
  14. ; ===================================================================
  15. ; #####     ##     #####    ##
  16. ; #    #   #  #      #     #  #
  17. ; #    #  #    #     #    #    #
  18. ; #    #  ######     #    ######
  19. ; #    #  #    #     #    #    #
  20. ; #####   #    #     #    #    #
  21. ; ===================================================================
  22. section .data
  23.  
  24.   a:      dd  1
  25.   b:      dd  2
  26.   msg_inf:  db "%d < %d", 10, 0
  27.   msg_supe: db "%d >= %d", 10, 0 
  28.  
  29. ; ===================================================================
  30. ;  ####    ####   #####   ######
  31. ; #    #  #    #  #    #  #
  32. ; #       #    #  #    #  #####
  33. ; #       #    #  #    #  #
  34. ; #    #  #    #  #    #  #
  35. ;  ####    ####   #####   ######
  36. ; ===================================================================
  37. section .text
  38.  
  39. ; -------------------------------------------------------------------
  40. ; SUBPROGRAM
  41. ;
  42. ; int main(int argc, char *argv[])
  43. ;
  44. ; DESCRIPTION
  45. ;
  46. ; Main subprogram that compares variables 'a' and 'b'
  47. ;
  48. ; PARAMETERS
  49. ;
  50. ; argc    int     number of arguments of the program
  51. ; argv    char *[]  array of arguments as strings
  52. ;
  53. ; RETURN VALUE
  54. ;
  55. ; 0   if everything is ok,
  56. ; >0  if error
  57. ;
  58. ; VARIABLES / REGISTERS
  59. ;
  60. ; a   int   first operand   eax
  61. ; b   int   second operand    ebx
  62. ;
  63. ; -------------------------------------------------------------------
  64. main:
  65.   push  ebp
  66.   mov   ebp, esp
  67.  
  68.   push  ebx
  69.  
  70.   mov   eax, [a]
  71.   mov   ebx, [b]
  72.  
  73. .if: 
  74.   cmp   eax, ebx
  75.   jge   .else
  76. .then: 
  77.   push  ebx
  78.   push  eax
  79.   push  dword msg_inf
  80.   call  printf
  81.   add   esp, 12
  82.   jmp   .endif
  83. .else: 
  84.   push  dword [b]     ; equivalent to push ebx
  85.   push  dword [a]     ; equivalent to push eax
  86.   push  dword msg_supe
  87.   call  printf
  88.   add   esp, 12
  89. .endif:
  90.  
  91.   pop   ebx
  92.  
  93.   xor   eax, eax    ; 0 of return 0
  94.  
  95.   mov   esp, ebp
  96.   pop   ebp
  97.   ret
  98.  
  99.  

2.3.3. Version avec saisie et affichage des valeurs

Traduire le programme suivant qui demande à l'utilisateur de saisir les valeurs des variables entières $a$ et $b$ et affiche un message en fonction du fait que $a < b$ :

Afficher le code    assembly/programs/if_then_else_v3.c
  1. // ===================================================================
  2. // Program: if_then_else_v3.c
  3. // Date: July 2020
  4. // Author: Jean-Michel Richer
  5. // Email: jean-michel.richer@univ-angers.fr
  6. // ===================================================================
  7. // Description:
  8. //   This program shows how to code a if-then-else statement in C.
  9. //   and print the values of 'a' and 'b'. First, the user is asked
  10. //   to provide the values of 'a' and 'b'.
  11. //   It is intended to be translated in 32 bits x86 assembly
  12. //   language.
  13. // ===================================================================
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16.  
  17. // global integer variables
  18. int a = 0;
  19. int b = 0;
  20.  
  21. /**
  22.  * main function
  23.  */
  24. int main(int argc, char *argv[]) {
  25.  
  26.   printf("a, b ? ");
  27.   scanf("%d%d", &a, &b);
  28.  
  29.   if (a < b) {
  30.     printf("%d < %d\n", a, b);
  31.   } else {
  32.     printf("%d >= %d\n", a, b);
  33.   }
  34.  
  35.   return EXIT_SUCCESS;
  36. }
  37.  

Dont la traduction en assembleur en 32 bits est :

Afficher le code    assembly/programs/if_then_else_v3_nasm.asm
  1. ; ===================================================================
  2. ; Program: if_then_else_v3_nasm.asm
  3. ; Date: July 2020
  4. ; Author: Jean-Michel Richer
  5. ; Email: jean-michel.richer@univ-angers.fr
  6. ; ===================================================================
  7. ; Description:
  8. ;   This program shows how to code a if then else statement.
  9. ;   This third version asks the values of 'a' and 'b' and
  10. ;   then prints them
  11. ; ===================================================================
  12. global main
  13. extern printf
  14. extern scanf
  15.  
  16. ; ===================================================================
  17. ; #####     ##     #####    ##
  18. ; #    #   #  #      #     #  #
  19. ; #    #  #    #     #    #    #
  20. ; #    #  ######     #    ######
  21. ; #    #  #    #     #    #    #
  22. ; #####   #    #     #    #    #
  23. ; ===================================================================
  24. section .data
  25.  
  26.   a:      dd  1
  27.   b:      dd  2
  28.   msg_inf:  db "%d < %d", 10, 0
  29.   msg_supe: db "%d >= %d", 10, 0
  30.   msg_ask:  db "a, b ? ", 0
  31.   msg_scanf:  db "%d%d", 0
  32.  
  33. ; ===================================================================
  34. ;  ####    ####   #####   ######
  35. ; #    #  #    #  #    #  #
  36. ; #       #    #  #    #  #####
  37. ; #       #    #  #    #  #
  38. ; #    #  #    #  #    #  #
  39. ;  ####    ####   #####   ######
  40. ; ===================================================================
  41. section .text
  42.  
  43. ; -------------------------------------------------------------------
  44. ; SUBPROGRAM
  45. ;
  46. ; int main(int argc, char *argv[])
  47. ;
  48. ; DESCRIPTION
  49. ;
  50. ; Main subprogram that compares variables 'a' and 'b'
  51. ;
  52. ; PARAMETERS
  53. ;
  54. ; argc    int     number of arguments of the program
  55. ; argv    char *[]  array of arguments as strings
  56. ;
  57. ; RETURN VALUE
  58. ;
  59. ; 0   if everything is ok,
  60. ; >0  if error
  61. ;
  62. ; VARIABLES / REGISTERS
  63. ;
  64. ; a   int   first operand   eax
  65. ; b   int   second operand    ebx
  66. ;
  67. ; -------------------------------------------------------------------
  68. main:
  69.   push  ebp
  70.   mov   ebp, esp
  71.  
  72.   push  dword msg_ask
  73.   call  printf
  74.   add   esp, 4
  75.  
  76.   push  dword b
  77.   push  dword a
  78.   push  dword msg_scanf
  79.   call  scanf
  80.   add   esp, 12
  81.  
  82.   push  ebx
  83.  
  84.   mov   eax, [a]
  85.   mov   ebx, [b]
  86.  
  87. .if: 
  88.   cmp   eax, ebx
  89.   jge   .else
  90. .then: 
  91.   push  ebx
  92.   push  eax
  93.   push  dword msg_inf
  94.   call  printf
  95.   add   esp, 12
  96.   jmp   .endif
  97. .else: 
  98.   push  dword [b]     ; equivalent to push ebx
  99.   push  dword [a]     ; equivalent to push eax
  100.   push  dword msg_supe
  101.   call  printf
  102.   add   esp, 12
  103. .endif:
  104.  
  105.   pop   ebx
  106.  
  107.   xor   eax, eax    ; 0 of return 0
  108.  
  109.   mov   esp, ebp
  110.   pop   ebp
  111.   ret
  112.  
  113.  

2.4. Que retenir

Dans le cas d'un if avec une seule condition, on utilise la négation de la condition pour faire le saut conditionnel au niveau du label .endif ou du .else.

 Exemple   Saut Compl.   Description 
 x < y   jge   Jump Greater or Equal 
 x <= y   jg   Jump Greater 
 x > y   jle   Jump Less or Equal 
 x >= y   jl   Jump Less 
 x == y   jne   Jump Not Equal 
 x != y   je   Jump Equal 
Saut conditionnel complémentaire