呼び出し規約について

引数の渡し規則と名前付け規則 に説明がある。
引数の渡し方、呼び出し側 (caller)、呼び出され側 (callee) のどちらが Stack Cleanup を行うか書いてある。以下のコードで確認してみる。

int func (int arg1, int arg2)
{
	return arg1 + arg2;
}

int __stdcall func_stdcall (int arg1, int arg2)
{
	return arg1 + arg2;
}

int __cdecl func_cdecl (int arg1, int arg2)
{
	return arg1 + arg2;
}

int __fastcall func_fastcall (int arg1, int arg2)
{
	return arg1 + arg2;
}

int main (int argc, char * argv [])
{
	int arg1 = 1;
	int arg2 = 2;
	int rslt = 0;
	
	rslt = func (arg1, arg2);
	rslt = func_stdcall (arg1, arg2);
	rslt = func_cdecl (arg1, arg2);
	rslt = func_fastcall (arg1, arg2);
		
	return 0;
}

結果

0:000> uf main!main
main!main:
   22 00321090 55              push    ebp
   22 00321091 8bec            mov     ebp,esp
   22 00321093 83ec0c          sub     esp,0Ch
   23 00321096 c745f401000000  mov     dword ptr [ebp-0Ch],1
   24 0032109d c745fc02000000  mov     dword ptr [ebp-4],2
   25 003210a4 c745f800000000  mov     dword ptr [ebp-8],0
   27 003210ab 8b45fc          mov     eax,dword ptr [ebp-4]
   27 003210ae 50              push    eax
   27 003210af 8b4df4          mov     ecx,dword ptr [ebp-0Ch]
   27 003210b2 51              push    ecx
   27 003210b3 e84dffffff      call    main!ILT+0(?funcYAHHHZ) (00321005)
   27 003210b8 83c408          add     esp,8
   27 003210bb 8945f8          mov     dword ptr [ebp-8],eax
   28 003210be 8b55fc          mov     edx,dword ptr [ebp-4]
   28 003210c1 52              push    edx
   28 003210c2 8b45f4          mov     eax,dword ptr [ebp-0Ch]
   28 003210c5 50              push    eax
   28 003210c6 e83fffffff      call    main!ILT+5(?func_stdcallYGHHHZ) (0032100a)
   28 003210cb 8945f8          mov     dword ptr [ebp-8],eax
   29 003210ce 8b4dfc          mov     ecx,dword ptr [ebp-4]
   29 003210d1 51              push    ecx
   29 003210d2 8b55f4          mov     edx,dword ptr [ebp-0Ch]
   29 003210d5 52              push    edx
   29 003210d6 e839ffffff      call    main!ILT+15(?func_cdeclYAHHHZ) (00321014)
   29 003210db 83c408          add     esp,8
   29 003210de 8945f8          mov     dword ptr [ebp-8],eax
   30 003210e1 8b55fc          mov     edx,dword ptr [ebp-4]
   30 003210e4 8b4df4          mov     ecx,dword ptr [ebp-0Ch]
   30 003210e7 e82dffffff      call    main!ILT+20(?func_fastcallYIHHHZ) (00321019)
   30 003210ec 8945f8          mov     dword ptr [ebp-8],eax
   32 003210ef 33c0            xor     eax,eax
   33 003210f1 8be5            mov     esp,ebp
   33 003210f3 5d              pop     ebp
   33 003210f4 c3              ret
0:000> uf main!func
main!func:
    2 00321040 55              push    ebp
    2 00321041 8bec            mov     ebp,esp
    3 00321043 8b4508          mov     eax,dword ptr [ebp+8]
    3 00321046 03450c          add     eax,dword ptr [ebp+0Ch]
    4 00321049 5d              pop     ebp
    4 0032104a c3              ret
0:000> uf main!func_stdcall
main!func_stdcall:
    7 00321050 55              push    ebp
    7 00321051 8bec            mov     ebp,esp
    8 00321053 8b4508          mov     eax,dword ptr [ebp+8]
    8 00321056 03450c          add     eax,dword ptr [ebp+0Ch]
    9 00321059 5d              pop     ebp
    9 0032105a c20800          ret     8
0:000> uf main!func_cdecl
main!func_cdecl:
   12 00321060 55              push    ebp
   12 00321061 8bec            mov     ebp,esp
   13 00321063 8b4508          mov     eax,dword ptr [ebp+8]
   13 00321066 03450c          add     eax,dword ptr [ebp+0Ch]
   14 00321069 5d              pop     ebp
   14 0032106a c3              ret
0:000> uf main!func_fastcall
main!func_fastcall:
   17 00321070 55              push    ebp
   17 00321071 8bec            mov     ebp,esp
   17 00321073 83ec08          sub     esp,8
   17 00321076 8955f8          mov     dword ptr [ebp-8],edx
   17 00321079 894dfc          mov     dword ptr [ebp-4],ecx
   18 0032107c 8b45fc          mov     eax,dword ptr [ebp-4]
   18 0032107f 0345f8          add     eax,dword ptr [ebp-8]
   19 00321082 8be5            mov     esp,ebp
   19 00321084 5d              pop     ebp
   19 00321085 c3              ret

func と func_decl では、caller が add esp,8 で 8 バイト分スタック ポインタを戻しているのがわかる。
一方、func_stdcall では callee が ret 8 で 8 バイト分スタック ポインタを戻している。
また、func_fastcall では、今回のケースでは引数の受け渡しにスタックは使用されず、edx と ecx レジスタが使われているようだ。