Un arreglo es una colección de datos del mismo tipo almacenados de forma contigua. En ensamblador, un arreglo es un espacio continuo en memoria, y cada elemento se accede mediante base más desplazamiento.
Definición de arreglo unidimensional
Ejemplo
section .data
; Método 1: enumerar los elementos uno por uno
arr1 dd 10, 20, 30, 40, 50 ; Un arreglo de 5 elementos de doble palabra (dword)
; Método 2: inicializar con dup
arr2 dd 10 dup(0) ; 10 dobles palabras, todas en 0
; Método 3: arreglo de bytes
bytes db 1, 2, 3, 4, 5, 6 ; 6 bytes
; Método 4: arreglo de caracteres (cadena)
chars db 'ejemplo', 0 ; 7 bytes
; Cálculo de la longitud del arreglo (en tiempo de compilación)
arr1_len equ ($ - arr1) / 4 ; Número de elementos de un arreglo de dobles palabras
arr2_len equ ($ - arr2) / 4
bytes_len equ ($ - bytes) ; Arreglo de bytes, no necesita división
section .bss
; Arreglo no inicializado
buffer resd 100 ; Reservar espacio para 100 dobles palabras
Acceso a elementos de arreglo
Para acceder a los elementos del arreglo se usabase + índice × tamaño del elementocomo modo de direccionamiento:
Ejemplo
; Lectura y escritura de elementos de un arreglo
section .data
nums dd 100, 200, 300, 400, 500 ; 5 elementos
nums_len equ ($ - nums) / 4
section .text
global _start
_start:
; Acceder al elemento 0 (índice 0)
mov eax, [nums] ; eax = 100
; Acceder al elemento 2 (índice 2)
mov eax, [nums + 2 * 4] ; eax = nums[2] = 300
; 2 * 4 = 8, desplazamiento de 8 bytes desde nums
; Usar un registro como índice
mov esi, 3 ; Índice = 3
mov eax, [nums + esi * 4] ; eax = nums[3] = 400
; Modificar un elemento del arreglo
mov dword [nums + 4], 250 ; nums[1] = 250
; El arreglo ahora es: 100, 250, 300, 400, 500
; Usar EBX como registro base
mov ebx, nums ; ebx = dirección base del arreglo
mov eax, [ebx + 4 * 4] ; eax = nums[4] = 500
mov eax, 1
mov ebx, 0
int 0x80
Nota:
[nums + esi * 4]La multiplicación por 4 en la fórmula se debe a que cada elemento es de 4 bytes (doble palabra). Si es un arreglo de bytes (db), se escribe directamente como[arr + esi]; para un arreglo de palabras (dw), se escribe como[arr + esi * 2]。
Recorrido del arreglo
Ejemplo
; Recorrer el arreglo y calcular la suma
section .data
numbers dd 5, 10, 15, 20, 25, 30, 35, 40, 45, 50
count equ ($ - numbers) / 4 ; Número de elementos
section .text
global _start
_start:
mov ecx, count ; Número de iteraciones del bucle
mov esi, 0 ; Índice (comenzando desde 0)
mov eax, 0 ; Suma acumulada
sum_loop:
add eax, [numbers + esi * 4] ; Acumular el elemento del arreglo
inc esi ; Índice + 1
loop sum_loop
; eax = 5+10+15+...+50 = 275
; Otro método de recorrido: usar puntero
mov ecx, count
mov ebx, numbers ; ebx apunta al inicio del arreglo
mov eax, 0 ; Suma acumulada
sum_loop2:
add eax, [ebx] ; Acumular el elemento actual
add ebx, 4 ; Mover el puntero al siguiente elemento
loop sum_loop2
; eax = 275
mov ebx, eax ; Código de salida = suma acumulada
mov eax, 1
int 0x80
Búsqueda en arreglo
Ejemplo
; Buscar un valor específico en el arreglo
section .data
data dd 12, 45, 67, 23, 89, 34, 56, 78, 90, 11
data_len equ ($ - data) / 4
target dd 23 ; Valor a buscar
found_msg db 'Found at index: ', 0
found_len equ $ - found_msg
notfound_msg db 'Not found (ejemplo)', 0xA
notfound_len equ $ - notfound_msg
newline db 0xA
section .text
global _start
_start:
mov ecx, data_len ; Número de iteraciones del bucle
mov esi, 0 ; Índice actual
search_loop:
mov eax, [data + esi * 4] ; Cargar el elemento actual
cmp eax, [target] ; Si es igual al valor objetivo
je found ; Encontrado
inc esi ; Índice + 1
loop search_loop
; No encontrado
mov eax, 4
mov ebx, 1
mov ecx, notfound_msg
mov edx, notfound_len
int 0x80
jmp exit
found:
; Encontrado (esi es el índice)
mov eax, 4
mov ebx, 1
mov ecx, found_msg
mov edx, found_len
int 0x80
; Convertir el índice a carácter ASCII para la salida
add esi, '0' ; Convertir un índice de un solo dígito a carácter
push esi ; Empujar a la pila como almacenamiento temporal
mov eax, 4
mov ebx, 1
mov ecx, esp ; Dirección del tope de la pila
mov edx, 1
int 0x80
pop esi
; Salida de nueva línea
mov eax, 4
mov ebx, 1
mov ecx, newline
mov edx, 1
int 0x80
exit:
mov eax, 1
mov ebx, 0
int 0x80
Arreglo bidimensional
Un arreglo bidimensional se expande por filas en memoria como almacenamiento unidimensional. Para accederarr[i][j]a él, la fórmula de dirección es:
地址 = 基址 + (i*列数 + j) * 元素大小
Ejemplo
; Definición y acceso de un arreglo bidimensional
section .data
; Arreglo bidimensional de 3 filas y 4 columnas
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 ; Doble palabra = 4 bytes
section .text
global _start
_start:
; Acceder a matrix
; Dirección = matrix + (1*4 + 2) * 4 = matrix + 24
mov eax, [matrix + (1 * cols + 2) * elem_size]
; eax = 7
; Cálculo dinámico con registros (suponiendo i=2, j=1)
; matrix
mov esi, 2 ; Fila i = 2
mov edi, 1 ; Columna j = 1
mov eax, cols ; Número de columnas
mul esi ; eax = i * cols = 2*4 = 8
add eax, edi ; eax = i*cols + j = 8+1 = 9
; eax = eax * elem_size
; Nota: el resultado de MUL está en EAX, aquí se usa directamente
mov eax, [matrix + eax * elem_size]
; eax = 10
; Recorrer todos los elementos del arreglo bidimensional
mov ecx, rows * cols ; Número total de elementos = 12
mov esi, 0 ; Índice
mov ebx, 0 ; Suma acumulada
traverse:
add ebx, [matrix + esi * elem_size]
inc esi
loop traverse
; ebx = 1+2+3+...+12 = 78
mov eax, 1
int 0x80
Ejemplo completo de ordenamiento de burbuja
Ejemplo
; Algoritmo de ordenamiento de burbuja
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 ; Bucle externo: n veces
dec ecx ; El bucle externo solo necesita n-1 veces
outer_loop:
push ecx ; Guardar el contador del bucle externo
mov esi, 0 ; El índice del bucle interno comienza en 0
mov ecx, array_len - 1 ; Número de iteraciones del bucle interno
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 ; No, no intercambiar
; Intercambiar a[j] y 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
; El arreglo ahora está ordenado: 11, 12, 22, 25, 34, 64, 78, 90
mov eax, 1
mov ebx, 0
int 0x80
Otras extensionesLos arreglos en lenguaje ensamblador no tienen ninguna verificación de límites. Acceder a un índice fuera de rango no genera un error, sino que lee o escribe silenciosamente datos en la memoria adyacente, lo que puede causar errores difíciles de depurar. Asegúrate siempre de que el índice esté dentro del rango válido.