Gcc 是否有必要初始化内联程序集中使用的所有寄存器?
我正在使用gcc测试简单的内联汇编代码。我发现以下代码的结果出乎意料:Gcc 是否有必要初始化内联程序集中使用的所有寄存器?,gcc,assembly,inline-assembly,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)
#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;
}
%0
和%2
使用相同的寄存器,为什么
我想让gcc生成,比如
movl %eax, %edx;
movl %ecx, %eax;
如果我将“0”(x1)
添加到输入约束中,gcc将生成上面的代码。这是否意味着在内联汇编中使用之前,所有寄存器都需要初始化?将我的注释移动到“答案”中,以便关闭此问题
为了防止编译器对输入和输出都重新使用寄存器,可以使用约束(例如=&r(x)
),它通知编译器与参数关联的寄存器已被删除
在指令使用输入操作数完成之前写入
虽然这可能是一件好事(因为它减少了调用asm之前必须提供的寄存器数量),但它也可能导致问题(如您所见)。因此,在写入输出之前,请确保已使用完所有输入,或者使用&
告诉编译器不要进行此优化
为了完整起见,我还要指出,使用内联asm通常是一个问题。您需要查看约束。将EarlyLobber修饰符添加到
%0
的输入约束中会起作用:“=&r(x0)”
。谢谢大家!@戴维德沃尔费尔德
movl %eax, %edx;
movl %ecx, %eax;