【发布时间】:2016-03-31 20:22:22
【问题描述】:
正如您可能已经猜到的那样,问题是gcc 是自动保存被调用者保存寄存器还是应该我自己做?我以为gcc 会为我做到这一点,但当我编写这段代码时
void foo(void) {
__asm__ volatile ("mov $123, %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 $0x7b,%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()之后没有在main函数中使用%rbx还是因为gcc没有提供这样的保证,我必须在修改前自己保存在foo中?
【问题讨论】:
-
GCC 不注意你的内联汇编,它只是逐字发出。做正确的事取决于你。
-
这将是一个相当笨拙的代码,它会死记硬背地保存和恢复每个寄存器。
-
正如@OliverCharlesworth 所写。你一个人在这里,gcc不知道你的意图是什么。
-
它将保存受其编译的 C 代码影响的寄存器。组装机可以让您进入引擎盖,但它不会为您更换火花塞。
-
您可以使用extended inline assembly 告诉编译器您破坏了哪些寄存器,然后它将保存它们。