10
votes

I'm learning x86_64 assembly on Linux and I've run into some conflicting information that I was hoping could get cleared up. On one hand, I've read that for syscall arguments, you would use registers in the order of rdi, rsi, rdx, and so on. But on the other hand I've read that you use the registers rbx, rcx, rdx, and so on. One person told me that the reasoning for this is because of ABI, but I'm not totally understanding what that exactly means.

Why are there two formats for this and which would be the proper one to use?

1

1 Answers

10
votes

According to this Wikibooks page, it depends on which instruction you are using to perform the syscall.

  • If you are using int $0x80 (the 32-bit ABI with call numbers from asm/unistd_32.h), then you should use eax for the syscall number, and ebx, ecx, edx, esi, edi, and ebp for the parameters (in that order).

  • If you are using the syscall instruction (the 64-bit ABI with native call numbers from asm/unistd.h), you should use rax for the syscall number and rdi, rsi, rdx, r10, r8, and r9 for the parameters.

What are the calling conventions for UNIX & Linux system calls on i386 and x86-64

In 64-bit mode syscall is preferred because it's faster, available on all x86-64 Linux kernels, and supports 64-bit pointers and integers. The int 0x80 ABI truly takes input in ecx, not rcx, for example, making it unusable for write or read of a buffer on the stack in 64-bit code. What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?.