2 c assembly gcc inline-assembly
该手册说:
“允许使用与指定操作数编号匹配的操作数。如果在同一替代方案中将数字与字母一起使用,则该数字应最后一位。”
我不确定这是什么意思。
示例代码:
asm volatile("swap %0" : "=r" (value) : "0" (value));
Run Code Online (Sandbox Code Playgroud)
这就像将"+r"(value)输入/输出操作数拆分为单独的操作数(具有单独的C变量)以进行输入和输出的方式,同时仍然迫使它们选择相同的寄存器。
具体来说"0"就是“输入操作数与操作数0在同一寄存器中”,在这种情况下为"=r"(value)。因此,无论%0选择哪种寄存器,%1都将是同一寄存器。 从开始,操作数从左到右计数0。 操作数的相同的编号%0,%1当匹配约束是指到一个较早的操作数在ASM模板等应用。
我只看过它与匹配输出约束的输入约束一起使用。这样,您就可以从模板中忽略它,而不必担心编译器期望您的asm模板从一个reg复制到另一个reg。
使用,更容易为输入和输出使用相同的C变量"+r"(value)。 匹配约束对此毫无意义。
也许"+r"只是在更高的gcc版本中添加了,因为您确实看到了在读/写操作数会更容易时使用的匹配约束。
如果在同一替代方案中将数字和字母一起使用,则该数字应排在最后。”
这是在考虑约束的可能性,该约束使编译器可以选择多个约束。例如,"rm"让编译器选择寄存器或存储器。
"a0"在x86上,将选择EAX或与操作数相同的寄存器0。我不确定什么时候有用。也许可以与早期专家一起使用,以告诉编译器此输入与某个输出位于同一寄存器中仍然可以吗?但可选地,任何寄存器,例如with "r0"?
显然,如果您使用像"r0"您这样的约束(通常),则需要%1在asm模板中显式使用(或使用其具有的任何数字或命名的操作数),因为您不知道在给定周围的代码和优化级别的情况下编译器将选择哪个位置。
在调试约束时,使用包含约束的asm注释会很有用,其中包括您将要进行假设的约束。
asm ("swap %0 # other operand: %1 " : "=r"(output) : "0"(input));
Run Code Online (Sandbox Code Playgroud)
生成的asm将为%0和两次打印相同的寄存器名称%1。这种情况是微不足道的。在更复杂的情况下,它变得更加有趣。
就像您曾经使用过的一样"r"(input),您的代码可能恰好起作用,因为编译器确实为输入和输出选择了相同的reg(因为没有早期用户)。但是,当它因选择一个不同的reg而中断output(并期望的原始值input仍保持在其寄存器中)时,您可以通过查看选择的regs来调试它,然后意识到您假设他们选择了相同的reg,但是没有告诉编译器。