函数调用约定
..
参数传递顺序
1.从右到左依次入栈:__stdcall,__cdecl,__thiscall,__fastcall
2.从左到右依次入栈:__pascal
主要说明__stdcall 和 __cdecl 区别
1…__stdcall 被调用的 函数本身负责堆栈平衡
2…__cdecl 调用函数 者负责 该函数的 堆栈平衡
///////********************** __stdcall 函数本身负责堆栈平衡 *********************////////////////
int __stdcall a(int v1,int xx) { return 5; } int main() { int t=a(5,1); return 0; } /**/ --- c:\users\hekun\desktop\cppp\cppp\源.cpp ------------------------------------- int __stdcall a(int v1,int xx) { 001713C0 push ebp 001713C1 mov ebp,esp 001713C3 sub esp,0C0h 001713C9 push ebx 001713CA push esi 001713CB push edi 001713CC lea edi,[ebp-0C0h] 001713D2 mov ecx,30h 001713D7 mov eax,0CCCCCCCCh 001713DC rep stos dword ptr es:[edi] return 5; 001713DE mov eax,5 } 001713E3 pop edi 001713E4 pop esi 001713E5 pop ebx 001713E6 mov esp,ebp 001713E8 pop ebp 001713E9 ret 8 /*堆栈平衡 函数参数占用8字节*/ --- c:\users\hekun\desktop\cppp\cppp\源.cpp ------------------------------------- int main() { 00171400 push ebp 00171401 mov ebp,esp 00171403 sub esp,0CCh 00171409 push ebx 0017140A push esi 0017140B push edi 0017140C lea edi,[ebp-0CCh] 00171412 mov ecx,33h 00171417 mov eax,0CCCCCCCCh 0017141C rep stos dword ptr es:[edi] int t=a(5,1); 0017141E push 1 00171420 push 5 00171422 call a (01711E0h) /* 调用函数a*/ 00171427 mov dword ptr [t],eax /*返回值位于寄存器eax*/ return 0; 0017142A xor eax,eax } 0017142C pop edi 0017142D pop esi 0017142E pop ebx 0017142F add esp,0CCh 00171435 cmp ebp,esp 00171437 call __RTC_CheckEsp (017113Bh) 0017143C mov esp,ebp 0017143E pop ebp 0017143F ret
///////********************** __cdecl 调用函数者 负责堆栈平衡 *********************////////////////
int __cdecl a(int v1,int xx) { return 5; } int main() { int t=a(5,1); return 0; } /* 反汇编 */ --- c:\users\hekun\desktop\cppp\cppp\源.cpp ------------------------------------- int __cdecl a(int v1,int xx) { 00F313C0 push ebp 00F313C1 mov ebp,esp 00F313C3 sub esp,0C0h 00F313C9 push ebx 00F313CA push esi 00F313CB push edi 00F313CC lea edi,[ebp-0C0h] 00F313D2 mov ecx,30h 00F313D7 mov eax,0CCCCCCCCh 00F313DC rep stos dword ptr es:[edi] return 5; 00F313DE mov eax,5 } 00F313E3 pop edi 00F313E4 pop esi 00F313E5 pop ebx 00F313E6 mov esp,ebp 00F313E8 pop ebp 00F313E9 ret --- c:\users\hekun\desktop\cppp\cppp\源.cpp ------------------------------------- int main() { 00F31400 push ebp 00F31401 mov ebp,esp 00F31403 sub esp,0CCh 00F31409 push ebx 00F3140A push esi 00F3140B push edi 00F3140C lea edi,[ebp-0CCh] 00F31412 mov ecx,33h 00F31417 mov eax,0CCCCCCCCh 00F3141C rep stos dword ptr es:[edi] int t=a(5,1); 00F3141E push 1 00F31420 push 5 00F31422 call a (0F311E5h) /* 调用函数 a */ 00F31427 add esp,8 /* 由于是 __cdecl 调用方式 所以调用者 main 负责堆栈平衡,函数a 返回后 立即堆栈平衡(占用8字节) 变参函数只能是这种调用,因为只有调用者才知道 参数实际大小*/ 00F3142A mov dword ptr [t],eax return 0; 00F3142D xor eax,eax } 00F3142F pop edi 00F31430 pop esi 00F31431 pop ebx 00F31432 add esp,0CCh 00F31438 cmp ebp,esp 00F3143A call __RTC_CheckEsp (0F3113Bh) 00F3143F mov esp,ebp 00F31441 pop ebp 00F31442 ret
__fastcall 调用 前参数 最大8字节 一次放入寄存器 ecx和edx 其余参数 放入栈中