汇编指令push,mov,call,pop,leave,ret建立与释放栈的过程
来源:互联网 发布:广告机发布软件 编辑:程序博客网 时间:2024/06/15 20:14
相比高级语言中的栈结构,在汇编指令层面栈的任务更加复杂—生命周期必须与汇编指令行的切换正确对应。
大图
图片说明:内存地址,汇编指令都为简写,用的十进制,栈空间1个格子大小是4*8=32位(对应32位操作系统),指令行长度都简化为1字节。为了突出建栈与撤栈的过程示意,函数都没有参数。栈空间也简化了,局部变量和参数都没有在其中。 实际执行顺序一列中对汇编指令行作用的进一步解释,左边为寄存器或栈空间地址,右边为其中的值。
寄存器%esp既是栈指针,总是指向最下方第一个空着的栈空间地址。当栈栈指针向上移动后,下方的栈空间就相当于被释放掉了。
%ebp寄存器在此机制中相当重要,它存储着当前函数在栈中所被分配的局部空间的起始地址。在释放栈的过程中,leave指令将会移动栈指针至%ebp存储的内存地址的位置,再反过来将此起始位置中存储的值,既上一层调用函数的起始地址,存到%ebp中,为下一次进一步释放做准备,并进一步向上移动栈指针,为ret命令做准备。在此机制中,当前函数在栈中所被分配的局部空间的起始地址的前一格内存(既是+32bit)中存储的是上一层调用函数指令call的下一行指令的内存位置,leave之后的ret指令将会控制指令行流水线跳到此处。
一些指令的简单说明:
push为入栈命令。
pop为出栈命令。
栈命令都跟伴随栈指针的移动。
mov在此过程中将一个寄存器中的值移到另一个寄存器。
call可以理解为goto。并将它的下一行指令地址存到栈中。
leave为mov+pop。为退出栈机制的重要一环。
ret也可以理解为goto。并移动栈指针。
汇编指令行对应的源码应为:
void main(){ //一些计算 f1(); //继续计算}void f1(){ //一些计算 f2(); //继续计算 return;}void f2(){ //一些计算 return;}
感觉这东西有点烧脑,花了一下午时间终于整个捋顺了整个流程。
想理解好此过程,理解每个指令的作用,必须结合指令行地址,栈地址和寄存器一起来分析,否则很容易被绕晕。
- 汇编指令push,mov,call,pop,leave,ret建立与释放栈的过程
- Push, Pop, call, leave 和 Ret 指令图解
- Push, Pop, call, leave 和 Ret 指令图解
- AT&T汇编指令enter、leave、call、ret
- AT&T汇编enter、leave、call、ret指令
- Call指令与ret指令
- Call指令与ret指令
- 汇编push,pop,call操作
- 汇编--9 call指令和ret指令
- 查找pop pop ret call dword ptr [esp+nn]指令的方法
- 汇编指令jmp call ret 变形
- 汇编学习笔记--CALL和RET指令
- 8086汇编之 CALL 和 RET指令
- 汇编第十节-CALL和RET指令
- ia32中程序调用返回时call.ret.leave的作用和栈变换的说明
- __stdcall 与 __cdecl 区别 (汇编 call ret 时,栈的变化)
- 汇编lea 指令与 mov 指令
- 汇编Lea 指令与 Mov 指令
- 代理模式
- 毫秒转换为天、小时、分、秒
- Eclipse 建立 Java Spring 最简控制台项目
- poj2195Going Home最小费用流
- 从 0 到 1 走进 Kaggle
- 汇编指令push,mov,call,pop,leave,ret建立与释放栈的过程
- Java实现非对称加密
- 虚函数与虚表再探
- 字符串
- eclipse使用maven搭建项目总结
- ★数组和链表的存删查
- C++算法学习——预备知识(3)——类模板
- 使用Scala写第一个Spark程序
- (poj 2480 Longge's problem)<欧拉函数>