I decided to take a crack at assembly the other day, and I've been playing around with really basic things like printing stuff from argv to stdout. I found this great list of linux syscall numbers with arguments and everything, and I'm curious why r10
is used for arguments before r8
and r9
. I've found all kinds of weird conventions about what can be used what for what and when, like how loop counters go in rcx
. Is there a particular reason why r10
was moved up? Was it more convenient?
I should probably also mention I'm interested in this out of curiosity, not because it's causing me problems.
Edit: I found this question which gets close, referencing the x64 ABI documentation on page 124, where it notes that user level applications use rdi, rsi, rdx, rcx, r8, r9
. The kernel on the other hand uses r10
instead of rcx
, and destroys rcx
and r11
. That might explain how r10
ended up there, but then why was it swapped in?
RCX
, along withR11
, is used by thesyscall
instruction, being immediately destroyed by it. Thus these registers are not only not saved after syscall, but they can't even be used for parameter passing. ThusR10
was chosen to replace unusableRCX
to pass fourth parameter.See also this answer for a bit more information on how
syscall
uses these registers.Reference: Intel's Instruction Set Reference, look for
SYSCALL
.see x86-64.orgs abi documentation
page 124
This is saying that when you use the syscall instruction the kernel destroys
%rcx
so you need to use%r10
instead.Also the comment from @technosaurus explains that the kernel is using
%rcx
to store the entry point in case of an interrupt during a syscall.