Calling Convention | Argument Passing | Stack Maintenance | Name Decoration (C only) | Notes |
__cdecl | Right to left. | Calling function pops arguments from the stack. | Underscore prefixed to function names. Ex: _Foo. | |
__stdcall | Right to left. | Called function pops its own arguments from the stack. | Underscore prefixed to function name, @ appended followed by the number of decimal bytes in the argument list. Ex: _Foo@10. | |
__fastcall | First two DWORD arguments are passed in ECX and EDX, the rest are passed right to left. | Called function pops its own arguments from the stack. | A @ is prefixed to the name, @ appended followed by the number of decimal bytes in the argument list. Ex: @Foo@10. | Only applies to Intel CPUs. This is the default calling convention for Borland compilers. |
thiscall | this pointer put in ECX, arguments passed right to left. | Calling function pops arguments from the stack. | None. | Used automatically by C++ code. |
naked | Right to left. | Calling function pops arguments from the stack. | None. | Only used by VxDs. |
Figure 2 Calling Convention Declarations
1: /*----------------------------------------------------------------------
2: MSJ Bugslayer - June '98 - John Robbins
3: ------------------------------------------------------------------------
4:
5: This sample demonstrates how the different calling convention
6: declarations are set up.
7:
8: ----------------------------------------------------------------------*/
9:
10: // The strings passed to each function.
11: static char * g_szStdCall = "__stdcall" ;
12: static char * g_szCdeclCall = "__cdecl" ;
13: static char * g_szFastCall = "__fastcall" ;
14: static char * g_szNakedCall = "__naked" ;
15:
16: // The extern "C" turns off all C++ name decoration.
17: extern "C"
18: {
19:
20: // The __cdecl function.
21: void CDeclFunction ( char * szString ,
22: unsigned long ulLong ,
23: char chChar ) ;
24:
25: // The __stdcall function.
26: void __stdcall StdCallFunction ( char * szString ,
27: unsigned long ulLong ,
28: char chChar ) ;
29: // The __fastcall function.
30: void __fastcall FastCallFunction ( char * szString ,
31: unsigned long ulLong ,
32: char chChar ) ;
33:
34: // The naked function. The declspec goes on the definition, not the
35: // declaration.
36: int NakedCallFunction ( char * szString ,
37: unsigned long ulLong ,
38: char chChar ) ;
39: }
40:
41: void main ( void )
42: {
00401000 55 push ebp
00401001 8B EC mov ebp,esp
00401003 53 push ebx
00401004 56 push esi
00401005 57 push edi
43: // Call each function to generate the code. I separate each of them
44: // with a couple of NOP bytes to make it easier to read the
45: // disassembly.
46: __asm NOP __asm NOP
00401006 90 nop
00401007 90 nop
47: CDeclFunction ( g_szCdeclCall , 1 , 'a' ) ;
00401008 6A 61 push 61h
0040100A 6A 01 push 1
0040100C A1 14 30 40 00 mov eax,[00403014]
00401011 50 push eax
00401012 E8 45 00 00 00 call 0040105C
00401017 83 C4 0C add esp,0Ch
48: __asm NOP __asm NOP
0040101A 90 nop
0040101B 90 nop
49: StdCallFunction ( g_szStdCall , 2 , 'b' ) ;
0040101C 6A 62 push 62h
0040101E 6A 02 push 2
00401020 8B 0D 10 30 40 00 mov ecx,dword ptr ds:[00403010h]
00401026 51 push ecx
00401027 E8 3D 00 00 00 call 00401069
50: __asm NOP __asm NOP
0040102C 90 nop
0040102D 90 nop
51: FastCallFunction ( g_szFastCall , 3 , 'c' ) ;
0040102E 6A 63 push 63h
00401030 BA 03 00 00 00 mov edx,3
00401035 8B 0D 18 30 40 00 mov ecx,dword ptr ds:[00403018h]
0040103B E8 38 00 00 00 call 00401078
52: __asm NOP __asm NOP
00401040 90 nop
00401041 90 nop
53: NakedCallFunction ( g_szNakedCall , 4 , 'd' ) ;
00401042 6A 64 push 64h
00401044 6A 04 push 4
00401046 8B 15 1C 30 40 00 mov edx,dword ptr ds:[0040301Ch]
0040104C 52 push edx
0040104D E8 40 00 00 00 call 00401092
00401052 83 C4 0C add esp,0Ch
54: __asm NOP __asm NOP
00401055 90 nop
00401056 90 nop
55:
56: }
00401057 5F pop edi
00401058 5E pop esi
00401059 5B pop ebx
0040105A 5D pop ebp
0040105B C3 ret
57:
58: void CDeclFunction ( char * szString ,
59: unsigned long ulLong ,
60: char chChar )
61: {
0040105C 55 push ebp
0040105D 8B EC mov ebp,esp
0040105F 53 push ebx
00401060 56 push esi
00401061 57 push edi
62: __asm NOP __asm NOP
00401062 90 nop
00401063 90 nop
63: }
00401064 5F pop edi
00401065 5E pop esi
00401066 5B pop ebx
00401067 5D pop ebp
00401068 C3 ret
64:
65: void __stdcall StdCallFunction ( char * szString ,
66: unsigned long ulLong ,
67: char chChar )
68: {
00401069 55 push ebp
0040106A 8B EC mov ebp,esp
0040106C 53 push ebx
0040106D 56 push esi
0040106E 57 push edi
69: __asm NOP __asm NOP
0040106F 90 nop
00401070 90 nop
70: }
00401071 5F pop edi
00401072 5E pop esi
00401073 5B pop ebx
00401074 5D pop ebp
00401075 C2 0C 00 ret 0Ch
71:
72: void __fastcall FastCallFunction ( char * szString ,
73: unsigned long ulLong ,
74: char chChar )
75: {
00401078 55 push ebp
00401079 8B EC mov ebp,esp
0040107B 83 EC 08 sub esp,8
0040107E 53 push ebx
0040107F 56 push esi
00401080 57 push edi
00401081 89 55 F8 mov dword ptr [ebp-8],edx
00401084 89 4D FC mov dword ptr [ebp-4],ecx
76: __asm NOP __asm NOP
00401087 90 nop
00401088 90 nop
77: }
00401089 5F pop edi
0040108A 5E pop esi
0040108B 5B pop ebx
0040108C 8B E5 mov esp,ebp
0040108E 5D pop ebp
0040108F C2 04 00 ret 4
78:
79: __declspec(naked) int NakedCallFunction ( char * szString ,
80: unsigned long ulLong ,
81: char chChar )
82: {
00401092 90 nop
00401093 90 nop
83: __asm NOP __asm NOP
84: // Naked functions must EXPLICITLY do a return.
85: __asm RET
00401094 C3 ret
Figure 4 Parameters to Create Process
Value | Type | Parameter |
0x0012EAB4 | LPCTSTR | lpApplicationName |
0x0012ED20 | LPTSTR | lpCommandLine |
0x00000000 | LPSECURITY_ATTRIBUTES | lpProcessAttributes |
0x00000000 | LPSECURITY_ATTRIBUTES | lpThreadAttributes |
0x00000001 | BOOL | bInheritHandles |
0x08000000 | DWORD | dwCreationFlags |
0x00000000 | LPVOID | lpEnvironment |
0x00000000 | LPCTSTR | lpCurrentDirectory |
0x0012EA2C | LPSTARTUPINFO | lpStartupInfo |
0x0012ECC8 | LPPROCESS_INFORMATION | lpProcessInformation |