将内联汇编片段合并在一起
Merging together inline assembly snippets
所以,我的代码按预期工作:
#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;
}
如何将两个调用合并为一个?
这些是无意义的 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));
这当然仍然很愚蠢,但至少在技术上没有错。注意第一个输出的 early-clobber &
修饰符。然而,第二次不需要它。
第一个 __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
在这两种情况下都是输出。
所以,我的代码按预期工作:
#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;
}
如何将两个调用合并为一个?
这些是无意义的 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));
这当然仍然很愚蠢,但至少在技术上没有错。注意第一个输出的 early-clobber &
修饰符。然而,第二次不需要它。
第一个 __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
在这两种情况下都是输出。