3. TP 3
Boucle for

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

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

3.1. for i

Traduire le programme suivant en assembleur 32 bits :

  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 :

  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 :

  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 :

  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 :

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

int tab[ 200 ];

t[ 10 ];
mov		esi, tab
mov		ecx, 10
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.