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

Hoo*_*lum 6 c assembly gcc inline-assembly

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

好的,这按预期工作;src变量被复制到dst变量,然后dst变量加 5。srcdst的值分别为 1 和 6 。

int src = 1;
int dst = 0;

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

但是当我尝试这个时,srcdst的值仍然是 1 和 6。我期望src的值为 1,dst的值为 5,因为将 5 添加到dst(自从 MOV 以来,dst 的值为 0)操作已被删除)应该有输出 5。

int src = 1; int dst = 0;

 asm ("add $5, %[DEST]"
     : [DEST] "=r" (dst)
     : [SRC] "r" (src));
Run Code Online (Sandbox Code Playgroud)

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

int dst = 0;

     asm (
         "add $5, %[DEST]"
         : [DEST] "=r" (dst));
Run Code Online (Sandbox Code Playgroud)

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

Win*_*ute 6

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

 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
Run Code Online (Sandbox Code Playgroud)

第二部分不起作用,因为您从不使用%[SRC],并且因为%[DEST]不是输入操作数,所以它的值不会进入计算。您只需获取 gcc 决定使用的寄存器中的内容即可。第三部分也因同样的原因而失败。

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

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

因为现在你有一个%1带有值的输入操作数dst和一个不同的输出操作数%0,其值将被写入dst,并且你永远不会使用%1。这个符号可以让你写

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

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

asm("add $5, %0"
    : "=r" (dst)
    : "0" (dst));
Run Code Online (Sandbox Code Playgroud)

这告诉 gcc%0允许作为输入操作数,并且它的值为dst是gcc手册的相关部分。

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

asm ("add $5, %[DEST]"
     : [DEST] "=r" (dst)
     : "[DEST]" (dst));
Run Code Online (Sandbox Code Playgroud)