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.


3. TP 3
Boucle for

Dans ce TP, nous nous intéressons à la traduction de la boucle for.

3.1. for i

Traduire le programme suivant en assembleur 32 bits :

Afficher le code    assembly/programs/for_loop_sum.c
  1. // ===================================================================
  2. // Program: for_loop_sum.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 for loop 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. /**
  16.  * main function
  17.  *
  18.  * we compute the sum of i=1 to 10 = (11*10)/2 = 55
  19.  */
  20. int main(int argc, char *argv[]) {
  21.  
  22.   int sum = 0;
  23.  
  24.   for (int i = 1; i < 11; ++i) {
  25.     sum += i;
  26.   }
  27.  
  28.   printf("sum=%d\n", sum);
  29.  
  30.   return EXIT_SUCCESS;
  31. }
  32.  

Voici sa traduction :

Afficher le code    assembly/programs/for_loop_sum_nasm.asm
  1. ; ===================================================================
  2. ; Program: for_loop_sum_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 computes and prints the sum of integers from
  9. ;   1 to 10
  10. ; ===================================================================
  11. global main
  12. extern printf
  13.  
  14. ; ===================================================================
  15. ; #####     ##     #####    ##
  16. ; #    #   #  #      #     #  #
  17. ; #    #  #    #     #    #    #
  18. ; #    #  ######     #    ######
  19. ; #    #  #    #     #    #    #
  20. ; #####   #    #     #    #    #
  21. ; ===================================================================
  22. section .data
  23.  
  24.   msg_sum:  db "sum=%d", 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 computes sum of 1 to 10 and prints result
  45. ;
  46. ; PARAMETERS
  47. ;
  48. ; argc    int     number of arguments of the program
  49. ; argv    char *[]  array of arguments as strings
  50. ;
  51. ; RETURN VALUE
  52. ;
  53. ; 0   if everything is ok,
  54. ; >0  if error
  55. ;
  56. ; VARIABLES / REGISTERS
  57. ;
  58. ;   i   int   loop variable ecx
  59. ;   sum   int   sum of values eax
  60. ;
  61. ; -------------------------------------------------------------------
  62. main:
  63.   push  ebp
  64.   mov   ebp, esp
  65.  
  66.   ;
  67.   ; Code of subprogram
  68.   ;
  69.   xor   eax, eax    ; sum = 0
  70.  
  71.   mov   ecx, 1      ; i = 1
  72. .for_i:
  73.   cmp   ecx, 11
  74.   jge   .endfor_i
  75.  
  76.     add   eax, ecx  ; sum += i
  77.    
  78.   inc   ecx       ; ++i
  79.   jmp   .for_i
  80. .endfor_i: 
  81.  
  82.   push  eax
  83.   push  dword msg_sum
  84.   call  printf
  85.   add   esp, 8
  86.    
  87.   xor   eax, eax    ; 0 of return 0
  88.  
  89.   mov   esp, ebp
  90.   pop   ebp
  91.   ret
  92.  
  93.  

3.2. for avec tableau

On itère sur un tableau :

  • dans un premier temps le tableau est initialisé avec des valeurs aléatoires
  • on affiche les valeurs
  • puis on en fait la somme que l'on affiche
Afficher le code    assembly/programs/for_loop_array.c
  1. // ===================================================================
  2. // Program: for_loop_sum.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 for loop in C and iterate
  9. //   through an array.
  10. //   It is intended to be translated in 32 bits x86 assembly
  11. //   language.
  12. // ===================================================================
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <time.h>
  17.  
  18. // Size of the array
  19. const int MAX_ELEMENTS = 8;
  20. // Array of integers that needs to be allocated
  21. int *array;
  22.  
  23. /**
  24.  * Initialization with random numbers from 1 to 10
  25.  * @param a array of integer
  26.  * @param size size of the array
  27.  */
  28. void random_init(int *a, int size) {
  29.   for (int i = 0; i < size; ++i) {
  30.     a[i] = (rand() % 10) + 1;
  31.   }
  32. }
  33.  
  34. /**
  35.  * Print contents of the array
  36.  * @param a array of integer
  37.  * @param size size of the array
  38.  */
  39. void print_values(int *a, int size) {
  40.   for (int i = 0; i < size; ++i) {
  41.     printf("%d ", a[i]);
  42.   }
  43.   printf("\n");
  44. }
  45.  
  46. /**
  47.  * Sum of the values of the array
  48.  * @param a array of integer
  49.  * @param size size of the array
  50.  */
  51. int array_sum(int *a, int size) {
  52.   int sum = 0;
  53.   for (int i = 0; i < size; ++i) {
  54.     sum += a[i];
  55.   }
  56.   return sum;
  57. }
  58.  
  59. /**
  60.  * main method
  61.  */
  62. int main(int argc, char *argv[]) {
  63.   // initialize random number generator
  64.   srand( time(nullptr) );
  65.  
  66.   //  allocate array
  67.   array = new int [ MAX_ELEMENTS ];
  68.  
  69.   // initialize araray with random values
  70.   random_init( array, MAX_ELEMENTS );
  71.   // print contents of array
  72.   print_values( array, MAX_ELEMENTS );
  73.  
  74.   // compute and print sum of values of array
  75.   printf( "sum=%d\n", array_sum( array, MAX_ELEMENTS ) );
  76.  
  77.   // free resources
  78.   delete [] array;
  79.  
  80.   return EXIT_SUCCESS;
  81. }
  82.  

Dont la traduction en assembleur en 32 bits est :

Afficher le code    assembly/programs/for_loop_array_nasm.asm
  1. ; ===================================================================
  2. ; Program: for_loop_sum_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 creates an array of random values and computes
  9. ;   and prints the sum of the values
  10. ; ===================================================================
  11. global main
  12. extern printf, rand, srand, time, malloc, free
  13.  
  14. ; ===================================================================
  15. ; #####     ##     #####    ##
  16. ; #    #   #  #      #     #  #
  17. ; #    #  #    #     #    #    #
  18. ; #    #  ######     #    ######
  19. ; #    #  #    #     #    #    #
  20. ; #####   #    #     #    #    #
  21. ; ===================================================================
  22. section .data
  23.  
  24.   MAX_ELEMENTS  equ 8
  25.  
  26.   array:      dd 0  ; int *array
  27.  
  28.   msg_print_a_i:  db "%d ", 0
  29.   msg_sum:    db "sum=%d", 10, 0
  30.   new_line:   db 10, 0
  31.  
  32. ; ===================================================================
  33. ;  ####    ####   #####   ######
  34. ; #    #  #    #  #    #  #
  35. ; #       #    #  #    #  #####
  36. ; #       #    #  #    #  #
  37. ; #    #  #    #  #    #  #
  38. ;  ####    ####   #####   ######
  39. ; ===================================================================
  40. section .text
  41.  
  42. ; -------------------------------------------------------------------
  43. ; SUBPROGRAM
  44. ;
  45. ; void random_init(int *a, int size)
  46. ;
  47. ; DESCRIPTION
  48. ;
  49. ; initialize integer array 'a' of size 'size' with random values
  50. ; between 1 and 10
  51. ;
  52. ; PARAMETERS
  53. ;
  54. ; a   int * array of integers
  55. ; size  int   size of the array
  56. ;
  57. ; RETURN VALUE
  58. ;  
  59. ; none
  60. ;
  61. ; VARIABLES / REGISTERS
  62. ;
  63. ; a   int *   array of integers   [ebp +8]  ebx
  64. ; size  int     size of the array   [ebp+12]   
  65. ; i   int   for loop variable         esi
  66. ;   eax   int   return value of rand()
  67. ; ecx   int   constant = 10
  68. ;
  69. ; -------------------------------------------------------------------
  70. random_init:
  71.   push  ebp
  72.   mov   ebp, esp
  73.  
  74.   push  ebx
  75.   push  esi
  76.  
  77.   mov   ebx, [ebp + 8]
  78.  
  79.   ; for (int i = 0; i < size; ++i)
  80.   xor   esi, esi
  81. .for_i:
  82.   cmp   esi, [ebp + 12]
  83.   jge   .endfor_i
  84.  
  85.     ; a[i] = (rand() % 10) + 1;
  86.     call  rand
  87.     xor   edx, edx
  88.     mov   ecx, 10
  89.     div   ecx
  90.     add   edx, 1
  91.     mov   [ebx + esi * 4], edx
  92.  
  93.   inc   esi
  94.   jmp   .for_i
  95. .endfor_i: 
  96.  
  97.   pop   esi
  98.   pop   ebx
  99.  
  100.   mov   esp, ebp
  101.   pop   ebp
  102.   ret
  103.  
  104. ; -------------------------------------------------------------------
  105. ; SUBPROGRAM
  106. ;
  107. ; void print_values(int *a, int size)
  108. ;
  109. ; DESCRIPTION
  110. ;
  111. ; print values of array 'a' of size 'size'
  112. ;
  113. ; PARAMETERS
  114. ;
  115. ; a   int * array of integers  
  116. ; size  int   size of the array  
  117. ;
  118. ; RETURN VALUE
  119. ;  
  120. ; none
  121. ;
  122. ; VARIABLES / REGISTERS
  123. ;
  124. ; a   int *   array of integers   [ebp +8]  ebx
  125. ; size  int     size of the array   [ebp+12]   
  126. ; i   int   for loop variable         esi
  127. ;
  128. ; -------------------------------------------------------------------
  129. print_values:
  130.   push  ebp
  131.   mov   ebp, esp
  132.  
  133.   push  ebx
  134.   push  esi
  135.  
  136.   mov   ebx, [ebp + 8]
  137.  
  138.   ; for (int i = 0; i < size; ++i)
  139.   xor   esi, esi
  140. .for_i:
  141.   cmp   esi, [ebp + 12]
  142.   jge   .endfor_i
  143.  
  144.     ; printf("%d ", a[i]);
  145.     push  dword [ebx + esi * 4]
  146.     push  dword msg_print_a_i
  147.     call  printf
  148.     add   esp, 8
  149.      
  150.   inc   esi
  151.   jmp   .for_i
  152. .endfor_i: 
  153.  
  154.   ; printf("\n");
  155.   push  dword new_line
  156.   call  printf
  157.   add   esp, 4
  158.  
  159.   pop   esi
  160.   pop   ebx
  161.  
  162.   mov   esp, ebp
  163.   pop   ebp
  164.   ret
  165.  
  166.  
  167. ; -------------------------------------------------------------------
  168. ; SUBPROGRAM
  169. ;
  170. ; int array_sum(int *a, int size)
  171. ;
  172. ; DESCRIPTION
  173. ;
  174. ; compute sum of value of the array 'a' of size 'size'
  175. ;
  176. ; PARAMETERS
  177. ;
  178. ; a   int * array of integers   [ebp+8]   ebx
  179. ; size  int   size of the array   [ebp+12]  esi
  180. ;
  181. ; RETURN VALUE
  182. ;  
  183. ; the sum of a[0] + ... + a[size-1]
  184. ;
  185. ; VARIABLES / REGISTERS
  186. ;
  187. ; a   int *   array of integers   [ebp +8]  ebx
  188. ; size  int     size of the array   [ebp+12]   
  189. ; i   int   for loop variable         esi
  190. ;   sum   int   sum of a[i]'s           eax
  191. ;
  192. ; -------------------------------------------------------------------
  193. array_sum:
  194.   push  ebp
  195.   mov   ebp, esp
  196.  
  197.   push  ebx
  198.   push  esi
  199.  
  200.   mov   ebx, [ebp + 8]
  201.  
  202.   ; sum = 0
  203.   xor   eax, eax
  204.  
  205.   ; for (int i = 0; i < size; ++i)
  206.   xor   esi, esi
  207. .for_i:
  208.   cmp   esi, [ebp + 12]
  209.   jge   .endfor_i
  210.  
  211.     ; sum += a[i]
  212.     add   eax, [ebx + esi * 4]
  213.      
  214.   inc   esi
  215.   jmp   .for_i
  216. .endfor_i: 
  217.  
  218.   pop   esi
  219.   pop   ebx
  220.  
  221.   mov   esp, ebp
  222.   pop   ebp
  223.   ret
  224.  
  225. ; -------------------------------------------------------------------
  226. ; SUBPROGRAM
  227. ;
  228. ; int main(int argc, char *argv[])
  229. ;
  230. ; DESCRIPTION
  231. ;
  232. ; Main subprogram that computes sum of 1 to 10 and prints result
  233. ;
  234. ; PARAMETERS
  235. ;
  236. ; argc    int     number of arguments of the program
  237. ; argv    char *[]  array of arguments as strings
  238. ;
  239. ; RETURN VALUE
  240. ;
  241. ; 0   if everything is ok,
  242. ; >0  if error
  243. ;
  244. ; VARIABLES / REGISTERS
  245. ;  
  246. ; argc  int     number of commandl line   [ebp + 8]
  247. ;           arguments
  248. ; argv  char *[]  command line arguments    [ebp + 12] 
  249. ;
  250. ; -------------------------------------------------------------------
  251. main:
  252.   push  ebp
  253.   mov   ebp, esp
  254.  
  255.   ; srand( time(nullptr) );
  256.   xor   eax, eax
  257.   push  eax
  258.   call  time
  259.   add   esp, 4
  260.   push  eax
  261.   call  srand
  262.   add   esp, 4
  263.  
  264.   ; array = new int [ MAX_ELEMENTS ];
  265.   ; array = (int *) malloc( MAX_ELEMENTS * sizeof(int) );
  266.   mov   eax, MAX_ELEMENTS
  267.   shl   eax, 2
  268.   push  eax
  269.   call  malloc
  270.   add   esp, 4
  271.   mov   [array], eax
  272.  
  273.   ; random_init( array, MAX_ELEMENTS );
  274.   push  dword MAX_ELEMENTS
  275.   push  dword [array]
  276.   call  random_init
  277.   add   esp, 8
  278.    
  279.   ; print_values( array, MAX_ELEMENTS );
  280.   push  dword MAX_ELEMENTS
  281.   push  dword [array]
  282.   call  print_values
  283.   add   esp, 8
  284.  
  285.   ; printf( "sum=%d\n", array_sum( array, MAX_ELEMENTS ) );
  286.   push  dword MAX_ELEMENTS
  287.   push  dword [array]
  288.   call  array_sum
  289.   add   esp, 8
  290.  
  291.   push  eax
  292.   push  dword msg_sum
  293.   call  printf
  294.   add   esp, 8
  295.  
  296.   ; delete [] array
  297.   push  dword [array]
  298.   call  free
  299.   add   esp, 4
  300.  
  301.   ; return 0
  302.   xor   eax, eax    ; 0 of return 0
  303.  
  304.   mov   esp, ebp
  305.   pop   ebp
  306.   ret
  307.  
  308.  

3.3. Que retenir

3.3.1. Manipulation des tableaux

Pour manipuler les éléments d'un tableau d'octets, d'entiers, de flottants a[i], on peut procéder en utilisant deux registres :

  • un registre pour stocker l'adresse du tableau
  • un registre pour stocker l'indice du tableau

Il faudra alors multiplier l'indice par un facteur qui dépend du type du tableau :

  • pour un tableau char : 1
  • pour un tableau int ou float : 4
  • pour un tableau double : 8
Afficher le code
  1. int tab[ 200 ];
  2. t[ 10 ];
Afficher le code
  1. mov   esi, tab
  2. mov   ecx, 10
  3. mov   eax, [ esi + ecx * 4 ]

3.3.2. Registres préservés

Si on utilise le registre ecx en tant qu'indicie de boucle et qu'à l'intérieur de la boucle on appelle une fonction standard de la bibliothèque C, ecx risque d'être modifié ce qui peut avoir deux conséquences : soit terminer la boucle, soit la rendre infinie.

Seuls les registres ebp,ebx, edi, esi sont préservés.