我们写一个比较简单的c语言程序
`#include“
int fun(int x,int y)
{
int c = 0xcccccccc;
printf(“hehe\n”);
return c;
}
int main()
{
int a = 0xaaaaaaaa;
int b = 0xbbbbbbbb;
int c = fun(a,b);
printf(“haha\n”);
system(“pause”);
return 0;
}
“`
不过并不是探讨这个c语言程序运行的结构,而是探讨一下函数调用中栈帧结构的变化,我们用反汇编来做这项工作,主要观察其中的内存处理
直接进行到函数调用,将b的值赋给寄存器eax,将a的值赋给寄存器ecx,然后按顺序压栈,并call指令调用_fun的地址,这个地址保存的是jump到fun函数的地址,并在栈中保存
跳转到fun函数内部
首先,将ebp压栈,并将esp的位置赋给ebp,即esp成为新的ebp,然后给esp往下减去0CC个地址,也就是创建fun的栈帧结构随即将ebx,esi,edi压栈,因为程序函数的调用在这里与c变量无关,我们便不考虑c。这时候的栈帧图:
随后,进行fun函数中的程序,接下来我们直接进行返回的部分
首先pop出edi,esi,ebx,然后esp加上0CC使得esp回到原来的位置,将esp与ebp进行比较,并判断esp是否有误,然后将ebp的地址赋给esp,pop出ebp:
最终通过之前call指令保存下的地址返回main函数内部
将esp的地址加8,回到main函数原来的栈帧结构
这就是函数调用中栈帧结构的变化,其中pc指针和esp,ebp起着至关重要的作用,这一方面的运用还是很稚嫩的,还需要好好学习和理解。