当发生函数调用的时候,栈空间中存放的数据是这样的:
1、调用者函数把被调函数所需要的参数按照与被调用函数的形参顺序相反的顺序压入栈中,即:从右向左依次把被调函数所需的参数压入栈中;
2、调用者函数使用call指令调用被调函数,并把call指令的下一条指令的地址当成返回地址压入栈中(这个压栈操作隐含在call指令中);
3、在被调函数中,被调函数会先保存调用者函数的栈底地址(push ebp)(从高内地址-》低内地址),然后再保存调用者函数的栈顶地址,
即:当前被调函数的栈底地址(mov ebp,esp);
4、在被调函数中,从ebp的位置处开始存放被调函数中的局部变量和临时变量,并且这些变量的地址按照定义时的顺序依次减小,即:这些变量的地址是按照栈的延伸方向排列的,先定义的变量入栈,后定义的变量后入栈;
首先,将调用者函数的ebp入栈,然后将调用者函数的栈顶指针esp赋值给被调用函数的ebp,此时,ebp寄存器处于一个非常重要的位置,该寄存器中存放着一个地址。
以该地址为基准,向上(栈底方向)能获取返回地址、参数值,向下(栈顶方向)能获取函数的局部变量值,而该地址又存放着上一层函数调用时的ebp。
一般而言,[ebp+4]处为被调用函数的返回地址,
[ebp+8]处为传递给被调函数的第一个参数(最后一个入栈的参数,此处假设其占用4字节内存)的值,
[ebp-4]处为被调函数中的第一个局部变量,
[ebp]处为上一层ebp值。
而在每一层函数调用中,都能通过当时的ebp值向上获取返回地址、参数值,向下获取被调函数的局部变量值。