main函数调用子函数堆栈解析

main函数调用子函数堆栈解析

ID:10591014

大小:33.32 KB

页数:5页

时间:2018-07-07

main函数调用子函数堆栈解析_第1页
main函数调用子函数堆栈解析_第2页
main函数调用子函数堆栈解析_第3页
main函数调用子函数堆栈解析_第4页
main函数调用子函数堆栈解析_第5页
资源描述:

《main函数调用子函数堆栈解析》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库

1、·任何一个程序通常都包括代码段和数据段,这些代码和数据本身都是静态的。程序要想运行,首先要由操作系统负责为其创建进程,并在进程的虚拟地址空间中为其代码段和数据段建立映射。光有代码段和数据段是不够的,进程在运行过程中还要有其动态环境,其中最重要的就是堆栈。图3所示为Linux下进程的地址空间布局:图3Linux下进程地址空间的布局 首先,execve(2)会负责为进程代码段和数据段建立映射,真正将代码段和数据段的内容读入内存是由系统的缺页异常处理程序按需完成的。另外,execve(2)还会将bss段清零,这就

2、是为什么未赋初值的全局变量以及static变量其初值为零的原因。进程用户空间的最高位置是用来存放程序运行时的命令行参数及环境变量的,在这段地址空间的下方和bss段的上方还留有一个很大的空洞,而作为进程动态运行环境的堆栈和堆就栖身其中,其中堆栈向下伸展,堆向上伸展。知道了堆栈在进程地址空间中的位置,我们再来看一看堆栈中都存放了什么。相信读者对C语言中的函数这样的概念都已经很熟悉了,实际上堆栈中存放的就是与每个函数对应的堆栈帧。当函数调用发生时,新的堆栈帧被压入堆栈;当函数返回时,相应的堆栈帧从堆栈中弹出。典型

3、的堆栈帧结构如图4所示。堆栈帧的顶部为函数的实参,下面是函数的返回地址以及前一个堆栈帧的指针,最下面是分配给函数的局部变量使用的空间。一个堆栈帧通常都有两个指针,其中一个称为堆栈帧指针,另一个称为栈顶指针。前者所指向的位置是固定的,而后者所指向的位置在函数的运行过程中可变。因此,在函数中访问实参和局部变量时都是以堆栈帧指针为基址,再加上一个偏移。对照图4可知,实参的偏移为正,局部变量的偏移为负。图4典型的堆栈帧结构 介绍了堆栈帧的结构,我们再来看一下在Inteli386体系结构上堆栈帧是如何实现的。图5和图

4、6分别是一个简单的C程序及其编译后生成的汇编程序。图5一个简单的C程序example1.cintfunction(inta,intb,intc){    charbuffer[14];    int  sum;    sum=a+b+c;    returnsum;}voidmain(){    int  i;    i=function(1,2,3);}图6example1.c编译后生成的汇编程序example1.s1  .file "example1.c"2  .version  "01.01"3gcc

5、2_compiled.:4.text5  .align46.globlfunction7  .type  function,@function8function:9  pushl%ebp10  movl%esp,%ebp11  subl$20,%esp12  movl8(%ebp),%eax13  addl12(%ebp),%eax14  movl16(%ebp),%edx15  addl%eax,%edx16  movl%edx,-20(%ebp)17  movl-20(%ebp),%eax18  jmp

6、.L119  .align420.L1:21  leave22  ret23.Lfe1:24  .size  function,.Lfe1-function25  .align426.globlmain27  .type  main,@function28main:29  pushl%ebp30movl%esp,%ebp31  subl$4,%esp32  pushl$333  pushl$234  pushl$135  callfunction36  addl$12,%esp37  movl%eax,%e

7、ax38  movl%eax,-4(%ebp)39.L2:40  leave41  ret42.Lfe2:43  .size  main,.Lfe2-main44  .ident "GCC:(GNU)2.7.2.3"这里我们着重关心一下与函数function对应的堆栈帧形成和销毁的过程。从图5中可以看到,function是在main中被调用的,三个实参的值分别为1、2、3。由于C语言中函数传参遵循反向压栈顺序,所以在图6中32至34行三个实参从右向左依次被压入堆栈。接下来35行的call指令除了将控制转移到

8、function之外,还要将call的下一条指令addl的地址,也就是function函数的返回地址压入堆栈。下面就进入function函数了,首先在第9行将main函数的堆栈帧指针ebp保存在堆栈中并在第10行将当前的栈顶指针esp保存在堆栈帧指针ebp中,最后在第11行为function函数的局部变量buffer[14]和sum在堆栈中分配空间。至此,函数function的堆栈帧就构建完成了,其结构如图7所示

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。