Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 内联程序集-无用的中间副本指令_C_Assembly_Inline Assembly_Cpu Registers_Mov - Fatal编程技术网

C 内联程序集-无用的中间副本指令

C 内联程序集-无用的中间副本指令,c,assembly,inline-assembly,cpu-registers,mov,C,Assembly,Inline Assembly,Cpu Registers,Mov,我正在尝试编写一个调度程序来运行我们所说的“光纤”。 不幸的是,我并不真正习惯于编写内联汇编 typedef struct { //fiber's stack long rsp; long rbp; //next fiber in ready list struct fiber *next; } fiber; //currently executing fiber fiber *fib; 因此,第一项任务显然是为main功能创建一根光纤,使其可以挂

我正在尝试编写一个调度程序来运行我们所说的“光纤”。 不幸的是,我并不真正习惯于编写内联汇编

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
s编译成临时寄存器?我能设法摆脱它们吗

这个问题的第一个版本有来自
gcc-O0
的asm输出,还有更多的指令和临时命令

启用优化并不能消除它们

打开它们并不能消除临时性

它确实消除了一些额外的负载和存储。
fib
当然仍然存在于内存中,因为您将其声明为全局变量。
rax
是来自
malloc
的返回值,必须分配给内存中的
fib
。另外两行写入您的
fib
成员,这也是必需的

由于指定了寄存器输出,asm块无法直接写入内存。不过,使用内存约束很容易解决这一问题:

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

    call    malloc
    movq    %rax, fib(%rip)
    movq    %rsp, (%rax)
    movq    %rbp, 8(%rax)

你启用了优化吗?@Jester我一开始没有,但启用它们并不能消除临时性(请参见上面的编辑)。C不支持方法为什么
rbp
专用于你的光纤?当然,您需要保存/恢复所有寄存器
rsp
是唯一一个特殊的:您可以使用它来查找光纤堆栈(我假设您保存了其他寄存器)。@User1291:restore
rsp
,一次弹出所有其他寄存器,包括
rbp
。轰,你回来了。如果恢复的函数使用了
rbp
作为帧指针,则仍然是。您已从保存的上下文恢复,恢复除存储寄存器的内存之外的所有状态。(请记住,SystemV AMD64 ABI使用128B红色区域,因此在推送寄存器之前,您应该
添加$-128,%rsp
,以便将它们保存在当前函数的红色区域下方。将状态弹出回regs后,
sub$-128,%rsp
imm8
中包含128,但+128不包含,因此为双负)您可能应该使用
“=rm”
为编译器提供选项。在这种情况下,这无关紧要,但是如果您编写查看这些值的代码,编译器可以将它们保存在regs中,而不是执行存储->加载。(虽然理想情况下,有一种方法可以使C变量引用
rbp
的值,而不使用任何指令。)如果给定多选项约束,Clang有时会做出错误的选择,因此请检查代码中的情况。(事实上,我不记得当我看到clang在GNUC
asm
语句中表现不佳时的细节,但它可能会发生。)