#include "stdafx.h"
int _cdecl test1(int a,int b,int c)
{
return a+b;
}
int _stdcall test2(int a,int b,int c)
{
return a+b;
}
int _fastcall test3(int a,int b,int c)
{
return a+b;
}
int _tmain(_In_ int _Argc,char* _In_reads_)
{
test1(1,2,3);
test2(1,2,3);
test3(1,2,3);
getchar();
return 0;
}
进入反汇编查看 _cdecl 特点
test1(1,2,3);
002414DE 6A 03 push 3 //自右向左压入参数
002414E0 6A 02 push 2
002414E2 6A 01 push 1
002414E4 E8 E3 FC FF FF call test1 (02411CCh)
002414E9 83 C4 0C add esp,0Ch //在函数返回后平衡堆栈
_cdecl 是外平栈 自右向左压入参数
_stdcall的特点
test2(1,2,3);
002414EC 6A 03 push 3
002414EE 6A 02 push 2
002414F0 6A 01 push 1
002414F2 E8 9A FB FF FF call test2 (0241091h)
进入 call test2 (0241091h)
0241430 55 push ebp
00241431 8B EC mov ebp,esp
00241433 81 EC C0 00 00 00 sub esp,0C0h
00241439 53 push ebx
0024143A 56 push esi
0024143B 57 push edi
0024143C 8D BD 40 FF FF FF lea edi,[ebp-0C0h]
00241442 B9 30 00 00 00 mov ecx,30h
00241447 B8 CC CC CC CC mov eax,0CCCCCCCCh
0024144C F3 AB rep stos dword ptr es:[edi]
12: return a+b;
0024144E 8B 45 08 mov eax,dword ptr [a]
12: return a+b;
00241451 03 45 0C add eax,dword ptr [b]
13: }
00241454 5F pop edi
00241455 5E pop esi
00241456 5B pop ebx
00241457 8B E5 mov esp,ebp
00241459 5D pop ebp
0024145A C2 0C 00 ret 0Ch //在这里平栈
_stdcall的特点 参数自右向左压入栈内 内平衡堆栈
_fastcall的特点
002414F7 6A 03 push 3
002414F9 BA 02 00 00 00 mov edx,2 //使用了两个寄存器压入参数
002414FE B9 01 00 00 00 mov ecx,1
00241503 E8 6F FC FF FF call test3 (0241177h)
进入 call test3 (0241177h)
00241470 55 push ebp
00241471 8B EC mov ebp,esp
00241473 81 EC D8 00 00 00 sub esp,0D8h
00241479 53 push ebx
0024147A 56 push esi
0024147B 57 push edi
0024147C 51 push ecx
0024147D 8D BD 28 FF FF FF lea edi,[ebp-0D8h]
00241483 B9 36 00 00 00 mov ecx,36h
00241488 B8 CC CC CC CC mov eax,0CCCCCCCCh
0024148D F3 AB rep stos dword ptr es:[edi]
0024148F 59 pop ecx //这里使用ecx传进来的值
00241490 89 55 EC mov dword ptr [b],edx
00241493 89 4D F8 mov dword ptr [a],ecx
17: return a+b;
00241496 8B 45 F8 mov eax,dword ptr [a]
00241499 03 45 EC add eax,dword ptr [b]
18: }
0024149C 5F pop edi
0024149D 5E pop esi
0024149E 5B pop ebx
0024149F 8B E5 mov esp,ebp
002414A1 5D pop ebp
002414A2 C2 04 00 ret 4 //这里平衡堆栈只有4个字节 另外两个参数使用的寄存器不需要平衡
_fastcall的特点 参数自右向左压入堆栈 使用内平栈 当参数少于3个时,使用了两个寄存器直接传值
对比三种调用约定的特点 当发现是外平栈的时候,可以用 add esp,0Ch 这一句判断函数参数的个数为3个
_stdcall _fastcall 这两种调用约定的函数参数个数判断则要看是否使用了寄存器传参数,在函数里面看有没有寄存器是直接使用的 然后加上ret的值 就可以判断函数的参数个数