文档介绍:在C语言中函数调用方式的区别
在使用VC进行函数定义时,通常会指定该函数调用方式,那么在C语言中函数调用方式有什么区别呢?
通常在使用VC进行函数定义时会指定该函数调用方式,诸如:
int __stdcall max r,12h
00401121 mov eax,0CCCCCCCCh
00401126 rep stos dword ptr
41: int s,i;
42:
43: while 00401128 mov eax,1
0040112D test eax,eax
0040112F je Input+0C1h 44:
45: printf 0040113A call printf 0040113F add esp,4
46: scanf 0040114B call scanf 00401150 add esp,8
47:
48: if 004011B3 mov eax,dword ptr
004011B6 mov ecx,dword ptr
004011B8 cmp ecx,dword ptr
004011BB jl Input+0AFh 57: break;
004011BD jmp Input+0C1h 58: else
59: printf 004011C4 call printf 004011C9 add esp,4
60:
004011CC jmp Input+18h 61:
62:
004011D1 pop edi
004011D2 pop esi
004011D3 pop ebx
004011D4 add esp,48h
004011D7 cmp ebp,esp
004011D9 call __chkesp 004011DE mov esp,ebp
004011E0 pop ebp
004011E1 ret 8
之后,我们看到在函数末尾部分,有ret 8,明显是恢复堆栈,由于在32位C++中,变量地址为4个字节(int也为4个字节),所以弹栈两个地址即8个字节。由此可以看出:在主调用函数中负责压栈,在被调用函数中负责恢复堆栈。因此不能实现变参函数,因为被调函数不能事先知道弹栈数量,但在主调函数中是可以做到的,因为参数数量由主调函数确定。
下面再看一下,ebp-8和ebp-4这两个地址实际存储的是什么值,ebp-8地址存储的是n 的值,ebp -4存储的是m的值。说明也是从右到左压栈,进行参数传递。
总结:_stdcall在主调用函数中负责压栈,在被调用函数中负责弹出堆栈中的参数,并且负责恢复堆栈。因此不能实现变参函数,参数传递是从右到左。另外,命名修饰方法是在函数前加一个下划线(_),在函数名后有符号(@),在@后面紧跟参数列表中的参数所占字节数(10进制),如:void Input(int &m,int &n),被修饰成:_******@8 对于大多数api函数以及窗口消息处理函数皆用CALLBACK,所以调用前,主调函数会先压栈,然后api函数自己恢复堆栈。
如