汇编:数组-寻址&取数据

比例因子寻址

比例因子寻址(也称为比例缩放索引寻址或基址加变址加比例因子寻址)是一种复杂的内存寻址方式,常用于数组和指针操作。它允许通过一个基址寄存器、一个变址寄存器和一个比例因子来计算内存地址。

语法

比例因子寻址的通用格式为:

[base + index * scale + displacement]
  • base:基址。

  • index:变址寄存器(如 ESIEDI 等)。

  • scale:比例因子,可以是 1、2、4、8(根据数组元素数据类型决定)。

  • displacement:位移量,可以是一个立即数(常数)。

示例:使用循环来操作一个字节数组
.586
.model flat,stdcall
option casemap:none
​
.data
byte_arr db 13,23,14,25 ;定义数组
​
.code
main proc
    xor ebx,ebx   ;xor异或指令;将 EBX 寄存器清零。
    mov eax,offset byte_arr  
loop_a:
    mov [eax + ebx * 1],bl  ;[eax + ebx * 1] 可以获取到字节数组每个元素的地址(ebx可以自加)
                            ;若是字数组:[eax + ebx * 2],双字数组:[eax + ebx * 4]..根据数组元素类型选择数字(字节)
    inc bl
    cmp ebx,4
    jl loop_a
main endp
end
代码执行过程
  1. 初始化 EBX 为 0 和 EAXbyte_arr 的地址。

  2. 进入循环,[eax + ebx * 1] 依次访问 byte_arr 的每个字节,将 BL 寄存器的值(从 0 开始递增)存储到数组的每个元素中。

  3. 循环结束后,byte_arr 的所有元素将被替换为 [0, 1, 2, 3]

代码段解释:
  • xor ebx,ebxEBX 寄存器清零,即 EBX = 0

  • mov eax,offset byte_arrbyte_arr 的地址加载到 EAX 寄存器。

  • loop_a: 是标签,表示循环的起始位置。

  • mov [eax + ebx * 1],blBL 寄存器的值存储到 byte_arr 数组中的相应位置。具体来说,[eax + ebx * 1] 计算数组 byte_arr 中的当前元素地址,并将 BL 的值存储到该位置。因为 EBX 从 0 开始,因此这将依次操作 byte_arr 的每个字节。(EBX32位寄存器,但是由于此时数组元素为1字节,8位数据;所以次数若是将ebx中的数据mov至数组元素中会造成数据溢出,所以只能movBL

  • inc blBL 寄存器的值加 1。

  • cmp ebx,4EBX 寄存器的值与 4 进行比较。

  • jl loop_a 如果 EBX 的值小于 4,则跳转到 loop_a,继续循环。

代码执行效果

byte_arr 将从原来的 [13, 23, 14, 25] 被修改为 [0, 1, 2, 3]

执行前数组内的数据:

执行后数组内的数据:

取数据

通过比例因子寻址取到地址后就可以使用LODS系列指令取数据。

LODS(Load String)指令是一条字符串操作指令,用于从数据段加载一个字节、一个字(16位),或者一个双字(32位)到累加器寄存器(AL, AX, EAX)。它使用源索引寄存器 ESI 来指示要加载的数据的地址,并根据方向标志位(DF)来决定 ESI 的增减。

语法
  • LODSB:从 [ESI] 加载一个字节到 AL,并根据 DF 更新 ESI

  • LODSW:从 [ESI] 加载一个字到 AX,并根据 DF 更新 ESI

  • LODSD:从 [ESI] 加载一个双字到 EAX,并根据 DF 更新 ESI

方向标志位(DF)
  • 如果 DF 为 0(使用 CLD 清除),ESI 递增。

  • 如果 DF 为 1(使用 STD 设置),ESI 递减。

示例:

使用 LODSB 指令从数组中逐字节加载数据。

.586
.model flat,stdcall
option casemap:none
​
.data
byte_arr db 13,23,14,25
​
.code
main proc
;取数据代码
    xor eax,eax     ;将 EAX 寄存器清零。
    mov esi,offset byte_arr
    mov ecx,4
lods_a:
    lodsb   ;根据ESI中的数组基地址,将数据加载至AL寄存器中
    loop lods_a
​
main endp
end 

xor eax,eax:将 EAX 寄存器清零。

mov esi,offset byte_arr:将数组 byte_arr 的地址加载到 ESI 寄存器。

mov ecx,4:将 ECX 寄存器设置为 4,表示要处理的字节数。

lods_a::标签,表示循环的起始位置。

lodsb:从 ESI 指向的地址加载一个字节到 AL 寄存器,并根据方向标志(DF)更新 ESI。默认情况下,ESI 会递增。

loop lods_a:将 ECX 寄存器的值减 1;如果 ECX 的值不为 0,则跳转到 lods_a,继续循环。

内存中的数组:

取出数据:

相关推荐

  1. 常见的数据方式

    2024-06-09 21:16:05       30 阅读
  2. 汇编】指令系统的方式

    2024-06-09 21:16:05       39 阅读
  3. 汇编:保护模式下的方式

    2024-06-09 21:16:05       31 阅读
  4. arm方式

    2024-06-09 21:16:05       60 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-09 21:16:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-09 21:16:05       101 阅读
  3. 在Django里面运行非项目文件

    2024-06-09 21:16:05       82 阅读
  4. Python语言-面向对象

    2024-06-09 21:16:05       91 阅读

热门阅读

  1. Search用法Python:深入探索搜索功能的应用与技巧

    2024-06-09 21:16:05       32 阅读
  2. spring框架限制接口是否要登录过才能访问

    2024-06-09 21:16:05       33 阅读
  3. 如何用结构化写好GPT的Prompt提示词

    2024-06-09 21:16:05       32 阅读
  4. DefaultTokenServices源码

    2024-06-09 21:16:05       24 阅读
  5. Fatfs

    Fatfs

    2024-06-09 21:16:05      20 阅读
  6. 基于Golang的AOI算法实现与优化

    2024-06-09 21:16:05       24 阅读
  7. k8s学习--kube-proxy的三种工作模式详细解释

    2024-06-09 21:16:05       28 阅读