汇编语言数组.md

原始源文件

---
ingested: true
ingestedAt: 2026-05-17
---
标题: 汇编语言 - 数组
UP主: runoob
链接: https://www.runoob.com/assembly/assembly-array.html
提取方式: WebFetch
内容: 数组是连续存放的同类型数据集合。在汇编中,数组就是内存中一段连续的空间,通过基址加偏移的方式来访问每个元素。

---

## 一维数组定义

## 实例

; 数组的定义方式

section .data  
; 方式1:逐个列出元素  
 arr1 dd 10, 20, 30, 40, 50 ; 5 个双字元素的数组

; 方式2:用 dup 初始化  
 arr2 dd 10 dup(0) ; 10 个双字,全为 0

; 方式3:字节数组  
 bytes db 1, 2, 3, 4, 5, 6 ; 6 个字节

; 方式4:字符数组(字符串)  
 chars db 'runoob', 0 ; 7 字节

; 数组长度计算(编译时)  
 arr1_len equ ($ - arr1) / 4 ; 双字数组的元素个数  
 arr2_len equ ($ - arr2) / 4  
 bytes_len equ ($ - bytes) ; 字节数组,不需除法

section .bss  
; 未初始化的数组  
 buffer resd 100 ; 预留 100 个双字的空间  

---

## 数组元素访问

访问数组元素使用 基址 + 索引 × 元素大小 的寻址方式:

## 实例

; 文件路径:array_access.asm  
; 数组元素的读取和写入

section .data  
 nums dd 100, 200, 300, 400, 500 ; 5 个元素  
 nums_len equ ($ - nums) / 4

section .text  
global _start

_start:  
; 访问第 0 个元素(下标 0)  
mov eax, [nums] ; eax = 100

; 访问第 2 个元素(下标 2)  
mov eax, [nums + 2 * 4] ; eax = nums[2] = 300  
; 2 * 4 = 8,从 nums 偏移 8 字节

; 使用寄存器作为下标  
mov esi, 3 ; 下标 = 3  
mov eax, [nums + esi * 4] ; eax = nums[3] = 400

; 修改数组元素  
mov dword [nums + 4], 250 ; nums[1] = 250  
; 数组中现在:100, 250, 300, 400, 500

; 使用 EBX 作为基址寄存器  
mov ebx, nums ; ebx = 数组基址  
mov eax, [ebx + 4 * 4] ; eax = nums[4] = 500

mov eax, 1  
mov ebx, 0  
int 0x80  

> 注意:`[nums + esi * 4]` 中的乘以 4 是因为每个元素是 4 字节(双字)。如果是字节数组(db),直接写成 `[arr + esi]`;字数组(dw),写成 `[arr + esi * 2]`。

---

## 数组遍历

## 实例

; 文件路径:array_traverse.asm  
; 遍历数组并计算总和

section .data  
 numbers dd 5, 10, 15, 20, 25, 30, 35, 40, 45, 50  
 count equ ($ - numbers) / 4 ; 元素个数

section .text  
global _start

_start:  
mov ecx, count ; 循环次数  
mov esi, 0 ; 下标(从 0 开始)  
mov eax, 0 ; 累加和

sum_loop:  
add eax, [numbers + esi * 4] ; 累加数组元素  
inc esi ; 下标 +1  
loop sum_loop  
; eax = 5+10+15+...+50 = 275

; 另一种遍历方式:使用指针  
mov ecx, count  
mov ebx, numbers ; ebx 指向数组起始  
mov eax, 0 ; 累加和

sum_loop2:  
add eax, [ebx] ; 累加当前元素  
add ebx, 4 ; 指针移动到下一个元素  
loop sum_loop2  
; eax = 275

mov ebx, eax ; 退出码 = 累加和  
mov eax, 1  
int 0x80  

---

## 数组查找

## 实例

; 文件路径:array_search.asm  
; 在数组中查找指定值

section .data  
data dd 12, 45, 67, 23, 89, 34, 56, 78, 90, 11  
 data_len equ ($ - data) / 4  
 target dd 23 ; 要查找的值  
 found_msg db 'Found at index: ', 0  
 found_len equ $ - found_msg  
 notfound_msg db 'Not found (runoob)', 0xA  
 notfound_len equ $ - notfound_msg  
 newline db 0xA

section .text  
global _start

_start:  
mov ecx, data_len ; 循环次数  
mov esi, 0 ; 当前下标

search_loop:  
mov eax, [data + esi * 4] ; 加载当前元素  
cmp eax, [target] ; 是否等于目标值  
je found ; 找到了

inc esi ; 下标 +1  
loop search_loop

; 没找到  
mov eax, 4  
mov ebx, 1  
mov ecx, notfound_msg  
mov edx, notfound_len  
int 0x80  
jmp exit

found:  
; 找到了(esi 是下标)  
mov eax, 4  
mov ebx, 1  
mov ecx, found_msg  
mov edx, found_len  
int 0x80

; 将下标转为 ASCII 字符输出  
add esi, '0' ; 单数字下标转字符  
push esi ; 压栈作为临时存储  
mov eax, 4  
mov ebx, 1  
mov ecx, esp ; 栈顶地址  
mov edx, 1  
int 0x80  
pop esi

; 输出换行  
mov eax, 4  
mov ebx, 1  
mov ecx, newline  
mov edx, 1  
int 0x80

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

---

## 二维数组

二维数组在内存中按行展开为一维存储。访问 `arr[i][j]` 的地址公式为:

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

## 实例

; 文件路径:2d_array.asm  
; 二维数组的定义和访问

section .data  
; 3 行 4 列的二维数组  
 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 ; 双字 = 4 字节

section .text  
global _start

_start:  
; 访问 matrix[1][2] = 7(第2行第3列)  
; 地址 = matrix + (1*4 + 2) * 4 = matrix + 24

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

; 使用寄存器动态计算(假设 i=2, j=1)  
; matrix[2][1] = 10(第3行第2列)  
mov esi, 2 ; 行 i = 2  
mov edi, 1 ; 列 j = 1

mov eax, cols ; 列数  
mul esi ; eax = i * cols = 2*4 = 8  
add eax, edi ; eax = i*cols + j = 8+1 = 9  
; eax = eax * elem_size  
; 注意:MUL 的结果在 EAX 中,这里直接使用  
mov eax, [matrix + eax * elem_size]  
; eax = 10

; 遍历二维数组所有元素  
mov ecx, rows * cols ; 总元素数 = 12  
mov esi, 0 ; 下标  
mov ebx, 0 ; 累加和

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

mov eax, 1  
int 0x80  

---

## 冒泡排序完整示例

## 实例

; 文件路径:bubble_sort.asm  
; 冒泡排序算法

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 ; 外层循环:n 次  
dec ecx ; 外层只需 n-1 次

outer_loop:  
push ecx ; 保存外层计数器

mov esi, 0 ; 内层下标从 0 开始  
mov ecx, array_len - 1 ; 内层循环次数

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 ; 否,不交换

; 交换 a[j] 和 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  
; 数组现在已排序:11, 12, 22, 25, 34, 64, 78, 90

mov eax, 1  
mov ebx, 0  
int 0x80  

> 汇编语言中的数组没有任何边界检查。访问越界的索引不会报错,而是会静默地读写邻近内存中的数据,这可能导致难以调试的 bug。务必自己确保索引在合法范围内。