- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
栈:?在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。?
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。?
当发生函数调用的时候,栈空间中存放的数据是这样的:1、调用者函数把被调函数所需要的参数按照与被调函数的形参顺序相反的顺序压入栈中,即:从右向左依次把被调函数所需要的参数压入栈;2、调用者函数使用call指令调用被调函数,并把call指令的下一条指令的地址当成返回地址压入栈中(这个压栈操作隐含在call指令中);3、在被调函数中,被调函数会先保存调用者函数的栈底地址(push ebp),然后再保存调用者函数的栈顶地址,即:当前被调函数的栈底地址(mov ebp,esp);4、在被调函数中,从ebp的位置处开始存放被调函数中的局部变量和临时变量,并且这些变量的地址按照定义时的顺序依次减小,即:这些变量的地址是按照栈的延伸方向排列的,先定义的变量先入栈,后定义的变量后入栈;所以,发生函数调用时,入栈的顺序为:参数N参数N-1参数N-2.....参数3参数2参数1函数返回地址上一层调用函数的EBP/BP局部变量1局部变量2....局部变量N函数调用栈如下图所示:
解释:首 先,将调用者函数的EBP入栈(push ebp),然后将调用者函数的栈顶指针ESP赋值给被调函数的EBP(作为被调函数的栈底,mov ebp,esp),此时,EBP寄存器处于一个非常重要的位置,该寄存器中存放着一个地址(原EBP入栈后的栈顶),以该地址为基准,向上(栈底方向)能 获取返回地址、参数值,向下(栈顶方向)能获取函数的局部变量值,而该地址处又存放着上一层函数调用时的EBP值;一般而言,SS: [ebp+4]处为被调函数的返回地址,SS:[EBP+8]处为传递给被调函数的第一个参数(最后一个入栈的参数,此处假设其占用4字节内存)的 值,SS:[EBP-4]处为被调函数中的第一个局部变量,SS:[EBP]处为上一层EBP值;由于EBP中的地址处总是上一层函数调用时的EBP 值,而在每一层函数调用中,都能通过当时的EBP值向上(栈底方向)能获取返回地址、参数值,向下(栈顶方向)能获取被调函数的局部变量值;如此递归,就形成了函数调用栈;函数内局部变量布局示例:#include stdio.h#include string.hstruct C{? int a;? int b;? int c;};int test2(int x, int y, int z){? printf(hello,test2\n);? return 0;}int test(int x, int y, int z){? int a = 1;? int b = 2;? int c = 3;? struct C st;? printf(addr x = %u\n,(unsigned int)(x));? printf(addr y = %u\n,(unsigned int)(y));? printf(addr z = %u\n,(unsigned int)(z));? printf(addr a = %u\n,(unsigned int)(a));? printf(addr b = %u\n,(unsigned int)(b));? printf(addr c = %u\n,(unsigned int)(c));? printf(addr st = %u\n,(unsigned int)(st));? printf(addr st.a = %u\n,(unsigned int)(st.a));? printf(addr st.b = %u\n,(unsigned int)(st.b));? printf(addr st.c = %u\n,(unsigned int)(st.c));? return 0;}
int main(int argc, char** argv){? int x = 1;? int y = 2;? int z = 3;? test(x,y,z);? printf(x = %d; y = %d; z = %d;\n, x,y,z);? memset(y, 0, 8);? printf(x = %d; y = %d; z = %d;\n, x,y,z);? return 0;}打印输出如下:addr
文档评论(0)