欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > 【汇编逆向系列】一、无参数的函数调用- RSP,EAX寄存器,全局变量,INT类型和MOV,INC,SHL指令

【汇编逆向系列】一、无参数的函数调用- RSP,EAX寄存器,全局变量,INT类型和MOV,INC,SHL指令

2025/6/8 13:49:39 来源:https://blog.csdn.net/pietian1157/article/details/148404607  浏览:    关键词:【汇编逆向系列】一、无参数的函数调用- RSP,EAX寄存器,全局变量,INT类型和MOV,INC,SHL指令

给出一段简单的汇编

no_params_function:0000000000000000: 40 57              push        rdi0000000000000002: 8B 05 00 00 00 00  mov         eax,dword ptr [global_counter]0000000000000008: FF C0              inc         eax000000000000000A: 89 05 00 00 00 00  mov         dword ptr [global_counter],eax0000000000000010: 8B 05 00 00 00 00  mov         eax,dword ptr [global_counter]0000000000000016: D1 E0              shl         eax,10000000000000018: 5F                 pop         rdi0000000000000019: C3                 ret000000000000001A: CC                 int         3000000000000001B: CC                 int         3000000000000001C: CC                 int         3000000000000001D: CC                 int         3000000000000001E: CC                 int         3000000000000001F: CC                 int         3

汇编分析

1. ​​寄存器保存与恢复​

可以看到有一个对应操作push rdi和pop rdi, 该操作是debug编译特有的操作,release编译则会优化掉。它的作用的保存rdi寄存器的值到该函数的栈顶,让这个函数内部可以随意使用rdi寄存器,而不会损坏函数外部的数据.

执行前: RSP = 0x7FFF0000
执行后: RSP = 0x7FFEFFF8
        [0x7FFEFFF8] = RDI原始值

这里出现了RSP寄存器

2. RSP寄存器

在Windows操作系统的x86-64架构中,​​RSP寄存器(Register Stack Pointer)​​ 是核心的栈指针寄存器,用于管理程序运行时的栈内存操作。RSP始终指向当前栈帧的顶部地址(即最新入栈数据的地址)。栈是一种“后进先出”(LIFO)的内存结构,用于存储函数调用时的临时数据(如局部变量、函数参数、返回地址等)。当数据压栈(push)时,RSP值减小;数据出栈(pop)时,RSP值增大,确保栈空间的动态分配与释放

3. 全局变量

  0000000000000002: 8B 05 00 00 00 00  mov         eax,dword ptr [global_counter]

汇编语句中用[]表示一个全局变量名,在链接阶段会转化成全局变量的地址

4. EAX寄存器

EAX(Extended Accumulator Register,扩展累加器寄存器)是x86/x86-64架构中的核心通用寄存器之一,主要用于算术运算、函数返回值存储及系统调用交互。其核心特性与功能如下:

1.  ​​算术运算的缺省寄存器

累加器角色​​:加法(ADD)、乘法(MUL/IMUL)等指令默认使用EAX存储操作数或结果

乘除法协作​​:

  • 32位乘法时,结果的高32位存于​​EDX​​,低32位存于​​EAX​​;
  • 除法中,EAX存放被除数,结果商存于EAX,余数存于EDX

2. ​​函数返回值与系统调用

在Windows/Linux系统调用及函数调用中,EAX通常存储返回值(如API函数执行结果)

3. ​​I/O操作端口寻址​

与​​DX​​寄存器配合,用于指定输入/输出设备的端口地址

这里使用到的是第二种用于存储函数的返回值

5. INT整型变量

  • dword ptr​:指定 32 位操作(int 类型)
  • 00 00 00 00​:地址占位符(链接时填充实际地址)

DWORD PTR 指定了32位操作,即一个整型

6. MOV语句

mov语句mov         eax,dword ptr [global_counter]

即将[global_counter]地址内的取出一个32位值,存放进eax寄存器

7. INC和SHL语句

inc为加1指令,shl为左移指令相当于乘法

8. 二次加载

  000000000000000A: 89 05 00 00 00 00  mov         dword ptr [global_counter],eax
  0000000000000010: 8B 05 00 00 00 00  mov         eax,dword ptr [global_counter]

在汇编中INC和SHL计算中,有一个二次加载的动作,将eax和[global_counter]进行了交换。主要原因是debug模式下的特性,在release当中会被优化掉

  1. 确保内存可见性(多线程场景)
  2. 避免寄存器优化(方便调试)
  3. 内存访问断点支持

9. RET语句

跳出函数

10. 调试特征

  • 末尾的 int 3CC)指令是调试断点,用于填充函数对齐(Debug 模式常见)
  • Release 模式会优化掉冗余的寄存器保存和二次内存访问。

等价转化

通过如上分析将汇编主要做的操作注释如下

no_params_function:0000000000000000: 40 57              push        rdi         ; 保存 RDI 寄存器0000000000000002: 8B 05 00 00 00 00  mov         eax, dword ptr [global_counter]  ; 加载全局变量0000000000000008: FF C0              inc         eax         ; eax 值加 1000000000000000A: 89 05 00 00 00 00  mov         dword ptr [global_counter], eax  ; 存回全局变量0000000000000010: 8B 05 00 00 00 00  mov         eax, dword ptr [global_counter]  ; 重新加载全局变量0000000000000016: D1 E0              shl         eax, 1      ; eax 左移 1 位(相当于乘 2)0000000000000018: 5F                 pop         rdi         ; 恢复 RDI 寄存器0000000000000019: C3                 ret                    ; 返回(返回值在 eax 中)

转化成C语言:

int no_params_function(void){global_counter = global_counter + 1;return global_counter * 2;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词