每一个程序的执行都使用了栈,没有栈就没有函数,没有局部变量,
栈被定义为一个特殊的容器,用户可以将数据压入栈中(入栈,push),也可以将已经压入的数据弹出(pop,出栈),但栈这个容器必须遵守一条规则“先进后出”,
在操作系统中,栈是动态内存区域,程序可以将数据压入栈中,也可以将数据从栈顶弹出。在i386下,栈顶由称之为esp的寄存器进行定位,
栈在程序运行中具有举足轻重的地位。栈保存了一个函数调用所需要的维护信息,被称之为堆栈帧或活动记录。一般包括如下几个方面的内容:
1.函数的返回地址和参数;
2.临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量;
3.保存的上下文:包括在函数调用前后需要保持不变的寄存器。
在i386中一个函数的活动记录用ebp和esp这两个寄存器划定范围。esp寄存器始终指向栈的顶部,同时也就指向当前函数的活动记录的顶部,而相对的,ebp寄存器指向了函数活动记录的一个固定位置,ebp寄存器又被称之为帧指针。
函数调用堆栈图示过程:
由main函数开始执行,通过edp调用a和b的值返回temp;
1.main函数调用完sum,需要返回main函数;(sum资源还在,main函数执行完之后,资源返回给操作系统,由操作系统释放)
2.返回后,继续从调用sum的下一句开始执行。
我们可以看一下程序的sum函数反汇编;
从图上我们可以看到:{}符号也有专门的汇编语言;temp值由eax寄存器存储并返回到main函数中区。
还有一个问题:函数的返回值是怎么带出来的?
1.小于四个字节的,由eax寄存器带出;
2.大于四个字节小于八个字节,采用eax和edx寄存器带出来;
3.大于八个字节,push三次参数,a,b,临时量地址(还可以是res的地址);由临时对象带出;
博主推荐大家可以看一下《程序员的自我修养,链接装载与库》这本书的第十章节内存,里面有详细讲解函数调用堆栈过程;