0

更新

将汇编的第二行更改为实际使用的助记符 ( mflr) 并在底部添加了更多信息。


我遇到了一些类似于以下的代码(使用 gcc)(释义):

#define SOME_MACRO( someVar ) \
do {                          \
  __asm__ (                   \
    "    b 0f\n"              \
    "0:  mflr %0\n"           \
    : "=r"( someVar )         \
  );                          \
} while(0)

...其中b指令(ppc)是一个简短的 jmp 并且mflr正在获取“链接寄存器”的内容——这在某些方面类似于程序计数器。对于英特尔代码,我也看到过这种情况(参见这个问题中接受的答案)。

该分支充当无操作...我的问题:这有什么目的?

我猜它与分支预测有关,但到目前为止,我只发现人们在搜索时使用这个成语的代码。


看起来我在分支预测猜测上错了。 mflr获取链接寄存器的内容。

所以,我的问题归结为:为什么需要分支。

4

1 回答 1

1

像这样有趣的代码往往发生在somethingelse. 此类代码的一些已知用途是:

  • 运行时状态检索;例如,在 x86 中,
    __asm__("call 0f\n0: pop %0\n" : "=r"(pc))
    是一种检索程序计数器的方法(IP 寄存器 - 这是隐藏的,不能直接访问,因此call将其推入堆栈的事实用于检索它)。
    请注意,由于红色区域,这在 64 位模式下的叶函数中使用是不安全的- 请参阅破坏红色区域的内联程序集。在 x86_64 上执行此操作的正确方法是
    asm("lea 0f(%%rip), %0\n0:\n" : "=r"(pc))
    利用 PC 相对寻址在 64 位模式下可能的事实。
  • 检测(调试/运行时跟踪),例如通过将跟踪代码/NOP槽放在那里,运行时跟踪实用程序可以修改以动态挂钩到代码中。Solaris DTrace 使用此类技术。
  • 在 ARM(和 64 位 x86)上,该方法还用于在代码中嵌入常量,用于与 PC 相关的负载。

像这样的无条件分支是否会导致分支预测丢失惩罚或其他类型的停顿是非常依赖于 CPU 的。

于 2013-04-04T16:48:20.093 回答