The cdecl
(C Declaration) calling convention is usually the default calling convention for x86 C compilers
In computer science, a calling convention is an implementation-level (low-level) scheme for how subroutines receive parameters from their caller and how they return a result. Differences in various implementations include where parameters, return values, return addresses and scope links are placed (registers, stack or memory etc.), and how the tasks of preparing for a function call and restoring the environment afterwards are divided between the caller and the callee.
(Source)
Calling conventions may be related to a particular programming language's evaluation strategy, but most often are not considered part of it (or vice versa), as the evaluation strategy is usually defined on a higher abstraction level and seen as a part of the language rather than as a low-level implementation detail of a particular language's compiler.
(Source)
The cdecl
(which stands for C declaration) is a calling convention that originates from Microsoft's compiler for the C programming language and is used by many C compilers for the x86 architecture. In cdecl
, subroutine arguments are passed on the stack. Integer values and memory addresses are returned in the EAX
register, floating point values in the ST0
x87 register. Registers EAX
, ECX
, and EDX
are caller-saved, and the rest are callee-saved. The x87 floating point registers ST0
to ST7
must be empty (popped or freed) when calling a new function, and ST1
to ST7
must be empty on exiting a function. ST0
must also be empty when not used for returning a value.
In the context of the C programming language, function arguments are pushed on the stack in the right-to-left order, i.e. the last argument is pushed first.
Consider the following C source code snippet:
int callee(int, int, int);
int caller(void)
{
return callee(1, 2, 3) + 5;
}
On x86, it might produce the following assembly code (Intel syntax):
caller:
; make new call frame
; (some compilers may produce an 'enter' instruction instead)
push ebp ; save old call frame
mov ebp, esp ; initialize new call frame
; push call arguments, in reverse
; (some compilers may subtract the required space from the stack pointer,
; then write each argument directly, see below.
; The 'enter' instruction can also do something similar)
; sub esp, 12 : 'enter' instruction could do this for us
; mov [ebp-4], 3 : or mov [esp+8], 3
; mov [ebp-8], 2 : or mov [esp+4], 2
; mov [ebp-12], 1 : or mov [esp], 1
push 3
push 2
push 1
call callee ; call subroutine 'callee'
add esp, 12 ; remove call arguments from frame
add eax, 5 ; modify subroutine result
; (eax is the return value of our callee,
; so we don't have to move it into a local variable)
; restore old call frame
; (some compilers may produce a 'leave' instruction instead)
mov esp, ebp ; most calling conventions dictate ebp be callee-saved,
; i.e. it's preserved after calling the callee.
; it therefore still points to the start of our stack frame.
; we do need to make sure
; callee doesn't modify (or restores) ebp, though,
; so we need to make sure
; it uses a calling convention which does this
pop ebp ; restore old call frame
ret ; return
The caller cleans the stack after the function call returns.
The cdecl
calling convention is usually the default calling convention for x86 C compilers, although many compilers provide options to automatically change the calling conventions used. To manually define a function to be cdecl
, some support the following syntax:
return_type __cdecl func_name();
Calling convention is the name of the calling convention. __cdecl
, __stdcall
, __pascal
and
__fastcall
can be specified explicitly in C++ function declarations for compilers that support
these conventions. __cdecl
is the default for applications and static libraries. __stdcall
is
the default for system calls (including Windows API calls) and recommended for library
DLL's in 32-bit Windows. __thiscall
is used by default in Microsoft compilers for member
functions in 16 and 32 bit mode. Microsoft, Borland, Watcom and Gnu are brands of
compilers. Intel compilers for Windows are compatible with Microsoft. Intel compilers for
Linux are compatible with Gnu. Symantec, Digital Mars and Codeplay compilers are
compatible with Microsoft. In 64 bit mode, there is one default calling convention for each
operating system, while other calling conventions are rare in 64 bit mode.
Other Conventions:
- __pascal
- __fortran
- __thiscall
- __stdcall
- __fastcall
- __msfastcall
- __regcall
- __vectorcall
(Source)
extern "C"
– Aerugo