How does the IA32 (32-bit x86) calling convention differ from x86_64?
IA32 passes all arguments on the stack and uses %ebp as a dedicated frame pointer; x86_64 passes the first six args in registers and usually needs no frame pointer.
The 32-bit convention predates the abundance of registers, so it leans on the stack:
| Aspect | x86_64 | IA32 |
|---|---|---|
| Argument passing | First 6 in registers | All on the stack |
| Frame reference | %rsp (usually no frame pointer) |
%ebp base/frame pointer |
| Callee-saved regs | 6 (%rbx,%rbp,%r12–%r15) |
3 (%ebx,%esi,%edi) |
| Caller-saved regs | many | 3 (%eax,%ecx,%edx) |
| Return value | %rax |
%eax |
IA32 stack frame: the caller pushes arguments before the call. Inside the callee, after the standard push %ebp; mov %esp,%ebp prologue, parameters live at positive offsets from %ebp (e.g. 8(%ebp) is arg 1) and locals at negative offsets.
Why the change? x86_64 doubled the register count (8 → 16 general-purpose registers), so the ABI could afford to keep arguments in registers — far faster than memory round-trips through the stack.
Go deeper:
x86 calling conventions (Wikipedia) — both conventions documented side by side.
Calling convention (Wikipedia) — why platforms carry more than one convention.