函数的调用及栈帧的创建和销毁
来源:互联网 发布:nba2k16库里数据 编辑:程序博客网 时间:2024/05/22 03:09
实例代码为:环境为vc++6.0
为了研究函数过程调用,我们先来了解几个寄存器,esp:堆栈指针寄存器,指向栈顶。ebp:基址寄存器,指向栈底。
eip/ip/pc:程序计数器。程序计数器保存的内容永远是当前正在执行指令的下一条指令的地址。
call:在调用函数的时候用。 1.通过修改eip来实现函数的跳转(jmp跳转)。
2.将当前正在执行指令的下一条指令的地址保存起来,以便返回。
ret:将当前的栈顶的位置(返回值地址)返回到main函数里。在返回的时候要保证现在的内容写在ip里。
#include<stdio.h>
int myfunction(int x,int y)
{
int z=x+y;
return z;
}
int main()
{
int a=0xaaaaaaaa;
int b=0xbbbbbbbb;
int c=myfunction(a,b);
printf("you should run here!ret=%d\n",c);
return 0;
}
一.调用栈
首先我们通过打开call stack(调用堆栈)可以看出一个程序在运行的时候第一个执行的函数不是main函数,从这张图可以看出main函数是由mainCRTstartup()所调用,main函数虽然不是第一个被调用的函数,但main函数却是应用逻辑中的入口函数.所谓栈,是一种先进后出的数据结构,每一次的函数调用都是一个过程,在这个过程中要开辟一段栈空间,用于保存过程中的临时变量,现场保护,这段栈空间我们称为函数栈帧。
这张图清楚的展示了c程序的内存空间,栈通常是在用户空间的最高地址处分配,而堆通常位于栈的下方。对于栈而言,先入栈的低至高,后入栈的地址低,stack向下生长,即地址从大到小,而堆heap正好相反。
二.利用call调用myfunction函数
函数在形参实例化的顺序是从右到左的,从右到左的进行压栈。
三.执行后释放函数空间返回调用主函数
此时eip的内容变为00401093,即call的下一条指令的地址。
此时调用myfunction函数之后,和在调用myfunction函数之前是一样的,函数调用过程中调用的变量叫做临时变量,在当前调用函数的栈帧的栈顶结构处。函数调用调用之后的函数之中的变量以及栈帧结构都被释放掉,所以函数的临时变量具有临时性。每调用一个函数就是形成一个栈帧结构的过程,返回之后释放。函数返回通过寄存器返回。
- 函数的调用及栈帧的创建和销毁
- 函数的调用及栈帧的创建和销毁
- 函数的调用过程,栈帧的创建和销毁
- 函数的调用过程,栈帧的创建和销毁。
- 函数的调用,栈帧的创建和销毁
- 浅谈函数的调用,栈帧的创建和销毁
- 函数的调用过程,栈帧的创建和销毁
- 函数的调用(栈帧的创建和销毁)
- 函数的调用过程,栈帧的创建和销毁。
- 函数的调用过程,栈帧的创建和销毁
- 函数的调用过程,栈帧的创建和销毁
- 函数调用过程,栈帧的创建和销毁
- 函数调用过程,栈帧的创建和销毁
- 函数的调用过程,栈桢的创建和销毁
- 函数的调用过程,栈桢的创建和销毁。
- 函数的调用过程、栈帧的创建以及销毁
- 函数的调用过程,栈帧的创建与销毁
- 浅谈函数的调用和栈帧的创建和销毁
- cookis的工具类
- 程序员的思考:一年管理成富翁,三年市场路路通,十年技术一场空
- 相对定位,绝对定位,固定定位
- 随笔
- JVM调优总结(四)-垃圾回收面临的问题
- 函数的调用及栈帧的创建和销毁
- php ssl生成密钥和证书
- JVM调优总结(五)-分代垃圾回收详述1
- java回调
- 类
- fetchRow的DB_FETCHMODE_ASSOC参数
- Python基础入门之Dict和Set类型一
- JVM调优总结(六)-分代垃圾回收详述2
- 11月06日解题报告