"不支持mov"GCC内联汇编程序

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装配输出?

Chr*_*odd 8

总的来说,使用约束将值放入正确的寄存器而不是显式移动会更好:

asm("syscall" :: "D" ((uint64_t)code), "a" ((uint64_t)231));
Run Code Online (Sandbox Code Playgroud)

如果有用的话,编译器可以在代码中提前提升移动,如果值可以安排在正确的寄存器中,甚至可以完全避免移动...