Langage d'assemblage - Tableaux

Un tableau est une collection de données du même type stockées de manière contiguë. En assembleur, un tableau est un bloc contigu de mémoire, et on accède à chaque élément à l'aide d'une adresse de base plus un décalage.


Définition d'un tableau unidimensionnel

Exemple

; Manières de définir un tableau

section .data
    ; Méthode 1 : Lister les éléments un par un
    arr1 dd 10, 20, 30, 40, 50  ; Un tableau de 5 éléments de type double mot

    ; Méthode 2 : Initialiser avec dup
    arr2 dd 10 dup(0)            ; 10 double mots, tous à 0

    ; Méthode 3 : Tableau d'octets
    bytes db 1, 2, 3, 4, 5, 6   ; 6 bytes

    ; Méthode 4 : tableau de caractères (chaîne)
    chars db 'example', 0         ; 7 bytes

    ; Calcul de la longueur du tableau (au moment de la compilation)
    arr1_len equ ($ - arr1) / 4  ; Nombre d'éléments dans un tableau de doubles mots
    arr2_len equ ($ - arr2) / 4
    bytes_len equ ($ - bytes)    ; Tableau d'octets, aucune division nécessaire

section .bss
    ; Tableau non initialisé
    buffer resd 100              ; Réserver de l'espace pour 100 doubles mots

Accès aux éléments d'un tableau

L'accès aux éléments d'un tableau utilise le mode d'adressagebase + index × element size:

Exemple

; Chemin du fichier : array_access.asm
; Lecture et écriture des éléments du tableau

section .data
    nums dd 100, 200, 300, 400, 500   ; 5 éléments
    nums_len equ ($ - nums) / 4

section .text
    global _start

_start:
    ; Accéder à l'élément 0 (indice 0)
    mov eax, [nums]              ; eax = 100

    ; Accéder au 2e élément (indice 2)
    mov eax, [nums + 2 * 4]      ; eax = nums[2] = 300
    ; 2 * 4 = 8, donc décalage de 8 octets depuis nums

    ; Utiliser un registre comme indice
    mov esi, 3                   ; Indice = 3
    mov eax, [nums + esi * 4]    ; eax = nums[3] = 400

    ; Modifier les éléments du tableau
    mov dword [nums + 4], 250    ; nums[1] = 250
    ; Le tableau contient maintenant : 100, 250, 300, 400, 500

    ; Utiliser EBX comme registre de base
    mov ebx, nums                ; ebx = adresse de base du tableau
    mov eax, [ebx + 4 * 4]       ; eax = nums[4] = 500

    mov eax, 1
    mov ebx, 0
    int 0x80

Remarque :[nums + esi * 4]La multiplication par 4 s'explique par le fait que chaque élément fait 4 octets (doubleword). Pour un tableau d'octets (db), écrivez-le directement comme[arr + esi]; pour un tableau de mots (dw), écrivez-le comme[arr + esi * 2]。


Parcours de tableau

Exemple

; Chemin du fichier : array_traverse.asm
; Parcourir le tableau et calculer la somme

section .data
    numbers dd 5, 10, 15, 20, 25, 30, 35, 40, 45, 50
    count equ ($ - numbers) / 4   ; Nombre d'éléments

section .text
    global _start

_start:
    mov ecx, count                ; Nombre d'itérations
    mov esi, 0                    ; Indice (à partir de 0)
    mov eax, 0                    ; Somme accumulée

sum_loop:
    add eax, [numbers + esi * 4]  ; Accumuler les éléments du tableau
    inc esi                       ; Indice + 1
    loop sum_loop
    ; eax = 5+10+15+...+50 = 275

    ; Autre méthode de parcours : utilisation d'un pointeur
    mov ecx, count
    mov ebx, numbers              ; ebx pointe vers le début du tableau
    mov eax, 0                    ; Somme accumulée

sum_loop2:
    add eax, [ebx]                ; Accumuler l'élément courant
    add ebx, 4                    ; Déplacer le pointeur vers l'élément suivant
    loop sum_loop2
    ; eax = 275

    mov ebx, eax                  ; Code de sortie = somme accumulée
    mov eax, 1
    int 0x80

Recherche dans un tableau

Exemple

; Chemin du fichier : array_search.asm
; Rechercher une valeur spécifiée dans le tableau

section .data
    data dd 12, 45, 67, 23, 89, 34, 56, 78, 90, 11
    data_len equ ($ - data) / 4
    target dd 23                   ; La valeur à rechercher
    found_msg db 'Trouvé à l’index : ', 0
    found_len equ $ - found_msg
    notfound_msg db 'Non trouvé (exemple)', 0xA
    notfound_len equ $ - notfound_msg
    newline db 0xA

section .text
    global _start

_start:
    mov ecx, data_len             ; Nombre d’itérations
    mov esi, 0                    ; Index actuel

search_loop:
    mov eax, [data + esi * 4]     ; Charger l’élément courant
    cmp eax, [target]             ; Vérifier s’il est égal à la valeur cible
    je  found                     ; Trouvé

    inc esi                       ; Indice + 1
    loop search_loop

    ; Non trouvé
    mov eax, 4
    mov ebx, 1
    mov ecx, notfound_msg
    mov edx, notfound_len
    int 0x80
    jmp exit

found:
    ; Trouvé (esi est l'indice)
    mov eax, 4
    mov ebx, 1
    mov ecx, found_msg
    mov edx, found_len
    int 0x80

    ; Convertir l'indice en un caractère ASCII et l'afficher
    add esi, '0'                  ; Convertir un indice à un seul chiffre en un caractère
    push esi                      ; Empiler sur la pile pour un stockage temporaire
    mov eax, 4
    mov ebx, 1
    mov ecx, esp                  ; Adresse du sommet de la pile
    mov edx, 1
    int 0x80
    pop esi

    ; Afficher un saut de ligne
    mov eax, 4
    mov ebx, 1
    mov ecx, newline
    mov edx, 1
    int 0x80

exit:
    mov eax, 1
    mov ebx, 0
    int 0x80

Tableau à deux dimensions

Un tableau à deux dimensions est développé ligne par ligne en un stockage unidimensionnel en mémoire. La formule d'adresse pour accéder àarr[i][j]est :

地址 = 基址 + (i*列数 + j) * 元素大小

Exemple

; Chemin du fichier : 2d_array.asm
= 10 (ligne 3, colonne 2)

section .data
   
    matrix dd 1,  2,  3,  4
           dd 5,  6,  7,  8
           dd 9, 10, 11, 12

    rows equ 3
    cols equ 4
    elem_size equ 4              ; DWORD = 4 octets

section .text
    global _start

_start:
    ; Accès à matrix
    ; Adresse = matrix + (1*4 + 2) * 4 = matrix + 24

    mov eax, [matrix + (1 * cols + 2) * elem_size]
    ; eax = 7

    ; Calcul dynamique utilisant les registres (en supposant i=2, j=1)
    ; matrix
    mov esi, 2                   ; Ligne i = 2
    mov edi, 1                   ; Colonne j = 1

    mov eax, cols                ; Nombre de colonnes
    mul esi                      ; eax = i * cols = 2*4 = 8
    add eax, edi                 ; eax = i*cols + j = 8+1 = 9
    ; eax = eax * elem_size
    ; Remarque : Le résultat de MUL est dans EAX, utilisez-le directement ici
    mov eax, [matrix + eax * elem_size]
    ; eax = 10

    ; Parcourir tous les éléments d'un tableau 2D
    mov ecx, rows * cols         ; Nombre total d'éléments = 12
    mov esi, 0                   ; Indice
    mov ebx, 0                   ; Somme accumulée

traverse:
    add ebx, [matrix + esi * elem_size]
    inc esi
    loop traverse
    ; ebx = 1+2+3+...+12 = 78

    mov eax, 1
    int 0x80

Exemple complet de tri à bulles

Exemple

; Chemin du fichier : bubble_sort.asm
; Algorithme de tri à bulles

section .data
    array dd 64, 34, 25, 12, 22, 11, 90, 78
    array_len equ ($ - array) / 4

section .text
    global _start

_start:
    mov ecx, array_len            ; Boucle externe : n fois
    dec ecx                       ; La boucle externe ne nécessite que n-1 itérations

outer_loop:
    push ecx                      ; Sauvegarder le compteur de la boucle externe

    mov esi, 0                    ; L'indice de la boucle interne commence à 0
    mov ecx, array_len - 1        ; Nombre d'itérations de la boucle interne

inner_loop:
    mov eax, [array + esi * 4]    ; a[j]
    mov ebx, [array + esi * 4 + 4]  ; a[j+1]
    cmp eax, ebx                  ; a[j] > a[j+1] ?
    jle no_swap                   ; Non, ne pas échanger

    ; Échanger a[j] et a[j+1]
    mov [array + esi * 4], ebx
    mov [array + esi * 4 + 4], eax

no_swap:
    inc esi
    loop inner_loop

    pop ecx
    loop outer_loop
    ; Le tableau est maintenant trié : 11, 12, 22, 25, 34, 64, 78, 90

    mov eax, 1
    mov ebx, 0
    int 0x80

Les tableaux en langage d'assemblage n'ont pas de contrôle des limites. Accéder à un indice hors limites ne lèvera pas d'erreur ; à la place, cela lit ou écrit silencieusement des données dans la mémoire adjacente, ce qui peut entraîner des bogues difficiles à déboguer. Assurez-vous de vérifier vous-même que l'indice est dans les limites valides.

Autres extensions