汇编基础
过程
如何在汇编语言中定义一个过程?编写一个"函数"?
堆栈操作
Q:运行时堆栈与抽象数据类型有什么不同?
A:运行时堆栈是内存数组,CPU用ESP寄存器对其进行直接管理,该寄存器被称为堆栈指针寄存器,在32位模式下,ESP及寄存器存放的是堆栈中某个位置的32位偏移量。ESP基本不会被程序员控制,它用的是CALL,POP,PUSH,RET等指令进行修改。
Q:32位模式中哪个寄存器管理堆栈?如何管理?
K:ESP,顺便一提,EIP寄存器为指令指针寄存器
A:ESP(extended stack pointer),32位入栈操作是:先把栈顶指针减4,再将数值复制到栈顶指针指向的堆栈的位置,所有,该栈是“向下”生长的,从高地址向低地址扩展
Q:(判断)过程中的局部变量是在堆栈中新建的
A:T
K:
堆栈的应用
- 当寄存器用于多个目的时,堆栈可以作为寄存器的一个方便的临时保存区域。在寄存器被修改后还能保存其初始值
- 执行CALL指令时,CPU在堆栈中保存了当前过程的返回值
- 调用过程时,输入数值(参数),通过其压栈实现参数传递
- 堆栈也为过程局部变量提供了临时存储区域
PUSH & POP
- PUSH指令就是压栈操作,首先减少堆栈指针,然后复制源操作数,POP首先把ESP指向的内容复制到寄存器或者变量,然后增加ESP的值
- PUSHAD把32位通用寄存器都压入栈,POPAD指令把堆栈中的数据弹出到32位通用寄存器
- PUSHA则是把16位通用寄存器压入栈,POPA指令把堆栈中的数据弹出到16位通用寄存器
- PUSHFD指令将32位EFLAGS寄存器压入栈,POPFD弹出,PUSHF和POPF对应16位
1 | .386 |
定义并使用过程
Q:(判断) PROC伪指令标识过程的开始,ENDP伪指令标识过程的结束
A:T
K:所有的程序都需要含有一个main过程,当在程序之外创建一个过程时,就用RET指令来结束它。RET强制CPU返回到被调用的位置
Q:(判断)CALL指令把自身指令的偏移量压入栈
A:F
K:
CALL指令调用一个过程,指挥处理器从新的内存地址开始执行,使用RET指令将处理器转回到被调用过程的程序点上。从物理上来说,CALL将其返回地址(运行的下一行)压入堆栈,再把被调用的过程的地址给EIP,RET从堆栈把返回地址弹回EIP。
当存在过程嵌套时,每次调用CALL就会把下一行位置压栈,然后遇见一个RET就弹出一个,直到返回main
例子:求和数组
1 | .386 |
- 过程中的push和pop可以省略,在PROC后加上 USES esi, ecx,可以让汇编器自己生成
链接到外部库
Q: (判断)链接库由汇编语言源代码组成
A:F
K:链接库是一种文件,包含了已经汇编为机器代码的过程。链接库开始时是一个或多个源文件,这些文件再被汇编为目标文件。目标文件插入到一个特殊格式文件,该文件由链接器工具识别。
Q:在一个外部链接库中,用PROTO伪指令声明过程MyProc并调用
A:
Myproc proto
call Myproc
- 当程序进行汇编时,汇编器不指定call的地址,链接器在链接库中寻找Myproc,并把库中适当的机器指令复制到程序可执行文件中,同时给call一个地址
- .dll文件(dynamic link library)
写在后面
在对应实验的博客中,我们会使用Irvine32链接库,再更往后的内容中,我们会学习如何实现库的功能
我就是鸽子精,咕咕咕