This article describes the calling conventions used when programming x86 architecture microprocessors.

Calling conventions describe the interface of called code: The order in which atomic (scalar) parameters, or individual parts of a complex parameter, are allocated How parameters are passed (pushed on the stack, placed in registers, or a mix of both) Which registers the called function must preserve for the caller (also known as: callee-saved registers or non-volatile registers) How the task of preparing the stack for, and restoring after, a function call is divided between the caller and the callee

This is intimately related with the assignment of sizes and formats to programming-language types. Another closely related topic is name mangling, which determines how symbol names in the code are mapped to symbol names used by the linker. Calling conventions, type representations, and name mangling are all part of what is known as an application binary interface (ABI).

There are subtle differences in how various compilers implement these conventions, so it is often difficult to interface code which is compiled by different compilers. On the other hand, conventions which are used as an API standard (such as stdcall) are very uniformly implemented.

Historical background The standard for IBM PC compatibles was defined by the Intel processors (8086, 80386) and the literal hardware IBM shipped. Hardware extensions and all software standards (save for a BIOS calling convention) were thrown open to market competition.

A multitude of independent software firms offered operating systems, compilers for many programming languages, and applications. Many different calling schemes were implemented by the firms, often mutually exclusive, based on different requirements, historical practices, and programmer creativity.

After the IBM compatible market shakeout, Microsoft operating systems and programming tools (with differing conventions) predominated, while second-tier firms like Borland and Novell, and open-source projects like GNU Compiler Collection (GCC), still maintained their own standards. Provisions for interoperability between vendors and products were eventually adopted, simplifying the problem of choosing a viable convention.

Caller clean-up In these types of calling conventions, the caller cleans the arguments from the stack (resets the state of the stack just as it was before the callee function was called).

cdecl The (which stands for C declaration) is a calling convention for the programming language C and is used by many C compilers for the x86 architecture. In cdecl, subroutine arguments are passed on the stack. If the return values are Integer values or memory addresses they are put into the EAX register by the callee, whereas floating point values are put 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 language C, function arguments are pushed on the stack in the right-to-left (RTL) order, i.e. the last argument is pushed first.

Consider the following C source code snippet:

On x86, it might produce the following assembly code (Intel syntax):

The caller cleans the stack after the function call returns.

The 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:

Variations There are some variations in the interpretation of cdecl. As a result, x86 programs compiled for different operating system platforms and/or by different compilers can be incompatible, even if they both use the "cdecl" convention and do not call out to the underlying environment.

Some compilers return simple data structures with a length of 2 registers or less in the register pair EAX:EDX and larger structures and class objects requiring special treatment by the exception handler (e.g., a defined constructor, destructor, or assignment) are returned in memory. To pass "in memory", the caller allocates memory and passes a pointer to it as a hidden first parameter; the callee populates the memory and returns the pointer, popping the hidden pointer when returning.

On Unix-like systems, the standard calling convention is defined in the System V ABI. There are separate documents for i386, x86-64, K1OM, etc.

In Linux, GCC sets the de facto standard for calling conventions. Since GCC version 4.5, the stack must be aligned to a 16-byte boundary when calling a function (prior versions only required a 4-byte alignment, as per System V ABI) due to the use of SSE aligned-load instructions.

syscall This is similar to cdecl in that arguments are pushed right-to-left. However, EAX, ECX, and EDX are not preserved, and the size of the parameter list in doublewords is passed in AL.

Syscall is the standard calling convention for 32 bit OS/2 API.

optlink Arguments are pushed right-to-left. The three first (leftmost) arguments are passed in EAX, EDX, and ECX and up to four floating-point arguments are passed in ST0 through ST3, although space for them is reserved in the argument list on the stack. Results are returned in EAX or ST0. Registers EBP, EBX, ESI, and EDI are preserved.

Optlink is used by the IBM VisualAge compilers.

Callee clean-up In these conventions, the callee cleans up the arguments from the stack. Functions which use these conventions are easy to recognize in ASM code because they will unwind the stack after returning. The x86 instruction allows an optional 16-bit parameter that specifies the number of stack bytes to release after returning to the caller. Such code looks like this:

Conventions named or have not been standardized, and have been implemented differently, depending on the compiler vendor. Typically register based calling conventions pass one or more arguments in registers which reduces the number of memory accesses required for the call and, thus, usually make them faster.

Pascal Based on the Borland Turbo Pascal language's calling convention, the parameters are pushed on the stack in left-to-right (LTR) order (opposite of cdecl), and the callee is responsible for removing them from the stack.

Returning the result works as follows: Ordinal values are returned in AL (8-bit values), AX (16-bit values), EAX (32-bit values), or DX:AX (32-bit values on 16-bit systems). Real values are returned in DX:BX:AX. Floating point (8087) values are returned in ST0. Pointers are returned in EAX on 32-bit systems and in AX in 16-bit systems. Strings are returned in a temporary location pointed by the @Result symbol.

This calling convention was common in the following 16-bit APIs: OS/2 1.x, Microsoft Windows 3.x, and Borland Delphi version 1.x. Modern versions of the Windows API use stdcall, which still has the callee restoring the stack as in the Pascal convention, but the parameters are now pushed right to left.

stdcall The stdcall calling convention is a variation on the Pascal calling convention in which the callee is responsible for cleaning up the stack, but the parameters are pushed onto the stack in right-to-left order, as in the _cdecl calling convention. Registers EAX, ECX, and EDX are designated for use within the function. Return values are stored in the EAX register.

stdcall is the standard calling convention for the Microsoft Win32 API and for Open Watcom C++.

Microsoft fastcall The Microsoft convention passes the first two arguments that fit (evaluated left to right) into ECX and EDX. Remaining arguments are pushed onto the stack from right to left. When the compiler compiles for IA64 or AMD64, it ignores the keyword (or any other calling convention keyword aside from ) and uses the Microsoft default 64-bit calling convention instead.

Other compilers like GCC and Clang provide similar "fastcall" calling conventions, although they are not necessarily compatible with each other or with Microsoft fastcall.

Consider the following C snippet:__attribute__((fastcall)) void printnums(int num1, int num2, int num3){ printf("The numbers you sent are: %d %d %d", num1, num2, num3); }

int main(){ printnums(1, 2, 3); return 0; }x86 decompilation of the main function will look like (in Intel syntax):main: ; stack setup push ebp mov ebp, esp push 3 ; immediate 3 (third argument is pushed to the stack) mov edx, 0x2 ; immediate 2 (second argument) is copied to edx register. mov ecx, 0x1 ; immediate 1 (first argument) is copied to ecx register. call printnums mov eax, 0 ; return 0 leave retn

The first two arguments are passed in the left to right order, and the third argument is pushed on the stack. There is no stack cleanup, as stack cleanup is performed by the callee. The disassembly of the callee function is:printnums: ; stack setup push ebp mov ebp, esp sub esp, 0x08 mov [ebp-0x04], ecx ; in x86, ecx = first argument. mov [ebp-0x08], edx ; arg2 push [ebp+0x08] ; arg3 is pushed to stack. push [ebp-0x08] ; arg2 is pushed push [ebp-0x04] ; arg1 is pushed push 0x8065d67 ; "The numbers you sent are %d %d %d" call printf ; stack cleanup add esp, 0x10 nop leave retn 0x04

As the two arguments were passed through the registers and only one parameter was pushed in the stack, the pushed value is being cleared by the retn instruction, as int is 4 bytes in size in x86 systems.

Microsoft vectorcall In Visual Studio 2013, Microsoft introduced the calling convention in response to efficiency concerns from game, graphic, video/audio, and codec developers. The scheme allows for larger vector types (, , , ) to be passed in registers as opposed to on the stack.

adds support for passing homogeneous vector aggregate (HVA) values, which are composite types (structs) consisting solely of up to four identical vector types, using the same six registers. Once the registers have been allocated for vector type arguments, the unused registers are allocated to HVA arguments from left to right. The positioning rules still apply. Resulting vector type and HVA values are returned using the first four XMM/YMM registers.

For IA-32 and x64 code, is similar to and the original x64 calling conventions respectively, but extends them to support passing vector arguments using SIMD registers. In IA-32, the integer values are passed as usual, and the first six SIMD (XMM/YMM0-5) registers hold up to six floating-point, vector, or HVA values sequentially from left to right, regardless of actual positions caused by, e.g. an int argument appearing between them. In x64, however, the rule from the original x64 convention still apply, so that XMM/YMM0-5 only hold floating-point, vector, or HVA arguments when they happen to be the first through the sixth.

The Clang compiler and the Intel C++ Compiler also implement vectorcall.

vectorcall only handles the 256-bit (AVX, YMM) view of the vector registers. It does not cover the AVX-512 (ZMM) view.

Intel register Before __vectorcall, ICC has a similar convention called , where as many parameters are stuffed into the registers as possible. It is also supported by clang.

Intel has a Vector Function ABI based on not implemented by clang (as of November 2025). It deals with vectors of ordinary types, so most parameters are passed (and the results returned) via [XYZ]MM registers. A variant of this ABI employing instead the x86_64 platform's usual System V calling convention with regard to register use is adopted by glibc's libmvec and supported by GCC, Clang, and ICC. (see VectorABI.txt)

GNU and clang modifiers