【代码真相】之 函数调用方式 __cdecl & __stdcall
1. __cdecl C和C++缺省调用方式
实参的压栈顺序是从右到左,最后由主调函数进行堆栈恢复。由于主调用函数管理堆栈,所以可以实现变参函数。
示例:
void Input(int &m,int &n){}
int a =1, b=2;
Input(a,b);
Disassembly是这样的:
Input(a,b);
004114EC lea eax,[b] //将b的地址传给eax
004114EF push eax //这两行完成参数b入栈 其实是地址入栈
004114F0 lea ecx,[a] //将c的地址传给ecx
004114F3 push ecx //这两行完成参数a入栈 其实是地址入栈
004114F4 call Input (4111E5h) //调用Input函数
004114F9 add esp,8 //恢复栈
思考:如果写成void Input(int m, int n){}是什么样的呢?
Input(a,b);
004114EC mov eax,dword ptr [b] //将2入栈
004114EF push eax
004114F0 mov ecx,dword ptr [a]
004114F3 push ecx
004114F4 call Input (4111EAh)
004114F9 add esp,8
知道传值和传引用传地址的区别了吧。
2. __stdcall CALLBACK
实参的压栈顺序是从右到左,调用返回时,堆栈由被调函数调整。
Input(a,b);
004114EC lea eax,[b]
004114EF push eax
004114F0 lea ecx,[a]
004114F3 push ecx
004114F4 call Input (4111FEh)
可以看出来,在调用函数Input之后,没有相应的堆栈恢复工作