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

标签 c gcc inline-assembly

我们知道,如果我将 %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 相同的寄存器。

关于我可以修改gcc内联汇编中的输入操作数吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48381184/

相关文章:

安装FFmpeg时gcc无法创建可执行文件

铛-错误: non-ASM statement in naked function is not supported

c++ - 写入超过内核允许一次打开的文件的最佳方法是什么?

c - 维吉尼亚如何停止增量

c++ - "vperm v0,v0,v0,v17"和未使用的 v0 有什么作用?

c - init-on-first-use 函数的 gcc 属性

delphi - 为什么某些汇编指令没有记录在案

c - C 中的内联汇编。错误的翻译

c# - void 数据类型和 void 指针的实际用途是什么?

c - 函数返回指针的行为不明确?