Mic*_*son 4 c optimization gcc inline-assembly
在使用GCC的内联汇编程序功能时,我尝试创建一个立即退出该过程的函数,类似于_ExitC标准库.
以下是相关的源代码:
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
}
Run Code Online (Sandbox Code Playgroud)
这适用于调试版本(带-O0),但只要我在任何级别打开优化,我都会收到以下错误:
immediate_exit.c: Assembler messages:
immediate_exit.c:4: Error: unsupported for `mov'
Run Code Online (Sandbox Code Playgroud)
所以我查看了两个版本的汇编程序输出(.cfi*为了清楚起见,我删除了指令和其他内容,如果这是一个问题,我可以再次添加它).调试版本:
immediate_exit:
.LFB0:
pushq %rbp
movq %rsp, %rbp
movl %edi, -4(%rbp)
mov -4(%rbp), %rdi
mov $231, %rax
syscall
popq %rbp
ret
Run Code Online (Sandbox Code Playgroud)
优化版本:
immediate_exit:
.LFB0:
mov %edi, %rdi
mov $231, %rax
syscall
ret
Run Code Online (Sandbox Code Playgroud)
因此,优化版本试图将32位寄存器edi放入64位寄存器rdi,而不是从中加载rbp,我认为这是导致错误的原因.
现在,我可以通过将'm'指定为寄存器约束来解决此问题code,这会导致GCC rbp无论优化级别如何加载.但是,我宁愿不这样做,因为我认为编译器及其作者对于放置东西比我更好.
所以(最后!)我的问题是:我如何说服GCC使用rdi而不是edi装配输出?
总的来说,使用约束将值放入正确的寄存器而不是显式移动会更好:
asm("syscall" :: "D" ((uint64_t)code), "a" ((uint64_t)231));
Run Code Online (Sandbox Code Playgroud)
如果有用的话,编译器可以在代码中提前提升移动,如果值可以安排在正确的寄存器中,甚至可以完全避免移动...