2013-04-04 135 views
4

我知道什么时候使用一个皮匠列表(例如列出一个在程序集中修改过的寄存器,以便它不会被选作输入寄存器等),但是我无法将头围绕在早期约束&。如果列出你的输出,那么这不意味着输入不能使用选定的寄存器(除了匹配的数字约束)?何时在扩展GCC内联汇编中使用earlyclobber约束?

例如:

asm(
    "movl $1, %0;" 
    "addl $3, %0;" 
    "addl $4, %1;" 
    "addl %1, %0;" 
    : "=g"(num_out) 
    : "g"(num_in) 
    : 
); 

&甚至需要为输出变量?编译器应该知道为输出选择的寄存器,因此不知道用于输入。

回答

10

默认情况下,编译器假定在写入任何输出寄存器之前,所有输入都将被消耗,因此它允许两者使用相同的寄存器。如果可能的话,这会导致更好的代码,但是如果这种假设是错误的,事情将会发生灾难性的失败。 “早期的clobber”标记是告诉编译器这种输出将在所有输入被消耗之前被写入的一种方式,因此它不能与任何输入共享一个寄存器。

+0

因此,这意味着编译器可以假设我输入所用的'eax'寄存器在需要输出时不再需要,因此它会重用'eax'寄存器?这是否意味着原始问题中代码中的输出事实上需要'&'修饰符? – 2013-04-04 19:29:14

+2

由于多种原因,您的代码有误。例如,你正在修改一个输入寄存器。 – 2013-04-04 20:31:47

+0

x86的典型“earlyclobber”是使用扩展乘法,其中'EDX:EAX' /'RDX:RAX' _implicitly_是输出。当这些指令用于多输入'asm()'语句中时,在早期输出“消耗”内容之后,'d'和'a'寄存器不能用作输入。如果该特定输入操作数被多次使用,编译器会将其放入_different_寄存器。 – 2013-04-19 08:43:17