内联汇编 - 无用的中间复制指令

时间:2016-05-05 14:41:36

标签: c assembly inline-assembly cpu-registers mov

我试图编写一个调度程序来运行我们称之为" fiber"。 不幸的是,我并不习惯于编写内联汇编。

typedef struct {
    //fiber's stack
    long rsp;
    long rbp;

    //next fiber in ready list
    struct fiber *next;

} fiber;

//currently executing fiber
fiber *fib;

因此,第一项任务是 - 显然 - 为main函数创建一条光纤,以便它可以被暂停。

int main(int argc, char* argv[]){

    //create fiber for main function
    fib = malloc(sizeof(*fib));
    __asm__(
        "movq %%rsp, %0;"
        "movq %%rbp, %1;"
         : "=r"(fib->rsp),"=r"(fib->rbp)
         );

    //jump to actual main and execute
    __asm__(...);

}

这会被编译为

    movl    $24, %edi   #,
    call    malloc  #
#APP
# 27 "scheduler.c" 1
    movq %rsp, %rcx;movq %rbp, %rdx;    # tmp92, tmp93
# 0 "" 2
#NO_APP
    movq    %rax, fib(%rip) # tmp91, fib
    movq    %rcx, (%rax)    # tmp92, MEM[(struct fiber *)_3].rsp
    movq    %rdx, 8(%rax)   # tmp93, MEM[(struct fiber *)_3].rbp

为什么将mov编译成临时寄存器?我可以以某种方式摆脱它们吗?

这个问题的第一个版本有gcc -O0的asm输出,有更多的指示和临时值。

启用优化并没有摆脱它们。

1 个答案:

答案 0 :(得分:3)

  

打开它们并没有摆脱临时工作

它确实摆脱了一些额外的装载和存储。 fib当然仍然存在于内存中,因为您将其声明为全局变量。 rax是必须分配给内存中malloc的{​​{1}}的返回值。其他两行写入您的fib成员,这也是必需的。

由于您指定了寄存器输出,因此asm块无法直接写入内存。但是,通过内存约束很容易解决:

fib

这将产生:

__asm__(
    "movq %%rsp, %0;"
    "movq %%rbp, %1;"
     : "=m"(fib->rsp),"=m"(fib->rbp)
     );