深入函数之调用堆栈(学习篇)

每一个程序的执行都使用了栈,没有栈就没有函数,没有局部变量,

栈被定义为一个特殊的容器,用户可以将数据压入栈中(入栈,push),也可以将已经压入的数据弹出(pop,出栈),但栈这个容器必须遵守一条规则“先进后出”,

在操作系统中,栈是动态内存区域,程序可以将数据压入栈中,也可以将数据从栈顶弹出。在i386下,栈顶由称之为esp的寄存器进行定位,

栈在程序运行中具有举足轻重的地位。栈保存了一个函数调用所需要的维护信息,被称之为堆栈帧或活动记录。一般包括如下几个方面的内容:

1.函数的返回地址和参数;

2.临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量;

3.保存的上下文:包括在函数调用前后需要保持不变的寄存器。

在i386中一个函数的活动记录用ebp和esp这两个寄存器划定范围。esp寄存器始终指向栈的顶部,同时也就指向当前函数的活动记录的顶部,而相对的,ebp寄存器指向了函数活动记录的一个固定位置,ebp寄存器又被称之为帧指针。

深入函数之调用堆栈(学习篇)_第1张图片

函数调用堆栈图示过程:

深入函数之调用堆栈(学习篇)_第2张图片

由main函数开始执行,通过edp调用a和b的值返回temp;

1.main函数调用完sum,需要返回main函数;sum资源还在,main函数执行完之后,资源返回给操作系统,由操作系统释放)

2.返回后,继续从调用sum的下一句开始执行。

我们可以看一下程序的sum函数反汇编;

深入函数之调用堆栈(学习篇)_第3张图片

从图上我们可以看到:{}符号也有专门的汇编语言;temp值由eax寄存器存储并返回到main函数中区。

还有一个问题:函数的返回值是怎么带出来的

1.小于四个字节的,由eax寄存器带出;

2.大于四个字节小于八个字节,采用eax和edx寄存器带出来;

3.大于八个字节,push三次参数,a,b,临时量地址(还可以是res的地址);由临时对象带出;

博主推荐大家可以看一下《程序员的自我修养,链接装载与库》这本书的第十章节内存,里面有详细讲解函数调用堆栈过程;

你可能感兴趣的:(深入函数之调用堆栈(学习篇))