Traditionally, C-function calls are made with a call that calls some parameters on the stack, a function call, and then dropping the stack to clear these pressed arguments.
push arg1 push arg2 push arg3 call function add sp,12 // effectively "pop; pop; pop"
Note. The default convention shown above is called __cdecl.
The other most popular convention is __stdcall. In it, the parameters are pressed again by the caller, but the stack is cleared by the called user. This is the standard convention for Win32 API functions (as defined by the WINAPI macro), and is also sometimes called the "Pascal" calling convention.
push arg1 push arg2 push arg3 call function // no stack cleanup - callee does this
This looks like a minor technical detail, but if there is disagreement about how the stack is managed between the caller and the callee, the stack will be destroyed in a way that is unlikely to be restored. Since __stdcall performs a stack cleanup, the (very small) code to complete this task is only in one place, and is not duplicated in each calling device, as in __cdecl. This makes the code very slightly smaller, although size effects are only visible in large programs.
Variadic functions, such as printf (), are almost impossible to get with __stdcall, because only the caller really knows how many arguments were passed to clear them. A call can make some good guesses (say, looking at a format string), but clearing the stack should be determined by the actual logic of the function, and not by the call-convention mechanism itself. Therefore, only __cdecl supports variational functions so that the caller can perform the cleanup.
Linker conventions: As mentioned in the paragraph above, calling a function with an "incorrect" convention can be disastrous, so Microsoft has a mechanism to avoid this. It works well, although it can be insane if you don't know what the reason is. They decided to resolve this by encoding the calling convention into low-level function names with extra characters (often called "decorations"), and they are treated as unrelated names by the linker. The standard call is __cdecl, but can anyone be requested explicitly with / G? parameter to the compiler.
__ cdecl (cl / Gd ...)
All function names of this type have an underscore prefix, and the number of parameters does not matter much, since the caller is responsible for installing the stack and clearing the stack. It is possible for the caller and the callee to cause confusion over the number of parameters actually transferred, but at least the stack discipline is properly maintained.
__ stdcall (cl / Gz ...)
These function names have an underscore prefix and are added along with @ plus the number of bytes of the parameters passed. By this mechanism, it is impossible to call a function with the βwrongβ type or even with the wrong number of parameters.
__ fastcall (cl / Gr ...)
These function names begin with the @ sign and suffixes with the @parameter parameter, like __stdcall.
Examples:
Declaration -----------------------> decorated name void __cdecl foo(void); -----------------------> _foo void __cdecl foo(int a); -----------------------> _foo void __cdecl foo(int a, int b); -----------------------> _foo void __stdcall foo(void); -----------------------> _foo@0 void __stdcall foo(int a); -----------------------> _foo@4 void __stdcall foo(int a, int b); -----------------------> _foo@8 void __fastcall foo(void); -----------------------> @foo@0 void __fastcall foo(int a); -----------------------> @foo@4 void __fastcall foo(int a, int b); -----------------------> @foo@8