Some linux userspace assembly details

All this stuff is of course documented in (or inferable from) source. Current kernel release as I write is 2.3.99pre6 ($Date: 2000-11-12 20:56:12 $).

Info on the web

Architecture independent details

Running ELF binaries

There is another explanation at You might like to look at a page about making tiny elf images. For more in depth of the ABI, see SCO Developer Specifications.

The ELF handling kernel code is currently a bit confused with a.out handling code, and tries to support various variants of ELF, making it difficult to understand. The main feature of interest from a userland perspective is what gets left on the stack.

Stack diagram

Top of diagram is %esp (the address from which things are popped off).

Description Type
Number of arguments (argc) Unsigned long
Program name (argv[0]) String pointer
List of command line arguments, if any String pointer array
0 Unsigned long
Environment variables (VAR=VALUE format) String pointer array
0 Unsigned long
ELF header. Normally contains only AT_HWCAP and AT_PLATFORM (so you can find out CPU version and capability flags). It is terminated by AT_NULL (two unsigned longs). Pair of unsigned longs per parameter

Finally, ELF_PLAT_INIT macro is called, which resets registers to 0 (on i386 at least -- see elf.h).

x86 specifics

Selector registers: fs and gs

These two and es are reset regularly by something (what?). Therefore it is possible to store only a limited amount of information in them. As far as I can see, if they're 0, they're not changed to non-zero and vice versa, so you get two extra independent bits to store things. Update: I saw a changes list on linux-kernel which claimed that the fs/gs modfication bug reported by Ulrich Drepper was fixed, so perhaps you now get full use of these registers.


System call arguments are passed to the kernel in registers. In entry.S they're all pushed onto the stack, and the actual syscall (usually C) procedure is called. This procedure is declared asmlinkage so that it takes all its arguments off the stack.

There is an example of how to make a syscall in glibc-2.1.2/sysdeps/unix/sysv/linux/i386/sysdep.h, but I don't think it's fully up to date wrt the 2.3.99 kernels. It explains in a comment the argument passing convention, but new kernels (from my understanding of entry.S) do not clobber any registers and allow a sixth argument to be passed in %ebp. In the old days (in which glibc at version 2.1.2 lives), calls with 6 arguments (like mmap) had to pass a pointer to a structure containing them.

Input Register Output
syscall number %eax Syscall return value
arg 1 %ebx Saved
arg 2 %ecx Clobbered (saved in 2.3?)
arg 3 %edx Clobbered (saved in 2.3?)
arg 4 %esi Saved
arg 5 %edi Saved
arg 6? %ebp ?