The introduction to caller-saved registers and callee-saved registers.

1. Prerequisite

Introduction to System V ABI

2. Definition

2.1 Caller-saved registers

Caller-saved registers (AKA volatile registers, or call-clobbered) are used to hold temporary quantities that need not be preserved across calls.

For that reason, it is the caller’s responsibility to push these registers onto the stack or copy them somewhere else if it wants to restore this value after a procedure call.

It’s normal to let a call destroy temporary values in these registers, though.

2.2 Callee-saved registers

Callee-saved registers (AKA non-volatile registers, or call-preserved) are used to hold long-lived values that should be preserved across calls.

When the caller makes a procedure call, it can expect that those registers will hold the same value after the callee returns, making it the responsibility of the callee to save them and restore them before returning to the caller. Or to not touch them.

3. Linux x86-64 function call

spec

3.1 Callee-saved registers

r12, r13, r14, r15, rbx, rsp, rbp are the callee-saved registers - they have a “Yes” in the “Preserved across function calls” column.

3.2 Caller-saved registers

4. Example

4.1 setjmp

https://gitlab.com/kvm-unit-tests/kvm-unit-tests/-/blob/master/lib/x86/setjmp64.S

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.globl setjmp
setjmp:
mov (%rsp), %rsi
mov %rsi, (%rdi)
mov %rsp, 0x8(%rdi)
mov %rbp, 0x10(%rdi)
mov %rbx, 0x18(%rdi)
mov %r12, 0x20(%rdi)
mov %r13, 0x28(%rdi)
mov %r14, 0x30(%rdi)
mov %r15, 0x38(%rdi)
xor %eax, %eax
ret

.globl longjmp
longjmp:
mov %esi, %eax
mov 0x38(%rdi), %r15
mov 0x30(%rdi), %r14
mov 0x28(%rdi), %r13
mov 0x20(%rdi), %r12
mov 0x18(%rdi), %rbx
mov 0x10(%rdi), %rbp
mov 0x8(%rdi), %rsp
mov (%rdi), %rsi
mov %rsi, (%rsp)
ret

4.2 arch_switch_to

https://github.com/projectacrn/acrn-hypervisor/blob/release_2.7/hypervisor/arch/x86/sched.S

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    .text

.code64
.align 8
.global arch_switch_to
arch_switch_to:
pushf
pushq %rbx
pushq %rbp
pushq %r12
pushq %r13
pushq %r14
pushq %r15
pushq %rdi
movq %rsp, (%rdi)
movq (%rsi), %rsp
popq %rdi
popq %r15
popq %r14
popq %r13
popq %r12
popq %rbp
popq %rbx
popf
retq

参考资料:

  1. What are callee and caller saved registers?
  2. What registers are preserved through a linux x86-64 function call
  3. x86 Assembly Guide