The following table summarizes some commonly used Microsoft calling
conventions. In the CS 413 project, we use the __cdecl
calling convention. In all these calling conventions, the
ebx
, ebp
, esi
, and
edi
are considered callee-save, as can be seen from
the example code below.
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. |
This C code with its interspersed assembly code demonstrates the various calling conventions.
// The strings passed to each function. static char * g_szStdCall = "__stdcall" ; static char * g_szCdeclCall = "__cdecl" ; static char * g_szFastCall = "__fastcall" ; static char * g_szNakedCall = "__naked" ; // The extern "C" turns off all C++ name decoration. extern "C" { // The __cdecl function. void CDeclFunction ( char * szString , unsigned long ulLong , char chChar ) ; // The __stdcall function. void __stdcall StdCallFunction ( char * szString , unsigned long ulLong , char chChar ) ; // The __fastcall function. void __fastcall FastCallFunction ( char * szString , unsigned long ulLong , char chChar ) ; // The naked function. The declspec goes on the definition, not the // declaration. int NakedCallFunction ( char * szString , unsigned long ulLong , char chChar ) ; } void main ( void ) { 00401000 55 push ebp 00401001 8B EC mov ebp,esp 00401003 53 push ebx 00401004 56 push esi 00401005 57 push edi // Call each function to generate the code. 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 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 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 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 } 00401057 5F pop edi 00401058 5E pop esi 00401059 5B pop ebx 0040105A 5D pop ebp 0040105B C3 ret void CDeclFunction ( char * szString , unsigned long ulLong , char chChar ) { 0040105C 55 push ebp 0040105D 8B EC mov ebp,esp 0040105F 53 push ebx 00401060 56 push esi 00401061 57 push edi __asm NOP __asm NOP // NOPs stand for the function body here 00401062 90 nop 00401063 90 nop } 00401064 5F pop edi 00401065 5E pop esi 00401066 5B pop ebx 00401067 5D pop ebp 00401068 C3 ret void __stdcall StdCallFunction ( char * szString , unsigned long ulLong , char chChar ) { 00401069 55 push ebp 0040106A 8B EC mov ebp,esp 0040106C 53 push ebx 0040106D 56 push esi 0040106E 57 push edi __asm NOP __asm NOP 0040106F 90 nop 00401070 90 nop } 00401071 5F pop edi 00401072 5E pop esi 00401073 5B pop ebx 00401074 5D pop ebp 00401075 C2 0C 00 ret 0Ch void __fastcall FastCallFunction ( char * szString , unsigned long ulLong , char chChar ) { 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 __asm NOP __asm NOP 00401087 90 nop 00401088 90 nop } 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: __declspec(naked) int NakedCallFunction ( char * szString , unsigned long ulLong , char chChar ) { __asm NOP __asm NOP 00401092 90 nop 00401093 90 nop // Naked functions must EXPLICITLY do a return. __asm RET 00401094 C3 ret