有必要在内联汇编中初始化所有使用的寄存器吗?

时间:2018-10-12 20:33:47

标签: gcc assembly inline-assembly

我正在使用gcc测试简单的内联汇编代码。而且我发现以下代码的结果意外:

#include <stdio.h>
int main(void) {
    unsigned x0 = 0, x1 = 1, x2 = 2;
    __asm__ volatile("movl %1, %0;\n\t"
                     "movl %2, %1"
                     :"=r"(x0), "+r"(x1)
                     :"r"(x2)
                     :);
    printf("%u, %u\n", x0, x1);
    return 0;
}

打印结果为1, 1,而不是预期的1, 2。然后,我用-S选项编译了代码,发现gcc生成的代码为

movl %eax, %edx;
movl %edx, %eax;

%0%2使用相同的寄存器,为什么?

我想让gcc生成

movl %eax, %edx;
movl %ecx, %eax;

如果我在输入约束中添加"0"(x1),则gcc将生成上面的代码。这是否意味着所有寄存器都需要在内联汇编中使用之前进行初始化?

1 个答案:

答案 0 :(得分:2)

将我的评论移至“答案”,以便可以关闭此问题。

要防止编译器为输入和输出重用寄存器,可以使用early clobber约束(例如=&r (x)),该约束通知编译器与该寄存器关联的寄存器。参数是

  

在使用输入操作数完成指令之前编写。

虽然这可能是一件好事(因为它减少了在调用asm之前必须提供的寄存器数量),但它也会引起问题(如您所见)。因此,请确保在写入输出之前已完成使用所有输入,或使用&告诉编译器不要执行此优化。

为完整起见,我还要指出,使用内联汇编通常是bad idea