问题
From this question, What registers are preserved through a linux x86-64 function call, it says that the following registers are saved across function calls:
r12, r13, r14, r15, rbx, rsp, rbp
So, I went ahead and did a test with the following:
.globl _start
_start:
mov $5, %r12
mov $5, %r13
mov $5, %r14
mov $5, %r15
call get_array_size
mov $60, %eax
syscall
get_array_size:
mov $0, %r12
mov $0, %r13
mov $0, %r14
mov $0, %r15
ret
And, I was thinking that after the call get_array_size
that my registers would automatically (and somewhat magically) restore with the values 5
. gdb
shows that this is incorrect.
But I think that maybe I'm misunderstanding this. I suppose it just means that any functions that "conform to the x86-64 ABI" are supposed to restore those registers after they are finished (in other words, my get_array_size
function is an invalid functino in the linux ABI), or could someone explain to me what I seem to be missing in my understanding.
Additionally, when someone says that a function should conform to the ABI
, are non-globl functions supposed to do this as well? Or do the 'internal-implementations' not matter at all and only the functions I expose to the public (via globl
) supposed to comply with it? Is there a notation that is typically used to say whether a function is local or global (such as in the naming scheme?).
Of course, I'm a beginner to asm
so thank you very much in explaining what I may be missing.
回答1:
Correct, your hand-written asm get_array_size
doesn't follow the ABI because it's clobbering call-preserved registers. That means its callers need to treat it specially, not follow the usual ABI guarantees.
The ABI doc is a standard that compiler-generated functions follow, and so should most hand-written functions unless you want to make up your own custom calling convention. See What are callee and caller saved registers? for more details about what call-preserved vs. call-clobbered means for the caller, and for the implementation of the function itself if it wants to follow the ABI.
Small private "helper" functions with custom calling conventions are fine as long as you comment them (and never try to call them from C). Especially when you're optimizing, e.g. for code size (see codegolf x86-64 tips)
There is no magic in asm, each instruction only has its documented effect on the architectural state. (Contents of registers and memory).
As you can see from Intel's docs for call and ret, the only integer register they modify is RSP. Normal assemblers like NASM and GAS don't magically add instructions to your function. (MASM can be different, but if you look at disassembly you can still see the real code.)
来源:https://stackoverflow.com/questions/63865026/what-does-it-mean-that-registers-are-preserved-across-function-calls