gcc 是否保留被调用者保存寄存器
does gcc preserve callee save registers
您可能已经猜到了,问题是 gcc
会自动保存被调用者保存寄存器还是我应该自己做?我以为 gcc
会为我做那件事但是当我写这段代码时
void foo(void) {
__asm__ volatile ("mov 3, %rbx");
}
void main(void) {
foo();
}
在 gcc a.c && objdump -d a.out
之后我看到了这个
00000000004004f6 <foo>:
4004f6: 55 push %rbp
4004f7: 48 89 e5 mov %rsp,%rbp
4004fa: 48 c7 c3 7b 00 00 00 mov [=11=]x7b,%rbx
400501: 90 nop
400502: 5d pop %rbp
400503: c3 retq
0000000000400504 <main>:
400504: 55 push %rbp
400505: 48 89 e5 mov %rsp,%rbp
400508: e8 e9 ff ff ff callq 4004f6 <foo>
40050d: 90 nop
40050e: 5d pop %rbp
40050f: c3 retq
根据 x86-64 ABI %rbx
是一个被调用者保存寄存器,但在这段代码中 gcc
在修改之前没有将其保存在 foo
中。是因为我调用foo()
后没有在主函数中使用%rbx
还是因为gcc
没有提供这样的保证,我必须自己保存在[=17=中] 修改之前?
死记硬背地保存和恢复每个寄存器将是相当笨拙的代码。编译器在它编译的 C 代码中保存寄存器,但是你在这里是你自己的,gcc 不知道你的意图是什么。
组装器可让您深入了解引擎盖,但不会为您更换火花塞。
Gcc 将自动保存和恢复所有被调用者保存的寄存器它知道被使用。它知道自己使用的寄存器,但如果您告诉它,它只会知道内联汇编中使用的寄存器。这就是 'clobbers' 列表的用途:
void foo(void) {
__asm__ volatile ("mov 3, %%rbx" : : : "rbx");
}
现在编译器知道你是using/modifying rbx,所以如果需要它会保存它。
请注意,你真的想这样做而不是试图自己保存它,因为如果 gcc 也想在这个函数中使用寄存器,这样它只会被保存一次。
您可能已经猜到了,问题是 gcc
会自动保存被调用者保存寄存器还是我应该自己做?我以为 gcc
会为我做那件事但是当我写这段代码时
void foo(void) {
__asm__ volatile ("mov 3, %rbx");
}
void main(void) {
foo();
}
在 gcc a.c && objdump -d a.out
之后我看到了这个
00000000004004f6 <foo>:
4004f6: 55 push %rbp
4004f7: 48 89 e5 mov %rsp,%rbp
4004fa: 48 c7 c3 7b 00 00 00 mov [=11=]x7b,%rbx
400501: 90 nop
400502: 5d pop %rbp
400503: c3 retq
0000000000400504 <main>:
400504: 55 push %rbp
400505: 48 89 e5 mov %rsp,%rbp
400508: e8 e9 ff ff ff callq 4004f6 <foo>
40050d: 90 nop
40050e: 5d pop %rbp
40050f: c3 retq
根据 x86-64 ABI %rbx
是一个被调用者保存寄存器,但在这段代码中 gcc
在修改之前没有将其保存在 foo
中。是因为我调用foo()
后没有在主函数中使用%rbx
还是因为gcc
没有提供这样的保证,我必须自己保存在[=17=中] 修改之前?
死记硬背地保存和恢复每个寄存器将是相当笨拙的代码。编译器在它编译的 C 代码中保存寄存器,但是你在这里是你自己的,gcc 不知道你的意图是什么。
组装器可让您深入了解引擎盖,但不会为您更换火花塞。
Gcc 将自动保存和恢复所有被调用者保存的寄存器它知道被使用。它知道自己使用的寄存器,但如果您告诉它,它只会知道内联汇编中使用的寄存器。这就是 'clobbers' 列表的用途:
void foo(void) {
__asm__ volatile ("mov 3, %%rbx" : : : "rbx");
}
现在编译器知道你是using/modifying rbx,所以如果需要它会保存它。
请注意,你真的想这样做而不是试图自己保存它,因为如果 gcc 也想在这个函数中使用寄存器,这样它只会被保存一次。