(一) __cdecl: c declaration
C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。C/C++默认的调用方式,可用于函数参数不确定的情况下。
1. 被调用函数代码及反汇编:
int _cdecl fun(int arg){//被调用者 return arg+1; } push ebp mov ebp, esp ¦ ¦ mov esp, ebp pop ebp retn ;被调用者不清除参数 fun endp
2.调用代码及反汇编:
int main(int argc, char* argv[],int _version)//调用者 { int _a=208; _a=fun(_a);//调用 std::cout<<_a<<std::endl; return 0; } var_4= dword ptr -4 ;变量_a的地址偏移量 ¦ ¦ rep stosd mov [ebp+var_4], 0D0h mov eax, [ebp+var_4] push eax ;实参_a压栈 call j_fun ;调用函数fun(_a) add esp, 4 ;调用者main函数清除实参_a,恢复栈
(二) __stdcall: standard calling
参数从右向左通过堆栈传递的, 函数调用在返回前要由被调用者清理堆栈。
1. 被调用函数代码及反汇编:
int __stdcall fun(int arg){//被调用者 return arg+1; } push ebp mov ebp, esp ¦ ¦ mov esp, ebp pop ebp retn 4;被调用者清除参数。对比上述。 fun endp
2.调用代码及反汇编:
int main(int argc, char* argv[],int _version)//调用者 { int _a=208; _a=fun(_a);//调用 std::cout<<_a<<std::endl; return 0; } var_4= dword ptr -4 ;变量_a的地址偏移量 ¦ ¦ rep stosd mov [ebp+var_4], 0D0h mov eax, [ebp+var_4] push eax ;实参_a压栈 call j_fun ;调用函数fun(_a) ;调用者不恢复栈 ¦ ¦