汇编语言使用USES运算符注意事项
在《USES运算符》一节中列出了在过程开始保存、结尾恢复的寄存器名。汇编器自动为每个列出的寄存器生成相应的 PUSH 和 POP 指令。
但是必须注意的是:如果过程用常数偏移量访问其堆栈参数,比如 [ebp+8],那么声明该过程时不能使用 USES 运算符。现在举例说明其原因。下面的 MySub1 过程用 USES 运算符保存和恢复 ECX 和 EDX:
假设在使用 USES 的同时还使用了堆栈参数,如 MySub2 过程所示,该参数预期保存的堆栈地址为 EBP+8:
则 MASM 为 MySub2 生成的相应代码如下:
由于汇编器在过程开头插入了 ECX 和 EDX 的 PUSH 指令,使得堆栈参数的偏移量发生变化,从而导致结果错误。
下图说明了为什么堆栈参数现在必须以[EBP+16]来引用。USES 在保存 EBP 之前修改了堆栈,破坏了子程序常用的标准开始代码。
提示:前面介绍了 PROC 伪指令声明堆栈参数的高级语法。在那种情况下,USES 运算符不会带来问题。
但是必须注意的是:如果过程用常数偏移量访问其堆栈参数,比如 [ebp+8],那么声明该过程时不能使用 USES 运算符。现在举例说明其原因。下面的 MySub1 过程用 USES 运算符保存和恢复 ECX 和 EDX:
MySub1 PROC USES ecx edx
ret
MySub1 ENDP
- push ecx
- push edx
- pop edx
- pop ecx
- ret
- MySub2 PROC USES ecx edx
- push ebp ;保存基址指针
- mov ebp, esp ;堆栈帧基址
- mov eax, [ebp+8] ;取堆栈参数
- pop ebp ;恢复基址指针
- ret 4 ;清除堆栈
- MySub2 ENDP
- push ecx
- push edx
- push ebp
- mov ebp,esp
- mov eax, dword ptr [ebp+8] ;错误地址!
- pop ebp
- pop edx
- pop ecx
- ret 4
下图说明了为什么堆栈参数现在必须以[EBP+16]来引用。USES 在保存 EBP 之前修改了堆栈,破坏了子程序常用的标准开始代码。

提示:前面介绍了 PROC 伪指令声明堆栈参数的高级语法。在那种情况下,USES 运算符不会带来问题。
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算