所以,我有这个代码按预期工作:
#include <stdio.h>
int main () {
unsigned int i;
int x=5;
__asm__ ("movl %1, %0;"
"subl %2, %0;"
: "=r" (i)
: "r" (4), "r" (x)
: "0");
__asm__ ("movl %1, %0;"
: "=r" (x)
: "r" (i)
: "0");
printf("%d\n", x);
return 0;
}
如何将两个调用合并为一个?
答案 0 :(得分:1)
这些是无意义的asm块开头。经验法则是,如果你使用mov
,你可能做错了。此外,即使您声称它按预期工作,代码也会被破坏。没有什么能阻止编译器将%2
分配给与产生错误代码的%0
相同的寄存器。你很幸运,它并没有发生在你身上。
无论如何,第二个asm块只是将i
复制到x
。因此合并的asm看起来像:
__asm__ ("movl %2, %0;"
"subl %3, %0;"
"movl %0, %1;"
: "=&r" (i), "=r" (x)
: "r" (4), "r" (x));
这当然仍然很愚蠢,但至少在技术上并不是错误的。注意第一个输出的早期clobber &
修饰符。但是,第二种情况并非如此。
答案 1 :(得分:1)
第一个__asm__
集:i <- 4 - x
。第二组:x <- i
。它们可以合并为:
__asm__ ("subl %k2, %k0" : "=r" (x) : "0" ((unsigned)(4)), "g" (x));
不需要clobbers(除非你想包括"cc"
,这总是由gcc承担),并且在读取之前没有输入被覆盖的问题。 "g"
约束表示寄存器,内存或立即操作数是可接受的。在这种情况下,输出应为:"-1"
:x <- 4 - 5
注意:第一个__asm__
的输出应为=&r
。此外,两者都不应将%0
列为破坏 - 这是隐含的,因为%0
在两种情况下都是输出。