1. 几种约定
调用约定 参数压栈顺序 平衡堆栈
__cdecl 从右至左入栈 调用者清理
__stdcall 从右至左入栈 自身清理堆栈
__fastcall ECX/EDX 传递前2个参数 自身清理堆栈
剩下的:从右至左入栈
2. 举例
#include <stdio.h>
int add(int x, int y)
{
return x + y;
}
int main()
{
int z = add(1, 2);
return 0;
}
1: #include <stdio.h>
2:
3: int add(int x, int y)
4: {
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,40h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 lea edi,[ebp-40h]
0040102C mov ecx,10h
00401031 mov eax,0CCCCCCCCh
00401036 rep stos dword ptr [edi]
5: return x + y;
00401038 mov eax,dword ptr [ebp+8]
0040103B add eax,dword ptr [ebp+0Ch]
6: }
0040103E pop edi
0040103F pop esi
00401040 pop ebx
00401041 mov esp,ebp
00401043 pop ebp
00401044 ret
8: int main()
9: {
0040D400 push ebp
0040D401 mov ebp,esp
0040D403 sub esp,44h
0040D406 push ebx
0040D407 push esi
0040D408 push edi
0040D409 lea edi,[ebp-44h]
0040D40C mov ecx,11h
0040D411 mov eax,0CCCCCCCCh
0040D416 rep stos dword ptr [edi]
10: int z = add(1, 2);
0040D418 push 2
0040D41A push 1
0040D41C call @ILT+5(add) (0040100a)
0040D421 add esp,8
0040D424 mov dword ptr [ebp-4],eax
11: return 0;
0040D427 xor eax,eax
12: }
0040D429 pop edi
0040D42A pop esi
0040D42B pop ebx
0040D42C add esp,44h
0040D42F cmp ebp,esp
0040D431 call __chkesp (0040d680)
0040D436 mov esp,ebp
0040D438 pop ebp
0040D439 ret
3. 改变调用约定 __stdcall
#include <stdio.h>
int __stdcall add(int x, int y)
{
return x + y;
}
int main()
{
int z = add(1, 2);
return 0;
}
3: int __stdcall add(int x, int y)
4: {
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,40h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 lea edi,[ebp-40h]
0040102C mov ecx,10h
00401031 mov eax,0CCCCCCCCh
00401036 rep stos dword ptr [edi]
5: return x + y;
00401038 mov eax,dword ptr [ebp+8]
0040103B add eax,dword ptr [ebp+0Ch]
6: }
0040103E pop edi
0040103F pop esi
00401040 pop ebx
00401041 mov esp,ebp
00401043 pop ebp
00401044 ret 8
7:
8: int main()
9: {
00401050 push ebp
00401051 mov ebp,esp
00401053 sub esp,44h
00401056 push ebx
00401057 push esi
00401058 push edi
00401059 lea edi,[ebp-44h]
0040105C mov ecx,11h
00401061 mov eax,0CCCCCCCCh
00401066 rep stos dword ptr [edi]
10: int z = add(1, 2);
00401068 push 2
0040106A push 1
0040106C call @ILT+10(add) (0040100f)
00401071 mov dword ptr [ebp-4],eax
11: return 0;
00401074 xor eax,eax
12: }
00401076 pop edi
00401077 pop esi
00401078 pop ebx
00401079 add esp,44h
0040107C cmp ebp,esp
0040107E call __chkesp (004010a0)
00401083 mov esp,ebp
00401085 pop ebp
00401086 ret
4. 改变调用约定 __fastcall
#include <stdio.h>
int __fastcall add(int x, int y)
{
return x + y;
}
int main()
{
int z = add(1, 2);
return 0;
}
3: int __fastcall add(int x, int y)
4: {
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,48h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 push ecx
0040102A lea edi,[ebp-48h]
0040102D mov ecx,12h
00401032 mov eax,0CCCCCCCCh
00401037 rep stos dword ptr [edi]
00401039 pop ecx
0040103A mov dword ptr [ebp-8],edx
0040103D mov dword ptr [ebp-4],ecx
5: return x + y;
00401040 mov eax,dword ptr [ebp-4]
00401043 add eax,dword ptr [ebp-8]
6: }
00401046 pop edi
00401047 pop esi
00401048 pop ebx
00401049 mov esp,ebp
0040104B pop ebp
0040104C ret
7:
8: int main()
9: {
00401050 push ebp
00401051 mov ebp,esp
00401053 sub esp,44h
00401056 push ebx
00401057 push esi
00401058 push edi
00401059 lea edi,[ebp-44h]
0040105C mov ecx,11h
00401061 mov eax,0CCCCCCCCh
00401066 rep stos dword ptr [edi]
10: int z = add(1, 2);
00401068 mov edx,2
0040106D mov ecx,1
00401072 call @ILT+15(add) (00401014)
00401077 mov dword ptr [ebp-4],eax
11: return 0;
0040107A xor eax,eax
12: }
0040107C pop edi
0040107D pop esi
0040107E pop ebx
0040107F add esp,44h
00401082 cmp ebp,esp
00401084 call __chkesp (004010a0)
00401089 mov esp,ebp
0040108B pop ebp
0040108C ret