%eax
设置为输入,那么我无法将其包含到破坏寄存器列表中。所以我的问题是,在汇编代码中修改
%eax
的值而不在破坏列表中进行任何声明是否合法?
__asm__ __volatile__("inc %0" :: "a"(num) : "%eax"); // illegal
__asm__ __volatile__("inc %0" :: "a"(num)); // Can I modify %eax?
示例:
__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)。