使用内联汇编在C中添加值

时间:2015-01-25 11:53:50

标签: c gcc assembly inline-assembly

我试图掌握C(ATT装配)中内联装配的基础知识,所以我通过添加2个变量来练习。

好的,这样可以按预期工作;将 src 变量复制到 dst 变量,然后将 dst 变量添加为5. src 和 dst 分别为1和6。

int src = 1;
int dst = 0;

asm ("mov %[SRC], %[DEST]\n\t"
     "add $5, %0"
     : [DEST] "=r" (dst));
     : [SRC] "r" (src));

但是当我尝试这个时, src dst 的值仍然是1和6.我期待 src 拥有将值1和 dst 赋值为5,因为将<5>添加到 dst (由于MOV操作已被删除,其值为0)应该具有输出5。 / p>

int src = 1;    int dst = 0;

 asm ("add $5, %[DEST]"
     : [DEST] "=r" (dst)
     : [SRC] "r" (src));

然后我尝试使用以下代码删除 src 作为输入操作数,但现在 dst 获取值11。

int dst = 0;

     asm (
         "add $5, %[DEST]"
         : [DEST] "=r" (dst));

现在我有点困惑它是如何运作的。我误解了什么?

1 个答案:

答案 0 :(得分:3)

代码的第一部分按预期工作。有

 mov %[SRC], %[DEST]        ; copies %[SRC] into %[DEST], which is now 1
 add $5, %0                 ; adds 5 to %0 (which is %[DEST]), so that's 6

第二部分不起作用,因为您从不使用%[SRC],并且因为%[DEST]不是输入操作数,所以它的值不会进入计算。你只是得到了gcc决定使用的寄存器。第三部分出于同样的原因失败了。

要使其工作,您需要将dst指定为输入和输出操作数,因为您既使用其值又更改它。但是,这不起作用:

asm("add $5, %0"  // This does not work!
    : "=r" (dst)
    : "r" (dst));

因为现在你有一个值为%1的输入操作数dst和一个不同的输出操作数%0,其值将写入dst,你永远不会使用{{ 1}}。这种表示法允许你写

%1

但这当然是不必要的低效率。要使用单个寄存器执行此操作,您需要使用匹配约束,如下所示:

asm("mov %1, %0; add $5, %0"  // needlessly inefficient!
    : "=r" (dst)
    : "r" (dst));

这告诉gcc允许asm("add $5, %0" : "=r" (dst) : "0" (dst)); 作为输入操作数,并且它的值为%0Here是gcc手册的相关部分。

使用命名操作数,最后看起来像这样:

dst