【问题标题】:Can I modify input operands in gcc inline assembly我可以在 gcc 内联汇编中修改输入操作数吗
【发布时间】:2018-01-22 12:02:54
【问题描述】:

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

__asm__ __volatile__("inc %0" :: "a"(num) : "%eax"); // illegal
__asm__ __volatile__("inc %0" :: "a"(num));       // Can I modify %eax?

【问题讨论】:

  • 您的代码将编译 + 汇编,但随后可能会在运行时以奇怪的方式中断,或者有时不会中断,具体取决于周围的代码和优化选项。这意味着单元测试不足以证明 inline-asm 正确或安全。

标签: c gcc inline-assembly


【解决方案1】:

不,如果汇编代码改变了一个输入寄存器,它也必须被列为一个输出寄存器,或者作为一个输入输出寄存器,通过在约束中使用“+”而不是“=”。

例子:

__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 相同的寄存器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    • 2011-09-07
    • 2018-07-28
    • 1970-01-01
    • 1970-01-01
    • 2012-10-20
    相关资源
    最近更新 更多