--- 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。务必自己确保索引在合法范围内。