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.

Le cheminement et les explications sont disponibles dans cette vidéo.

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 :

  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 :

  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 :

  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.     gcc -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$ :

  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 :

  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$ :

  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 :

  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$ :

  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 :

  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, 4
  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