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
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
; 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
; 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
; 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
= 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
; 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
Autres extensionsLes 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.