从汇编的角度看栈
来源:互联网 发布:esxi 6.0 网络配置 编辑:程序博客网 时间:2024/06/11 23:51
大家都知道,栈区是存储函数,局部变量的一块内存区域。
那么让我们从汇编的角度,来看看函数的执行过程。首先,当我们使用pushl将数据入栈时,栈顶会移动,以容纳新增加的值。实际上,我们能不断将值入栈,栈会在内存中保持向下增长,知道存放代码或数据的地方。那么,我们如何知道栈顶地址呢?栈寄存器%esp总是包含一个指向当前栈顶的指针。
在执行函数之前,一个程序将函数的所有参数按逆序压入栈中。接着程序发出一条call指令,表明程序希望开始执行哪一个函数。call指令会去做两件事;首先,它将下一条指令的地址即返回地址压入栈中;然后,修改指令指针(%eip)以指向函数起始处。
参数 N。。。参数2参数1返回地址
现在函数自己也有一些工作。首先通过pushl %ebp指令保存当前基址指针寄存器%ebp。基址指针是一个特殊的寄存器,用于访问函数的参数和局部变量。其次,它会用movl %esp, %ebp。将指针%esp复制到%ebp,这使你能够把函数参数作为相对于基址指针的固定索引进行访问。
在函数开始时将栈指针复制到基址指针寄存器可以让你一直清楚参数的位置(局部变量也是如此),即使在其它数据压入弹出栈的情况下。%ebp将一直是栈指针在函数开始是的位置,所以可以说是对栈帧的常量引用。(栈帧包含一个函数中所使用的所有栈变量,包括参数、局部变量和返回地址。)
参数 N N×4+4(%ebp)。。。 参数2 12(%ebp)参数1 8(%ebp)返回地址 4(%ebp)旧%ebp (%ebp) 和 (%esp) 可以看到,每个参数都可以用%ebp通过基址寻址方式访问。接下来,函数为其所需的所有局部变量保留栈空间,只需将栈指针向外移动即可实现。假设要运行函数,我们需要两个字的内存,只需要将栈指针向下移动两个字即可。
sub $8, %esp
这样,我们久能就爱那个栈用于变量的存储,而不需要担心函数调用引起的入栈会破坏存储的变量。因为函数调用是在栈帧上分配的,而变量仅仅在函数运行期间有效,而当函数返回时,栈帧久不复存在,这些变量也就不存在了。
假如我们有两个字可用于本地存储。那么栈就是如下情况了:
当一个函数执行完毕后,会做三件事。
(1) 将其返回值存储到%eax。
(2) 将栈恢复到调用函数时的状态(移除当前栈帧,并使调用代码的栈帧重新生效)。
(3) 将控制权换给调用它的程序。这是通过ret指令实现的,该指令将栈顶的值弹出,并将指令指针寄存器%eip设置为该弹出值。
因此,要执行如下命令:
movl %ebp, %esp
popl %ebp
ret
现在控制权已经回到,调用函数的那里,你可以检查%eax中的返回值。弹出其入栈的所有参数,将栈指针复位至其原先的位置(如果不需要参数值,按你可以用addl 将“4 *参数个数”加到%esp即可)。
- 从汇编的角度看栈
- 从汇编的角度看段错误
- 从汇编的角度看递归
- 从汇编角度看计算机
- 从汇编、内存的角度看类中的this指针 .
- 从反汇编的角度看C++语法(构造函数)
- 从汇编角度看c++的const实现
- 从汇编角度看c++引用(reference)
- 从反汇编的角度看引用和指针的区别
- 从汇编角度看Linux C函数的调用约定和参数传递的细节
- 从汇编角度看C++类的方法访问类成员的原理
- 从汇编的角度看inline函数与非inline函数
- 从汇编和底层的角度看c和类c语言
- 从汇编角度看英特尔x86函数调用规范
- 从汇编角度看C语言类型转换
- [学习小记] 从汇编角度看局部变量的分配及数组名与指针的关系
- [学习小记] 从汇编角度看局部变量的分配及数组名与指针的关系 .
- 从FrameWork的角度看Creational Pattern
- IT忍者神龟之修改IE地址栏Tomcat 小猫咪图标
- STL源码阅读-iterator
- ROS发展之路 -版本回顾篇
- Hibernate操作数据库的3个准备和七个步骤,以及在SSH框架中Hibernate的配置。
- Mybatis和Ibatis的区别
- 从汇编的角度看栈
- Material Design(一)
- Stacking Boxes - UVa 103 dp
- 100个优秀的loading进度条PSD素材下载
- 《TCP/IP详解卷2:实现》笔记--ICMP:Internet控制报文协议
- 数据库查看内存使用INFORMIX
- Android内存泄漏分析及调试
- PHP超时处理全面总结
- [经验感受] 一点感受