LOGBOOK

HELP

Quiz Entry - updated: 2026.07.14

How are Linux system calls invoked on x86_64, and how does the syscall register convention differ from the normal function ABI?

Put the syscall number in %rax, the arguments in %rdi, %rsi, %rdx, %r10, %r8, %r9, then execute syscall; the result returns in %rax. Note arg 4 is %r10, not %rcx.

Register mapping for Linux syscalls with the number in rax and args in rdi, rsi, rdx, r10, r8, r9, highlighting r10 as the replacement for rcx.

* Syscall number and result in rax; arg 4 uses r10 not rcx because the syscall instruction clobbers rcx. *

A system call is a controlled jump into the kernel. Unlike a normal call, you select the operation with a number in %rax and trigger the syscall instruction:

Register Purpose
%rax System-call number (e.g. 1 = write, 60 = exit)
%rdi Argument 1
%rsi Argument 2
%rdx Argument 3
%r10 Argument 4 — not %rcx!
%r8 Argument 5
%r9 Argument 6
%rax Return value: ≥0 success, <0 error (negative errno)
mov  $1, %rax        # syscall 1 = write
mov  $1, %rdi        # fd = 1 (stdout)
lea  msg(%rip), %rsi # buffer
mov  $13, %rdx       # count
syscall              # trap into the kernel

The %r10 quirk: the user-space function ABI uses %rcx for the 4th argument, but the syscall instruction itself clobbers %rcx (it stashes the return address there). So the kernel ABI substitutes %r10 for argument 4. Everything else matches the function ABI.

Note: Normally you don't write this by hand — libc provides wrapper functions (write(), exit()) that set up the registers and issue syscall for you.

Go deeper:

From Quiz: REVE1 / Translation of C to Assembly | Updated: Jul 14, 2026