将内联汇编片段合并在一起

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 在这两种情况下都是输出。