32位下_stdcall, _fastcall, _cdecl
#include <windows.h> int _stdcall Func1(int a, int b, int c, int d) { return a+b+c+d; } int _fastcall Func2(int a, int b, int c, int d) { return a+b+c+d; } int _cdecl Func3(int a, int b, int c, int d) { return a + b + c + d; } double _stdcall Func4(double a, double b, double c, double d) { return a + b + c + d; } double _fastcall Func5(double a, double b, double c, double d) { return a + b + c + d; } double _cdecl Func6(double a, double b, double c, double d) { return a + b + c + d; } int _stdcall Func7(int a, double b, int c, double d) { return a + b + c + d; } int _fastcall Func8(int a, double b, int c, double d) { return a + b + c + d; } int _cdecl Func9(int a, double b, int c, double d) { return a + b + c + d; } int pascal Func10(int a, int b, int c, int d) //似乎#define pascal __stdcall 不过pascal也太古老了 { return a + b + c + d; } int main() { Func1(1,2,3,4); Func2(5,6,7,8); Func3(2,2,3,4); Func4(1.0, 2.0, 3.0, 4.0); Func5(1.0, 2.0, 3.0, 4.0); Func6(1.0, 2.0, 3.0, 4.0); Func7(1, 2.0, 3, 4.0); Func8(1, 2.0, 3, 4.0); Func9(1, 2.0, 3, 4.0); Func10(1, 2, 3, 4); return 0; } /* 0101178E 6A 04 push 4 01011790 6A 03 push 3 01011792 6A 02 push 2 01011794 6A 01 push 1 01011796 E8 BF F8 FF FF call Func1 (0101105Ah) 0101179B 6A 08 push 8 0101179D 6A 07 push 7 0101179F BA 06 00 00 00 mov edx,6 010117A4 B9 05 00 00 00 mov ecx,5 010117A9 E8 57 F8 FF FF call Func2 (01011005h) 010117AE 6A 04 push 4 010117B0 6A 03 push 3 010117B2 6A 02 push 2 010117B4 6A 02 push 2 010117B6 E8 E3 FA FF FF call Func3 (0101129Eh) 010117BB 83 C4 10 add esp,10h */ /* Func4 sub esp,8 00F64221 movsd xmm0,mmword ptr [__real@4010000000000000 (0F66BE8h)] 00F64229 movsd mmword ptr [esp],xmm0 00F6422E sub esp,8 00F64231 movsd xmm0,mmword ptr [__real@4008000000000000 (0F66BE0h)] 00F64239 movsd mmword ptr [esp],xmm0 00F6423E sub esp,8 00F64241 movsd xmm0,mmword ptr [__real@4000000000000000 (0F66BD8h)] 00F64249 movsd mmword ptr [esp],xmm0 00F6424E sub esp,8 00F64251 movsd xmm0,mmword ptr [__real@3ff0000000000000 (0F66BD0h)] 00F64259 movsd mmword ptr [esp],xmm0 00F6425E call Func4 (0F6134Dh) 00F64263 fstp st(0) */ /* Func5 011F4D55 83 EC 08 sub esp,8 011F4D58 F2 0F 10 05 E8 6B 1F 01 movsd xmm0,mmword ptr [__real@4010000000000000 (011F6BE8h)] 011F4D60 F2 0F 11 04 24 movsd mmword ptr [esp],xmm0 011F4D65 83 EC 08 sub esp,8 011F4D68 F2 0F 10 05 E0 6B 1F 01 movsd xmm0,mmword ptr [__real@4008000000000000 (011F6BE0h)] 011F4D70 F2 0F 11 04 24 movsd mmword ptr [esp],xmm0 011F4D75 83 EC 08 sub esp,8 011F4D78 F2 0F 10 05 D8 6B 1F 01 movsd xmm0,mmword ptr [__real@4000000000000000 (011F6BD8h)] 011F4D80 F2 0F 11 04 24 movsd mmword ptr [esp],xmm0 011F4D85 83 EC 08 sub esp,8 011F4D88 F2 0F 10 05 D0 6B 1F 01 movsd xmm0,mmword ptr [__real@3ff0000000000000 (011F6BD0h)] 011F4D90 F2 0F 11 04 24 movsd mmword ptr [esp],xmm0 011F4D95 E8 B8 C5 FF FF call Func5 (011F1352h) 011F4D9A DD D8 fstp st(0) */ /* Func6 01214DEC 83 EC 08 sub esp,8 01214DEF F2 0F 10 05 E8 6B 21 01 movsd xmm0,mmword ptr [__real@4010000000000000 (01216BE8h)] 01214DF7 F2 0F 11 04 24 movsd mmword ptr [esp],xmm0 01214DFC 83 EC 08 sub esp,8 01214DFF F2 0F 10 05 E0 6B 21 01 movsd xmm0,mmword ptr [__real@4008000000000000 (01216BE0h)] 01214E07 F2 0F 11 04 24 movsd mmword ptr [esp],xmm0 01214E0C 83 EC 08 sub esp,8 01214E0F F2 0F 10 05 D8 6B 21 01 movsd xmm0,mmword ptr [__real@4000000000000000 (01216BD8h)] 01214E17 F2 0F 11 04 24 movsd mmword ptr [esp],xmm0 01214E1C 83 EC 08 sub esp,8 01214E1F F2 0F 10 05 D0 6B 21 01 movsd xmm0,mmword ptr [__real@3ff0000000000000 (01216BD0h)] 01214E27 F2 0F 11 04 24 movsd mmword ptr [esp],xmm0 01214E2C E8 26 C5 FF FF call Func6 (01211357h) 01214E31 DD D8 fstp st(0) 01214E33 83 C4 20 add esp,20h */ //结果发现浮点型的参数全部都是弄到栈里传参的 /* Func7 01234E86 sub esp,8 01234E89 movsd xmm0,mmword ptr [__real@4010000000000000 (01236BE8h)] 01234E91 movsd mmword ptr [esp],xmm0 01234E96 push 3 01234E98 sub esp,8 01234E9B movsd xmm0,mmword ptr [__real@4000000000000000 (01236BD8h)] 01234EA3 movsd mmword ptr [esp],xmm0 01234EA8 push 1 01234EAA call Func7 (0123135Ch) */ /* Func8 00834EFF sub esp,8 00834F02 movsd xmm0,mmword ptr [__real@4010000000000000 (0836BE8h)] 00834F0A movsd mmword ptr [esp],xmm0 00834F0F sub esp,8 00834F12 movsd xmm0,mmword ptr [__real@4000000000000000 (0836BD8h)] 00834F1A movsd mmword ptr [esp],xmm0 00834F1F mov edx,3 00834F24 mov ecx,1 00834F29 call Func8 (0831361h) */ //大发现 /* Func9 00834F2E sub esp,8 00834F31 movsd xmm0,mmword ptr [__real@4010000000000000 (0836BE8h)] 00834F39 movsd mmword ptr [esp],xmm0 00834F3E push 3 00834F40 sub esp,8 00834F43 movsd xmm0,mmword ptr [__real@4000000000000000 (0836BD8h)] 00834F4B movsd mmword ptr [esp],xmm0 00834F50 push 1 00834F52 call Func9 (0831366h) 00834F57 add esp,18h */
64位下,没什么约定
#include <windows.h> int Func1(int a, int b, int c, int d) { return a + b + c + d; } double Func2(double a, double b, double c, double d) { return a + b + c + d; } int Func3(int a, double b, int c, double d) { return a + b + c + d; } int Func4(int a, int b, int c, int d, int e, int f) { return a + b + c + d + e + f; } int Func5(int a, int b, int c, int d, double e, double f) { return a + b + c + d + e + f; } int Func6(int a, int b, int c, int d, double e, int f, double g, int h) { return a + b + c + d + e + f + g + h; } int main() { int a = Func1(1, 2, 3, 4); double b = Func2(1.0, 2.0, 3.0, 4.0); int c = Func3(1, 2.0, 3, 4.0); int d = Func4(1, 2, 3, 4, 5, 6); int e = Func5(1, 2, 3, 4, 5.0, 6.0); int f = Func6(1, 2, 3, 4, 5.0, 6, 7.0, 8); return 0; } /*Func1 00007FF7AF04170E mov r9d,4 00007FF7AF041714 mov r8d,3 00007FF7AF04171A mov edx,2 00007FF7AF04171F mov ecx,1 00007FF7AF041724 call Func1 (07FF7AF0410B9h) 00007FF7AF041729 mov dword ptr [a],eax */ /*Func2 00007FF7F7723C7C movsd xmm3,mmword ptr [__real@4010000000000000 (07FF7F7729C88h)] 00007FF7F7723C84 movsd xmm2,mmword ptr [__real@4008000000000000 (07FF7F7729C50h)] 00007FF7F7723C8C movsd xmm1,mmword ptr [__real@4000000000000000 (07FF7F7729C30h)] 00007FF7F7723C94 movsd xmm0,mmword ptr [__real@3ff0000000000000 (07FF7F7729BD8h)] 00007FF7F7723C9C call Func2 (07FF7F7721343h) 00007FF7F7723CA1 movsd mmword ptr [b],xmm0 */ /*Func3 movsd xmm3,mmword ptr [__real@4010000000000000 (07FF7103D9C30h)] 00007FF7103D3624 mov r8d,3 00007FF7103D362A movsd xmm1,mmword ptr [__real@4000000000000000 (07FF7103D9BD8h)] 00007FF7103D3632 mov ecx,1 00007FF7103D3637 call Func3 (07FF7103D133Eh)
浮点参数和整型参数是一起计数的
意味着每列中,只能取一个
rcx rdx r8 r9
xmm0 xmm1 xmm2 xmm3
*/
/*Func4 00007FF6F96848C9 mov dword ptr [rsp+28h],6 00007FF6F96848D1 mov dword ptr [rsp+20h],5 00007FF6F96848D9 mov r9d,4 00007FF6F96848DF mov r8d,3 00007FF6F96848E5 mov edx,2 00007FF6F96848EA mov ecx,1 00007FF6F96848EF call Func4 (07FF6F968134Dh) 00007FF6F96848F4 mov dword ptr [d],eax */ /*Func5 00007FF7364E5307 movsd xmm0,mmword ptr [__real@4018000000000000 (07FF7364E9D78h)] 00007FF7364E530F movsd mmword ptr [rsp+28h],xmm0 00007FF7364E5315 movsd xmm0,mmword ptr [__real@4014000000000000 (07FF7364E9CB0h)] 00007FF7364E531D movsd mmword ptr [rsp+20h],xmm0 00007FF7364E5323 mov r9d,4 00007FF7364E5329 mov r8d,3 00007FF7364E532F mov edx,2 00007FF7364E5334 mov ecx,1 00007FF7364E5339 call Func5 (07FF7364E1352h) 00007FF7364E533E mov dword ptr [e],eax */ /*Func6 00007FF7519C53D4 mov dword ptr [rsp+38h],8 00007FF7519C53DC movsd xmm0,mmword ptr [__real@401c000000000000 (07FF7519C9D80h)] 00007FF7519C53E4 movsd mmword ptr [rsp+30h],xmm0 00007FF7519C53EA mov dword ptr [rsp+28h],6 00007FF7519C53F2 movsd xmm0,mmword ptr [__real@4014000000000000 (07FF7519C9CB0h)] 00007FF7519C53FA movsd mmword ptr [rsp+20h],xmm0 00007FF7519C5400 mov r9d,4 00007FF7519C5406 mov r8d,3 00007FF7519C540C mov edx,2 00007FF7519C5411 mov ecx,1 00007FF7519C5416 call Func6 (07FF7519C1357h) 00007FF7519C541B mov dword ptr [f],eax */ //这样应该是全部的情况了
补充,类成员函数
class thiscall { public: static int test(int a, int b, int c, int d) { return a + b + c + d; } int test2(int a, int b, int c, int d) { return a + b + c + d; } int _stdcall test3(int a, int b, int c, int d) { return a + b + c + d; } int _cdecl test4(int a, int b, int c, int d) { return a + b + c + d; } }; int main() { thiscall obj; int a = thiscall::test(1, 2, 3, 4); int b = obj.test2(2, 3, 4, 5); int c = obj.test3(3, 4, 5, 6); int d = obj.test4(5, 6, 7, 8); return 0; } //test的 //008D1748 push 4 //008D174A push 3 //008D174C push 2 //008D174E push 1 //008D1750 call thiscall::test(08D1226h) 这似乎是 _cdecl 不是_stdcall ,后者是callee来平衡堆栈的 //008D1755 add esp, 10h //test2的 //008D175B push 5 //008D175D push 4 //008D175F push 3 //008D1761 push 2 //008D1763 lea ecx, [obj] //008D1766 call thiscall::test2(08D1082h) //test3的 //00AE464E push 6 //00AE4650 push 5 //00AE4652 push 4 //00AE4654 push 3 //00AE4656 lea eax, [obj] //00AE4659 push eax //00AE465A call thiscall::test3(0AE1348h) //test4的 //003A4D12 push 8 //003A4D14 push 7 //003A4D16 push 6 //003A4D18 push 5 //003A4D1A lea eax, [obj] //003A4D1D push eax //003A4D1E call thiscall::test4(03A134Dh) //003A4D23 add esp, 14h //x64下 //test //00007FF6280918DF mov r9d, 4 //00007FF6280918E5 mov r8d, 3 //00007FF6280918EB mov edx, 2 //00007FF6280918F0 mov ecx, 1 //00007FF6280918F5 call thiscall::test(07FF628091221h) //00007FF6280918FA mov dword ptr[a], eax //test2 //00007FF6280918FD mov dword ptr[rsp + 20h], 5 //00007FF628091905 mov r9d, 4 //00007FF62809190B mov r8d, 3 //00007FF628091911 mov edx, 2 //00007FF628091916 lea rcx, [obj] //00007FF62809191A call thiscall::test2(07FF628091339h) //00007FF62809191F mov dword ptr[b], eax //test3 //00007FF628091922 mov dword ptr[rsp + 20h], 6 //00007FF62809192A mov r9d, 5 //00007FF628091930 mov r8d, 4 //00007FF628091936 mov edx, 3 //00007FF62809193B lea rcx, [obj] //00007FF62809193F call thiscall::test3(07FF628091087h) //00007FF628091944 mov dword ptr[c], eax //test4 //00007FF628091947 mov dword ptr[rsp + 20h], 8 //00007FF62809194F mov r9d, 7 //00007FF628091955 mov r8d, 6 //00007FF62809195B mov edx, 5 //00007FF628091960 lea rcx, [obj] //00007FF628091964 call thiscall::test4(07FF62809133Eh) //00007FF628091969 mov dword ptr[d], eax //显然各种调用约定都被无视了,static不需要传对象,其他都一样.