【问题标题】:GCC extended Asm - Understanding clobbers and scratch registers usageGCC 扩展 Asm - 了解 clobbers 和暂存寄存器的使用
【发布时间】:2018-03-02 10:31:06
【问题描述】:

从关于 Extended ASM - Clobbers and Scratch Registers 的 GCC 文档中,我发现很难理解以下解释和示例:

这是一个虚构的平方和指令,它需要两个 指向内存中浮点值的指针并产生一个浮点数 点寄存器输出。请注意,x 和 y 在 asm 参数,一次指定访问的内存,一次指定一个 asm 使用的基址寄存器。

好的,第一部分明白了,现在继续:

您通常不会浪费 通过这样做注册,因为 GCC 可以为两者使用相同的寄存器 目的。但是,将 %1 和 %3 同时用于 x in 这个 asm 并期望它们是相同的。事实上,%3 很可能不是 登记。它可能是对对象的符号内存引用 由 x 指向。

失去了我。

例子:

asm ("sumsq %0, %1, %2"
     : "+f" (result)
     : "r" (x), "r" (y), "m" (*x), "m" (*y));

这个例子和句子的第二部分告诉我们什么?与其他代码相比,此代码的附加值是多少?这段代码是否会导致更有效的内存刷新(如本章前面所述)?

【问题讨论】:

  • 这个例子我也看不懂。

标签: gcc assembly inline-assembly


【解决方案1】:

与其他代码相比,此代码的附加值是什么?

哪个“另一个”?在我看来,如果你有这种指令,你几乎必须使用这段代码(唯一的选择是通用的memoryclobber)。

情况是,您需要将寄存器传递给指令,但实际操作数在内存中。因此,您需要确保两件独立的事情,即:

  1. 您的指令获取寄存器中的操作数。这就是 r 约束的作用。
  2. 编译器知道您的asm 块读取内存,因此*x*y 的值必须在块之前刷新。这就是 m 约束的用途。

您不能使用%3 代替%1,因为m 约束使用内存引用语法。例如。而%1 可能类似于%r0%eax%3 可能是(%r0)(%eax),甚至只是some_symbol。不幸的是,您的假设指令不接受这些类型的操作数。

【讨论】:

  • 值得一提的是,这种事情的主要用例是当您想自己构建寻址模式时,尽管在这种情况下,您需要告诉您引用的编译器而不是 *x整个数组,而不仅仅是第一个元素。请参阅stackoverflow.com/questions/1956379/att-asm-inline-c-problem/… 进行讨论。
  • 顺便说一句,如果您告诉编译器您将修改指针寄存器并使用早期破坏器,它通常确实会为虚拟内存操作数使用另一个寄存器。 ("+&r"(buffer), "m" (*(const char (*)[]) *buffer).) 如果你对编译器撒谎并忽略了 early-clobber,你可以避免这种情况,但是如果任何其他操作数与该指针具有相同的值,那么你就有一个潜在的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多