Microsoft Calling Conventions

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.

Example code

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