"The most important thing in the programming language is the name. A language will not succeed without a good name. I have recently invented a very good name and now I am looking for a suitable language." -- Donald Knuth
In addition to specifying how the parameters are placed on the stack as well as who is responsible for cleaning up the stack, the calling convention also dictates how the function names are decorated.Calling convention Parameters Stack cleanup -------------------------------------------------------------------- __cdecl right to left caller __stdcall right to left callee (function) __fastcall registers, right to left callee (function) __pascal left to right callee (function)
Given these 4 declarations using each of the four calling conventions:
this is how the decoration is done:int __cdecl Function1(int a, double b, float c); int __stdcall Function2(int a, double b, float c); int __fastcall Function3(int a, double b, float c); int __pascal Function4(int a, double b, float c);
_Function1
_Function2@16
@Function3@16
FUNCTION4
But, since we've never defined the 3 functions above, the linker will generate these errors:int __cdecl Function1(int a, double b, float c); int __stdcall Function2(int a, double b, float c); int __fastcall Function3(int a, double b, float c); void main(void) { Function1(1, 2.0, 3.14F); Function2(1, 2.0, 3.14F); Function3(1, 2.0, 3.14F); }
Sample generated asm code:Linking... main.obj : error LNK2001: unresolved external symbol @Function3@16 main.obj : error LNK2001: unresolved external symbol _Function2@16 main.obj : error LNK2001: unresolved external symbol _Function1
308: Function1(1, 2.0, 3.14F);
004013B8 push 4048F5C3h
004013BD push 40000000h
004013C2 push 0
004013C4 push 1
004013C6 call @ILT+40(_Function1) (0040102d)
004013CB add esp,10h
309: Function2(1, 2.0, 3.14F);
004013CE push 4048F5C3h
004013D3 push 40000000h
004013D8 push 0
004013DA push 1
004013DC call @ILT+20(_Function2@16) (00401019)
310: Function3(1, 2.0, 3.14F);
004013E1 push 4048F5C3h
004013E6 push 40000000h
004013EB push 0
004013ED mov ecx,1
004013F2 call @ILT+0(@Function3@16) (00401005)
311: }
Note that if we had this:3.14 in binary is 1000000010010001111010111000011 (it's 4048F5C3 in hex) 2.0 in binary is 1000000000000000000000000000000 (it's 40000000 in hex)
and called it like this:int __fastcall Function5(int a, int b, int c, int d);
the generated assembler code looks like this:Function5(1, 2, 3, 4);
311: Function5(1, 2, 3, 4);
00401427 push 4
00401429 push 3
0040142B mov edx,2
00401430 mov ecx,1
00401435 call @ILT+0(@Function5@16) (00401005)
From WINDEF.H
#ifdef _MAC
#define CALLBACK PASCAL
#define WINAPI CDECL
#define WINAPIV CDECL
#define APIENTRY WINAPI
#define APIPRIVATE CDECL
#ifdef _68K_
#define PASCAL __pascal
#else
#define PASCAL
#endif
#elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
#define APIPRIVATE __stdcall
#define PASCAL __stdcall
#else
#define CALLBACK
#define WINAPI
#define WINAPIV
#define APIENTRY WINAPI
#define APIPRIVATE
#define PASCAL pascal
#endif
Additional details from Microsoft's site.
Notes:
History of Calling Conventions from Raymond Chen's blog. This document is a copy from here, here, and here.