我可以修改gcc内联汇编中的输入操作数吗

问题描述 投票:0回答:1
我们知道,如果我将

%eax

 设置为输入,那么我无法将其包含到破坏寄存器列表中。所以我的问题是,在汇编代码中修改 
%eax
 的值而不在破坏列表中进行任何声明是否合法?

__asm__ __volatile__("inc %0" :: "a"(num) : "%eax"); // illegal __asm__ __volatile__("inc %0" :: "a"(num)); // Can I modify %eax?
    
c gcc inline-assembly
1个回答
6
投票
不可以,如果汇编代码更改了输入寄存器,则还必须通过在约束中使用“+”而不是“=”将其列为输出寄存器或输入输出寄存器。

示例:

__asm__ __volatile__("..." : "+r"(num)); __asm__ __volatile__("..." : "=a"(dummy) : "a"(num)); __asm__ __volatile__("..." : "=r"(dummy) : "0"(num));
第一个示例将 

num

 指定为输入和输出。这将覆盖 
num
 的先前值,如果操作数被破坏而不是被设置为有用的值,这可能是不可取的。

第二个示例明确使用 eax 作为输入和输出。它将输出定向到

dummy

 变量,以免损坏实际输入变量 
num

第三个示例使用虚拟输出,以避免修改

num

,并且还避免显式指定 eax,从而允许编译器选择要使用的寄存器。 
"0"
 约束告诉编译器为此输入操作数使用与操作数 0 相同的寄存器。


内联汇编标签 wiki 链接了一些指南和教程,以及 GCC 手册,其中写道:

警告:请勿

修改仅输入操作数的内容(与输出相关的输入除外)。编译器假定从 asm 语句退出时,这些操作数包含与执行该语句之前相同的值。不可能使用 clobber 通知编译器这些输入中的值正在更改。一种常见的解决方法是将不断变化的输入变量与从未使用过的输出变量联系起来。但请注意,如果 asm 语句后面的代码不使用任何输出操作数,则 GCC 优化器可能会丢弃不需要的 asm 语句(请参阅 Volatile)。


    

© www.soinside.com 2019 - 2024. All rights reserved.