在使用 GCC 的内联汇编器功能时,我尝试制作一个立即退出进程的函数,类似于_Exit
C 标准库中的函数。
这是相关的源代码:
void immediate_exit(int code)
{
#if defined(__x86_64__)
asm (
//Load exit code into %rdi
"mov %0, %%rdi\n\t"
//Load system call number (group_exit)
"mov $231, %%rax\n\t"
//Linux syscall, 64-bit version.
"syscall\n\t"
//No output operands, single unrestricted input register, no clobbered registers because we're about to exit.
:: "" (code) :
);
//Skip other architectures here, I'll fix these later.
#else
# error "Architecture not supported."
#endif
}
这适用于调试构建(使用-O0
),但只要我在任何级别打开优化,我都会收到以下错误:
immediate_exit.c: Assembler messages:
immediate_exit.c:4: Error: unsupported for `mov'
因此,我查看了两个构建的汇编器输出(.cfi*
为了清楚起见,我删除了指令和其他内容,如果有问题,我可以再次添加)。调试版本:
immediate_exit:
.LFB0:
pushq %rbp
movq %rsp, %rbp
movl %edi, -4(%rbp)
mov -4(%rbp), %rdi
mov $231, %rax
syscall
popq %rbp
ret
和优化版本:
immediate_exit:
.LFB0:
mov %edi, %rdi
mov $231, %rax
syscall
ret
因此,优化版本试图将 32 位寄存器edi
放入 64 位寄存器rdi
,而不是从 加载它rbp
,我认为这是导致错误的原因。
现在,我可以通过将 'm' 指定为 的寄存器约束来解决此问题code
,这会导致 GCC 从任何rbp
优化级别加载。但是,我宁愿不这样做,因为我认为编译器及其作者比我更清楚将东西放在哪里。
所以(最后!)我的问题是:我如何说服 GCC 使用rdi
而不是edi
汇编输出?