Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.0k views
in Technique[技术] by (71.8m points)

assembly - What does it mean that "registers are preserved across function calls"?

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...