Four ABIs cover nearly all x86 code: System V x86-64 for Linux, macOS and the BSDs, Microsoft x64 for Windows and UEFI, and their 32-bit counterparts, System V i386 and the 32-bit Windows conventions, of which the tables show __cdecl, the default. The overview says which platform uses which. The columns of every table link to the page of their ABI.

Arguments

Tables 1 and 2 are not typed in. Each function of a small example returns its Nth argument, and the build reads where the argument comes from out of the function’s first instruction, for each ABI; a stack slot is given relative to the stack pointer on entry, when it points at the return address.

Where the first eight int arguments arrive, measured from GCC and Clang output.
ArgumentSystem V x86-64Microsoft x64System V i386Windows x86
1RDIRCXESP+4ESP+4
2RSIRDXESP+8ESP+8
3RDXR8ESP+12ESP+12
4RCXR9ESP+16ESP+16
5R8RSP+40ESP+20ESP+20
6R9RSP+48ESP+24ESP+24
7RSP+8RSP+56ESP+28ESP+28
8RSP+16RSP+64ESP+32ESP+32
Where the first ten double arguments arrive, measured the same way.
ArgumentSystem V x86-64Microsoft x64System V i386Windows x86
1XMM0XMM0ESP+4ESP+4
2XMM1XMM1ESP+12ESP+12
3XMM2XMM2ESP+20ESP+20
4XMM3XMM3ESP+28ESP+28
5XMM4RSP+40ESP+36ESP+36
6XMM5RSP+48ESP+44ESP+44
7XMM6RSP+56ESP+52ESP+52
8XMM7RSP+64ESP+60ESP+60
9RSP+8RSP+72ESP+68ESP+68
10RSP+16RSP+80ESP+76ESP+76

The two 64-bit ABIs differ in more than the registers. System V keeps two independent sequences: integers take the next of six general-purpose registers and floating-point values the next of eight vector registers, whatever their order. Microsoft gives each of the first four positions one slot: the second argument is in RDX if it is an integer and in XMM1 if it is a double. Microsoft’s stack arguments also start 32 bytes further up, past the shadow space that the caller reserves. On 32-bit x86, every argument is on the stack, and a double takes two slots.

The second argument, once a double after an int and once an int after a double. In System V it arrives in the first register of its kind, XMM0 or EDI; in Microsoft x64, in the second slot, XMM1 or EDX.

mixed-slots.c

/* Mixed arguments: System V fills integer and vector registers from
   separate sequences, Microsoft x64 gives each position one slot. */
double second_double(int a, double b)
{
	return b;
}

int second_int(double a, int b)
{
	return b;
}

GCC 14.2.0 (Debian 14.2.0-19) x86_64-linux-gnu

AT&T syntax gcc-14 -O2 -fno-asynchronous-unwind-tables -S mixed-slots.c

second_double:
        ret

second_int:
        movl    %edi, %eax
        ret

Intel syntax gcc-14 -O2 -fno-asynchronous-unwind-tables -masm=intel -S mixed-slots.c

second_double:
        ret

second_int:
        mov     eax, edi
        ret

Clang 23.1.2 x86_64-pc-windows-msvc

AT&T syntax clang --target=x86_64-pc-windows-msvc -O2 -fno-asynchronous-unwind-tables -S mixed-slots.c

second_double:
        movaps  %xmm1, %xmm0
        retq

second_int:
        movl    %edx, %eax
        retq

Intel syntax clang --target=x86_64-pc-windows-msvc -O2 -fno-asynchronous-unwind-tables -masm=intel -S mixed-slots.c

second_double:
        movaps  xmm0, xmm1
        ret

second_int:
        mov     eax, edx
        ret

Return values

Where results are returned.
ValueSystem V x86-64Microsoft x64System V i386Windows x86
Integers and pointersRAXRAXEAXEAX
A 64-bit integerRAXRAXEDX:EAXEDX:EAX
float, doubleXMM0XMM0ST0ST0
long doubleST0XMM0, as a double (MSVC); memory (MinGW-w64)ST0ST0
Structs of up to 16 bytesRAX, RDX, XMM0, XMM1 by classRAX if 1, 2, 4 or 8 bytes; else memorymemory (Linux); EAX, EDX if 1, 2, 4 or 8 bytes (FreeBSD, OpenBSD)EAX, EDX if 1, 2, 4 or 8 bytes; else memory
Larger structsmemorymemorymemorymemory
Address of the memoryRDI, returned in RAXRCX, returned in RAXon the stack, popped by the calleeon the stack, left to the caller

Callee-saved registers

A callee-saved register must have the same value when a function returns as when it was called; the function saves and restores it if it uses it. All other registers are scratch, and any call may change them.

Callee-saved registers in each ABI.
System V x86-64Microsoft x64System V i386Windows x86
General-purposeRBX, RBP, R12 to R15RBX, RBP, RDI, RSI, R12 to R15EBX, ESI, EDI, EBPEBX, ESI, EDI, EBP
VectornoneXMM6 to XMM15, the low 128 bitsnonenone
APX (R16 to R31)noneR30, R31not in 32-bit modenot in 32-bit mode
Control statex87 control word, control bits of MXCSRthe samethe samenot documented

The difference in the first two columns is the cost of calling across ABIs: a Windows function called from System V code may overwrite nothing the caller expects kept, but a System V function called from Windows code may overwrite RSI, RDI and XMM6 to XMM15, which the caller expects back. The Microsoft x64 page shows the code that saves them.

Structs, floating point and vectors

How structs, floating-point values and vectors are passed.
ArgumentSystem V x86-64Microsoft x64System V i386Windows x86
Struct of up to 16 bytesclassified by eightbyte: up to two registers, integer or vectorin a register if 1, 2, 4 or 8 bytes, else by referenceby value on the stackby value on the stack
Larger structby value on the stackby reference to a copyby value on the stackby value on the stack
float, doublenext of XMM0 to XMM7its slot among XMM0 to XMM3on the stackon the stack
long doubleon the stack, 16 bytesa double (MSVC); by reference (MinGW-w64)on the stack, 12 bytesa double (MSVC); on the stack (MinGW-w64)
__m128in an XMM registerby referencethe first three in XMM0 to XMM2in XMM registers
__m256, __m512in a YMM or ZMM register, if named and the CPU has themby referencethe first three in YMM0 to YMM2 or ZMM0 to ZMM2by value with __vectorcall
A 16-byte vector, as SSE’s __m128 is: in XMM0 and XMM1 everywhere but in Microsoft x64, which passes both by reference, in RCX and RDX. GCC for i386 is given -msse2, since the i686 it otherwise compiles for has no XMM registers.

vector-args.c

/* A 16-byte vector, like SSE's __m128, as argument and result. */
typedef float v4sf __attribute__((vector_size(16)));

v4sf vadd(v4sf a, v4sf b)
{
	return a + b;
}

GCC 14.2.0 (Debian 14.2.0-19) x86_64-linux-gnu

AT&T syntax gcc-14 -O2 -fno-asynchronous-unwind-tables -S vector-args.c

vadd:
        addps   %xmm1, %xmm0
        ret

Intel syntax gcc-14 -O2 -fno-asynchronous-unwind-tables -masm=intel -S vector-args.c

vadd:
        addps   xmm0, xmm1
        ret

Clang 23.1.2 x86_64-pc-windows-msvc

AT&T syntax clang --target=x86_64-pc-windows-msvc -O2 -fno-asynchronous-unwind-tables -S vector-args.c

vadd:
        movaps  (%rcx), %xmm0
        addps   (%rdx), %xmm0
        retq

Intel syntax clang --target=x86_64-pc-windows-msvc -O2 -fno-asynchronous-unwind-tables -masm=intel -S vector-args.c

vadd:
        movaps  xmm0, xmmword ptr [rcx]
        addps   xmm0, xmmword ptr [rdx]
        ret

GCC 14.2.0 (Debian 14.2.0-19) i386-linux-gnu

AT&T syntax gcc-14 -m32 -march=i686 -mtune=generic -O2 -fno-asynchronous-unwind-tables -msse2 -S vector-args.c

vadd:
        addps   %xmm1, %xmm0
        ret

Intel syntax gcc-14 -m32 -march=i686 -mtune=generic -O2 -fno-asynchronous-unwind-tables -msse2 -masm=intel -S vector-args.c

vadd:
        addps   xmm0, xmm1
        ret

Clang 23.1.2 i686-pc-windows-msvc

AT&T syntax clang --target=i686-pc-windows-msvc -march=pentium4 -O2 -fno-asynchronous-unwind-tables -S vector-args.c

_vadd:
        addps   %xmm1, %xmm0
        retl

Intel syntax clang --target=i686-pc-windows-msvc -march=pentium4 -O2 -fno-asynchronous-unwind-tables -masm=intel -S vector-args.c

_vadd:
        addps   xmm0, xmm1
        ret

The stack

The stack at a call.
System V x86-64Microsoft x64System V i386Windows x86
Alignment at a call16 bytes16 bytes16 bytes4 bytes
Space the caller providesnone32 bytes of shadow spacenonenone
Space below the stack pointer128-byte red zonenonenonenone
Who removes stack argumentsthe callerthe callerthe callerthe caller for __cdecl, the callee otherwise
Variadic callsAL gives the number of vector registers usedfloating-point values also in the general-purpose register of their slotnothing extra__cdecl only

The stack frames page shows how a function lays out its frame in each ABI.

Sources

  1. System V Application Binary Interface, AMD64 Architecture Processor Supplement, version 1.0: commit e1ce098331da, 2025-03-12
  2. System V Application Binary Interface, Intel386 Architecture Processor Supplement, version 1.2: commit 20ec676cd56d, 2025-08-24
  3. Microsoft Learn: x64 calling convention: commit f70d88cd5da7, 2026-09-24
  4. Microsoft Learn: Overview of x64 ABI conventions: commit f70d88cd5da7, 2026-09-24
  5. Microsoft Learn: Argument passing and naming conventions: commit f70d88cd5da7, 2026-09-24
  6. Microsoft Learn: __stdcall: commit f70d88cd5da7, 2026-09-24