GCC 扩展 Asm - 了解 clobbers 和暂存寄存器的使用
Posted
技术标签:
【中文标题】GCC 扩展 Asm - 了解 clobbers 和暂存寄存器的使用【英文标题】:GCC extended Asm - Understanding clobbers and scratch registers usage 【发布时间】: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));
这个例子和句子的第二部分告诉我们什么?与其他代码相比,此代码的附加值是多少?这段代码是否会导致更有效的内存刷新(如本章前面所述)?
【问题讨论】:
这个例子我也看不懂。 【参考方案1】:与其他代码相比,此代码的附加值是什么?
哪个“另一个”?在我看来,如果你有这种指令,你几乎必须使用这段代码(唯一的选择是通用的memory
clobber)。
情况是,您需要将寄存器传递给指令,但实际操作数在内存中。因此,您需要确保两件独立的事情,即:
-
您的指令获取寄存器中的操作数。这就是
r
约束的作用。
编译器知道您的asm
块读取内存,因此*x
和*y
的值必须在块之前刷新。这就是 m
约束的用途。
您不能使用%3
代替%1
,因为m
约束使用内存引用语法。例如。而%1
可能类似于%r0
或%eax
,%3
可能是(%r0)
,(%eax)
,甚至只是some_symbol
。不幸的是,您的假设指令不接受这些类型的操作数。
【讨论】:
值得一提的是,这种事情的主要用例是当您想自己构建寻址模式时,尽管在这种情况下,您需要告诉您引用的编译器而不是*x
整个数组,而不仅仅是第一个元素。请参阅***.com/questions/1956379/att-asm-inline-c-problem/… 进行讨论。
顺便说一句,如果您告诉编译器您将修改指针寄存器并使用早期破坏器,它通常确实会为虚拟内存操作数使用另一个寄存器。 ("+&r"(buffer), "m" (*(const char (*)[]) *buffer)
.) 如果你对编译器撒谎并忽略了 early-clobber,你可以避免这种情况,但是如果任何其他操作数与该指针具有相同的值,那么你就有一个潜在的错误。以上是关于GCC 扩展 Asm - 了解 clobbers 和暂存寄存器的使用的主要内容,如果未能解决你的问题,请参考以下文章
GCC 内联汇编错误:变量 '%al' 的 asm 说明符与 asm clobber 列表冲突
asm、asm volatile 和 clobbering memory 的区别
扩展 GCC asm 中多个输入和输出操作数的正确用法是啥?