函数的调用过程——栈帧

首先,插入一段代码:

#include

 

int myadd(int x,int y)

{

 int z=x+y;

 return z;

}

int main()

{

 int a = 0xaaaaaaaa;

 int b = 0xbbbbbbbb;

 int c = myadd(a,b);

 printf("you should runhere!:%d\n");

 return 0;

}

VC6.0下运行该程序;

函数的调用过程——栈帧_第1张图片

转换成汇编语言:

函数的调用过程——栈帧_第2张图片

做一些概念的说明:

通用寄存器:EAX、EBX、ECX、EDX……

EIP(PC):程序计数器(保存正在执行指令的下一条指令地址)

ESP:栈顶

EBP:栈底

及一些汇编语言的含义:

mov   将数据放置区域

push:入栈

pop:出栈

add:两者相加

sub:相减

call:1.保存当前汇编指令的下一条指令地址(入栈保存),目的是为了恢复;

         2.跳转至目标函数的入口处(修改EIP)(jmp)

ret:1.将当前保存的函数的返回值的地址出栈;将弹出的数据修改EIP;

        2.常规的临时变量通过寄存器返回,从而将结果拿回。

 

对a、b进行入栈;

函数的调用过程——栈帧_第3张图片


将b的值放在EAX中;


将a的值放在ECX中;

函数的调用过程——栈帧_第4张图片

函数的调用过程——栈帧_第5张图片

形参实例化顺序:从右至左(先b后a);


执行call命令:

函数的调用过程——栈帧_第6张图片

将下一条指令的地址00401093存入0018FEE4中(小端);

并跳转至myadd函数;


修改EIP:

函数的调用过程——栈帧_第7张图片

跳转至myadd函数:


开始执行myadd函数:


函数的调用过程——栈帧_第8张图片

此时,EBP、ESP指向同一位置。

接下来执行 sub     ESP,44h;

函数的调用过程——栈帧_第9张图片

此时,蓝色框中形成栈帧结构,供myadd函数使用;EIP中存放的为myadd函数的地址。

函数的调用过程——栈帧_第10张图片

把a的值放在EAX里,再将a+b的值放在EAX里。

函数的调用过程——栈帧_第11张图片

然后:


将EBP弹出,ESP上移;

函数的调用过程——栈帧_第12张图片

此时,栈帧结构释放,执行ret;

函数的调用过程——栈帧_第13张图片

EIP变为00401093,回到了下一条指令的地址。

再执行add   esp,8;

函数的调用过程——栈帧_第14张图片

过程调用结束,临时变量被释放。

返回值通过EAX寄存器返回。

函数调用结束。

你可能感兴趣的:(函数的调用过程——栈帧)