汇编语言:基于x86处理器考前笔记 | 第八章 高级过程
2025/1/19 0:44:16
来源:https://blog.csdn.net/everfoot/article/details/145216941
浏览:
次
关键词:汇编语言:基于x86处理器考前笔记 | 第八章 高级过程
一、参数传递方式
- 寄存器传参数
- 将参数值复制到寄存器,但存在缺点,可能无法恢复寄存器,导致代码混乱,使系统无法正常运行。例如在一些操作中,若未正确恢复寄存器值,后续程序执行可能出错。
- 如代码中常见的先保存寄存器值(如 push ebx、push ecx 等),在子程序调用结束后再恢复(pop esi、pop ecx、pop ebx 等)操作就是为了避免此问题。
- 堆栈传参数
- 在调用子程序前将参数压入堆栈。有值传递(如 push val2、push val1 后 call AddTwo)和引用传递(如 push OFFSET val2、push OFFSET val1 后 call Swap)两种方式。
- 优点是相对灵活,能传递较多参数且不依赖特定寄存器。但需注意堆栈平衡,子程序返回时要清除堆栈,否则会导致内存泄露和堆栈破坏。如在一些示例中,若不清理堆栈,后续程序获取参数或执行其他操作时会出现错误。
二、堆栈帧
- 创建步骤
- 被传递的实际参数(如有)压入堆栈。
- 子程序调用时,其返回值压入堆栈。
- 子程序开始执行时,EBP(扩展帧指针寄存器)压入堆栈。
- 设置 EBP 等于 ESP,确立基址。
- 若有局部变量,修改 ESP 为变量留空间。
- 如有其他寄存器要保存,压入堆栈。
- 访问堆栈里的参数:通过 EBP 加上偏移量(堆栈中一个存储 4 字节)来访问,如在 AddTwo 子程序中,
mov eax,[ebp + 12]
获取第二个参数,add eax,[ebp + 8]
获取第一个参数。
三、调用规范
- 32 位调用规范
- c 语言调用协议:适用于 Unix、Windows。在 Example1 中,call AddTwo 后通过
add esp,8
来清除堆栈,恢复堆栈指针。 - STDCALL 调用协议:用于调用 Windows API 函数协议。在 AddTwo 中,
ret 8
可清除堆栈,确保堆栈平衡。
- 本书事例:多采用 STDCALL 调用协议。
四、寄存器保存与恢复及局部变量处理
- 寄存器保存与恢复:在子程序中,如 MySub PROC 中,先
push ebp、push ecx、push edx
保存相关寄存器,在子程序结束前 pop edx、pop ecx、pop ebp
恢复寄存器,且这种操作不会影响参数与 ESP 的位移量。
- 局部变量处理:在 MySub 等子程序中,通过 sub esp,8 为局部变量预留空间,如创建局部变量
DWORD PTR [ebp - 4],10
(值 10 存储到[ebp - 4]的内存地址)和 DWORD PTR [ebp - 8],20
,最后通过 mov esp,ebp
和 pop ebp
来删除局部变量并恢复堆栈。