x64汇编语言与逆向工程基础指南(四)

1. 数组的存储与遍历

1.1 编写数组数据写入内存

  • 首先选中某部分地址编辑数据,这里以x64架构的 " long "类型数组为例,即每个元素占据8字节(qword)。

类比如图
在这里插入图片描述

  • 构造数组元素如下图:
    在这里插入图片描述
  • 易知,数组结构如下表
IndexAddressData
00x7FF68FE800500x11
10x7FF68FE800580x22
20x7FF68FE800600x33
30x7FF68FE800680x44
40x7FF68FE800700x55

1.2 汇编循环遍历数组元素

	mov rbx,0x7FF68FE80050               //将数组基地址(首地址)赋给 rbx寄存器保存
	mov rcx,0                           // 将 rcx寄存器作为index
loop_start:                             //循环体
	mov rax,qword ptr[rbx+rcx*8]        // 取出数组元素放入rax寄存器
	inc rcx                             //索引值自增
	cmp rcx,5                           //跳出循环判断
	jl loop_start                      //  如果 rcx < 5 ,则执行跳转

在这里插入图片描述

  • 执行结果如下:
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. Lea指令

  • lea(Load Effective Address)指令用于计算内存地址而不进行内存访问。它将地址表达式的结果加载到寄存器中。比如:
lea rax, [rbx + 4*rcx]
  • 这条指令计算 (rbx + 4*rcx) 的地址,并将结果存储到 rax 寄存器中。lea 可以用来进行地址计算、实现指针算术或调整寄存器值,但不会访问内存中的数据。

示例:

lea rdx, [rbx+rcx*8]
mov r9, qword ptr [rdx]
  • 执行前状态
    在这里插入图片描述
  • 执行结果
    在这里插入图片描述

lea 指令也可以作为计算器存储计算结果
如:仅使用 lea rax, [rbx+rdx * 3] 指令将会把 rbx+rdx*3 式子的结果存储到 rbx寄存器。

4. mul指令与imul指令

mulimul 指令用于执行乘法操作,但它们在处理有符号数和无符号数、以及结果存储方面有所不同。

4.1 mul 指令

mul 指令用于执行无符号乘法。它有不同的操作数形式和结果存储方式:

  1. 8位操作数

    mul al  ; AL 寄存器中的值与操作数(AL)相乘,结果存储在 AX 中。
    
    • 操作数:AL(8位寄存器)
    • 结果:AX(16位寄存器)
    • AX = AL * 操作数
    • 如果结果超过16位,则 AX 中高字节的值将反映结果的高位部分。
  2. 16位操作数

    mul ax  ; AX 寄存器中的值与操作数(AX)相乘,结果存储在 DX:AX 中。
    
    • 操作数:AX(16位寄存器)
    • 结果:DX:AX(32位结果)
    • DX:AX = AX * 操作数
    • 如果结果超过16位,则 DX 中的高16位包含结果的高位部分,AX 中的低16位包含结果的低位部分。
  3. 32位操作数

    mul eax  ; EAX 寄存器中的值与操作数(EAX)相乘,结果存储在 EDX:EAX 中。
    
    • 操作数:EAX(32位寄存器)
    • 结果:EDX:EAX(64位结果)
    • EDX:EAX = EAX * 操作数
    • 如果结果超过32位,则 EDX 中的高32位包含结果的高位部分,EAX 中的低32位包含结果的低位部分。

mul 指令的特点

  • mul 指令始终是无符号乘法。
  • 结果存储在特定的寄存器对中,以便捕获可能的溢出。
  • 操作数通常是寄存器中的值,但也可以是内存中的值。

4.2 imul 指令

imul 指令用于执行有符号乘法。它有几种不同的操作数形式:

  1. 单操作数形式

    imul ax  ; AX 寄存器中的值与操作数(AX)相乘,结果存储在 AX 中。
    
    • 操作数:AX(16位寄存器)
    • 结果:AX(16位寄存器)
    • AX = AX * 操作数
    • 如果结果溢出,结果会被截断,只保留低位部分。
  2. 双操作数形式

    imul eax, ebx  ; EAX 寄存器中的值与 EBX 寄存器中的值相乘,结果存储在 EAX 中。
    
    • 操作数:EAX(32位寄存器)、EBX(32位寄存器)
    • 结果:EAX(32位寄存器)
    • EAX = EAX * EBX
    • 如果结果超出32位范围,则结果会被截断,只保留低32位部分。
  3. 三操作数形式

    imul eax, ebx, 5  ; EAX 寄存器中的值与 EBX 寄存器中的值和 5 相乘,结果存储在 EAX 中。
    
    • 操作数:EAX(32位寄存器)、EBX(32位寄存器)、5(立即数)
    • 结果:EAX(32位寄存器)
    • EAX = EBX * 5
    • 这里,EBX 乘以 5,结果存储在 EAX 中。

imul 指令的特点

  • imul 指令是有符号乘法。
  • imul 的结果是有符号的,考虑了符号位。
  • 当使用多操作数形式时,imul 可以用来进行更复杂的乘法计算。

总结

  • mul 进行无符号乘法,结果存储在特定的寄存器对中(例如,DX:AXEDX:EAX)。
  • imul 进行有符号乘法,支持多种形式,包括单操作数、双操作数和三操作数形式。结果存储在目的寄存器中。
  • mulimul 都会根据操作数的大小选择适当的寄存器对来存储结果,以处理可能的溢出。

5. div指令

div 指令用于执行无符号除法操作。与 mulimul 指令不同,div 指令用于将一个数除以另一个数,并计算商和余数。它的操作方式根据操作数的大小和类型有所不同。

5.1 div 指令的基本原理

div 指令会根据被除数和除数的大小来选择不同的寄存器对,以存储商和余数。操作数是无符号的,所以结果也会是无符号的。

5.2 8 位除法

语法

div byte [memory]  ; 除数在内存中
div al             ; 除数在 AL 寄存器中
  • 被除数AX 寄存器
  • 除数:8 位操作数(如 AL 寄存器中的值或内存中的值)
  • AL 寄存器
  • 余数AH 寄存器

计算

AX / 除数 = 商 (AL)
AX % 除数 = 余数 (AH)
  • AX 寄存器的高字节 AH 和低字节 AL 共同存储被除数。
  • div 指令将 AL 除以操作数,结果存储在 AL 中,余数存储在 AH 中。

示例代码

mov al, 20      ; 被除数
mov bl, 4       ; 除数
div bl           ; AL = AL / BL, AH = AL % BL
; 结果:AL = 5, AH = 0

5.3 16 位除法

语法

div word [memory]  ; 除数在内存中
div ax             ; 除数在 AX 寄存器中
  • 被除数DX:AX 寄存器对
  • 除数:16 位操作数(如 AX 寄存器中的值或内存中的值)
  • AX 寄存器
  • 余数DX 寄存器

计算

DX:AX / 除数 = 商 (AX)
DX:AX % 除数 = 余数 (DX)
  • DX 寄存器存储被除数的高16位,AX 寄存器存储低16位。
  • div 指令将 DX:AX 除以操作数,结果存储在 AX 中,余数存储在 DX 中。

示例代码

mov ax, 1000    ; 被除数
mov bx, 25      ; 除数
div bx           ; DX:AX = AX / BX, DX = AX % BX
; 结果:AX = 40, DX = 0

5.3 32 位除法

语法

div dword [memory]  ; 除数在内存中
div eax             ; 除数在 EAX 寄存器中
  • 被除数EDX:EAX 寄存器对
  • 除数:32 位操作数(如 EAX 寄存器中的值或内存中的值)
  • EAX 寄存器
  • 余数EDX 寄存器

计算

EDX:EAX / 除数 = 商 (EAX)
EDX:EAX % 除数 = 余数 (EDX)
  • EDX 寄存器存储被除数的高32位,EAX 寄存器存储低32位。
  • div 指令将 EDX:EAX 除以操作数,结果存储在 EAX 中,余数存储在 EDX 中。

示例代码

mov eax, 100000 ; 被除数
mov ebx, 200    ; 除数
div ebx          ; EDX:EAX = EAX / EBX, EDX = EAX % EBX
; 结果:EAX = 500, EDX = 0

特点和要求

  1. 被除数和除数的大小

    • div 指令要求被除数必须通过寄存器对来存储,以适应可能的结果范围(AX 对于8位操作数,DX:AX 对于16位操作数,EDX:EAX 对于32位操作数)。
    • 除数的大小必须与被除数的大小相匹配。
  2. 除数不能为零

    • 如果除数为零,div 指令会引发除零异常,这是一个运行时错误。
  3. 结果存储

    • 商和余数分别存储在特定的寄存器中。如果结果超出寄存器的大小,div 指令会在商寄存器中存储结果的低位部分,而高位部分存储在余数寄存器中。
  4. 标志位

    • div 指令不会影响标志寄存器的标志位(如 ZFOFCFSF

在使用 div 指令时,请确保被除数的大小和除数匹配,并且除数不能为零,以避免程序异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暮夜--

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值