做内容网站赚钱吗,黄冈论坛东部社区,技术支持 东莞网站建设母婴护理,自己怎么建设手机网站首页【0】写在前面
过程#xff08;栈帧结构是干货#xff09;#xff1b;本文总结于csapp#xff0c; 加上自己的理解#xff1b;【1】栈帧结构
每个函数的每次调用#xff0c;都有它自己独立的一个栈帧#xff0c;这个栈帧中维持着所需要的各种信息。
过程调用#xf…【0】写在前面
过程栈帧结构是干货本文总结于csapp 加上自己的理解【1】栈帧结构
每个函数的每次调用都有它自己独立的一个栈帧这个栈帧中维持着所需要的各种信息。
过程调用函数调用另一个词语表示叫作过程
IA32 程序 用程序栈 来支持过程调用
【2】转移控制
此处非常重要关系到对函数调用和返回理解是否到位 解说显然是地址80483dc的call调用sum函数 call指令的效果是将返回地址0x080483e1压入栈中再跳转到sum函数的第一条指令0x0804394直到遇到ret指令为止即是说ret指令是一个函数的结束标志 call push ip ; jmp near ptr 标号压栈后跳转 ret pop ip出栈
【3】寄存器使用惯例
惯例——我们必须保证当一个过程调用者调用另一个过程被调用者时
被调用者不会覆盖某个调用者稍后会使用的寄存器的值。寄存器%eax %edx 和 %ecx 被划分为调用者保存寄存器。意思就是左边3个寄存器实现覆盖时需要保存到调用者的栈帧结构中寄存器%ebx, %esi 和 edi 被划分为被调用者保存寄存器。意思就是左边3个寄存器实现覆盖时需要保存到被调用者的栈帧结构中
看个荔枝
int P(int x)
{int y x * x;int z Q(y);return y z;
}过程P在调用Q之前计算y 但它必须保证y的值在Q返回后是可用的。有两个方法可以实现
1Q调用之前将y的值保存到调用者P的栈帧结构中当Q返回时过程P从栈中取出y的值2将y保存在被调用者Q所保存的寄存器中如%ebx等3个寄存器如果Q或者其他的程序要使用这个寄存器的话先把该寄存器的值压入栈帧中并在返回前恢复该值因为每个函数或过程都有栈帧结构谁要使用保存y的寄存器谁就把y保存在其对应的栈帧中
【4】过程实例
函数A调用函数B有三个过程其实上述的转移控制的解说已经说的很清楚了
1建立部分初始化栈帧把call指令的下一条指令的地址压入栈帧结构2主体部分执行过程的实际计算执行被调用函数或者过程3结束部分恢复栈的状态以及过程返回将call指令的下一条指令的地址出栈到ip 或者叫做程序计数器pc
我的观点 -干货
1说说%ebp
它其实是%esp的一个副本作用在于记录每个执行函数或过程的栈帧结构的首地址注意是每个函数或过程如函数A调用函数B 函数B的汇编代码的第一句就要把函数A的栈帧首地址压入栈以便函数B结束标志ret指令执行前的一条指令将其调用者——函数A的栈帧首地址弹回到%ebp参看上上图中的swap_add的汇编指令接近尾部部分
为什么GCC分配从不使用的空间
GCC 坚持一个X86编程指导方针也就是一个函数使用的所有栈空间必须是16字节的整数倍采用这个规则是为了保证访问数据的严格对齐。
再来看一个荔枝 执行时%esp0x800040, 而%ebp0x800060 scanf返回后 的栈帧图结构 如下 干货-这里又是一个——很好的解释了C语言中的传值和传址的问题
为什么分配的栈帧空间中还有没有被使用的 这个问题你不要问我了自己多思考答案就在附近哈哈。 【5】递归过程
先看个荔枝对于理解递归运算过程——至关重要 干货-这里 你也可以看到 对于参数n它是存储在调用者的栈帧结构中的从而解释了为什么取用参数的时候都是%ebp8Bingo