内联汇编在开头使用“jmp 0f”或“b 0f”

时间:2013-04-03 23:51:15

标签: assembly pipeline branch-prediction

更新

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


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

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

...其中b指令(ppc)是一个简短的jmp而mflr正在获取'链接寄存器'的内容 - 在某些方面类似于程序计数器。我也已经看过英特尔代码的这种事情(参见this问题中接受的答案)。

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

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


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

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

1 个答案:

答案 0 :(得分:1)

像这样的有趣代码往往发生在somethingelse中。这些代码的一些已知目的是:

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

这样的无条件分支是否会导致分支预测未命中处罚或其他类型的停顿是非常依赖CPU的。