汇编语言 - 数组

汇编语言 - 数组

汇编语言 - 数组

数组是连续存放的同类型数据集合。在汇编中,数组就是内存中一段连续的空间,通过基址加偏移的方式来访问每个元素。

一维数组定义

实例

; 数组的定义方式

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

你可能也喜欢

魔兽世界神器在哪儿看
be365是否安全

魔兽世界神器在哪儿看

📅 07-12 👀 7208
问道力带什么娃娃?最新娃娃推荐!
365bet官方投注网站

问道力带什么娃娃?最新娃娃推荐!

📅 09-26 👀 2911
快乐番薯廖明通:要学会降低成本,缩减SKU-TopMarketing
十大好用的推广平台 推广网站有哪些 推广引流平台推荐→MAIGOO生活榜
【京东优评】热卖商品
365bet365娱乐场

【京东优评】热卖商品

📅 11-18 👀 7222
触控芯片市场份额报告:全球行业规模、市场占有率及排名
泉的解釋
be365是否安全

泉的解釋

📅 11-15 👀 5528
遭遇海盗要怎样保命?海盗旗的起源及背后鲜为人知的秘密
在我附近购买蒟蒻可享受免费送货
365bet官方投注网站

在我附近购买蒟蒻可享受免费送货

📅 08-06 👀 3632