- 函数参数的代入
- 参数代入顺序:参数入栈的顺序是从右向左入栈的。
- <=8字节的参数代入:push入栈的方式将参数传递
- >8字节的参数代入:先在main函数的栈顶向上移动12字节,然后将参数的数据拷贝到main函数栈顶开辟的内存。
- 函数栈帧的开辟
int fun1(int a,int b)
{
return 0;
}
int main()
{
int a = 10;
int b = 20;
int c = fun1(10,20);
return 0;
}
第一步进行函数参数入栈,如图:
第二步进行函数栈帧的开辟
- 先将调用方的栈底地址入栈
- 让ebp=esp
- Esp - 栈帧大小
- 将栈帧内存写入0xcccccccc
函数栈帧开辟流程:
- 函数返回值返回
1、<=8字节的返回值带出:利用寄存器带回,然后将寄存器的值写入到接收返回值的变量中
2、>8字节的返回值带出:
- 参数入栈之后入main栈帧上的地址
- 将返回值写入到main栈帧的地址上
- 将地址写入到eax寄存器
- 从eax寄存器中的的地址中取出值写入到接收返回值的变量
- 函数栈帧的回退
函数栈帧的回退分为两步,第一步是函数栈帧的回退,第二步是函数参数的清除。
- 先将寄存器pop
- Esp=ebp
- Pop main栈底地址 -----》ebp
- Ret
- Esp+8
函数栈帧回退汇编码如下:
- 调用约定
- _cdecl c标准调用约定
- _stdcall window标准调用约定
- _fastcall 快速调用约定
- _thiscall 类成员方法的调用约定