93
  • 是什么rep; nop意思?
  • pause指令一样吗?
  • 它与rep nop(没有分号)相同吗?
  • 与简单nop指令有什么区别?
  • 它在 AMD 和 Intel 处理器上的行为是否不同?
  • (奖励)这些说明的官方文档在哪里?

这个问题的动机

另一个问题的评论中进行了一些讨论后,我意识到我不知道rep; nop;在 x86(或 x86-64)程序集中是什么意思。而且我在网上找不到很好的解释。

我知道这rep是一个前缀,意思是“重复下一条指令cx时间”(或者至少在旧的 16 位 x86 程序集中是这样)。根据Wikipedia 上的这个汇总表,它似乎rep只能与movs, stos, cmps,lods一起使用scas(但也许这个限制在较新的处理器上被删除了)。因此,我认为rep nop(没有分号)会重复一次nop操作cx

然而,经过进一步的搜索,我变得更加困惑。似乎rep; nopandpause 映射到完全相同的操作码,并且pause具有与 just 不同的行为nop。2005 年的一些旧邮件说了不同的话:

  • “尽量不要烧太多电”
  • “它相当于 'nop' 只是使用 2 字节编码。”
  • “这对英特尔来说很神奇。它就像'nop,但让另一个 HT 兄弟运行'”
  • “它在英特尔上暂停,在 Athlon 上快速填充”

有了这些不同的意见,我无法理解正确的含义。

它在 Linux 内核中使用(在i386x86_64上),连同这条评论:/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */它也在BeRTOS 中使用,带有相同的评论。

4

2 回答 2

81

rep; nop确实与pause指令(操作码F390)相同。它可能用于不支持该pause指令的汇编程序。在以前的处理器上,这根本没有做任何事情,就像nop在两个字节中一样。在支持超线程的新处理器上,它用作向处理器提示您正在执行自旋循环以提高性能的处理器。来自英特尔的指令参考

提高自旋等待循环的性能。在执行“自旋等待循环”时,奔腾 4 或英特尔至强处理器在退出循环时会遭受严重的性能损失,因为它检测到可能的内存顺序违规。PAUSE 指令向处理器提示代码序列是一个自旋等待循环。处理器在大多数情况下使用此提示来避免内存顺序冲突,从而大大提高处理器性能。因此,建议在所有自旋等待循环中放置一条 PAUSE 指令。

于 2011-08-16T23:22:37.673 回答
17

rep nop= F3 90 = 的编码pause,以及它如何在不支持的旧 CPU 上解码pause


lock不适用于指令的前缀(除了)实际上会被现有 CPU 忽略。

文档说使用rep不适用的指令是“保留的,可能导致不可预测的行为”,因为未来的CPU 可能会将其识别为某些新指令的一部分。 一旦他们使用 建立任何特定的新指令编码f3 xx,他们就会记录它如何在旧 CPU 上运行。(是的,x86 操作码空间非常有限,以至于他们会做这样疯狂的事情,是的,它使解码器变得复杂。)

在这种情况下,这意味着您可以pause在 spinloops 中使用而不会向后破坏 compat。不知道的旧 CPUpause会将其解码为 NOP 而不会造成任何伤害,正如英特尔的 ISA ref 手册条目pause所保证的那样。在新 CPU 上,您将受益于节能/HT 友好性,并且当您正在旋转的内存确实发生变化并且您离开自旋循环时,避免了内存排序错误推测。


链接到英特尔手册和x86 标签 wiki 信息页面上的大量其他好东西

另一种无意义rep前缀成为新 CPU 上的新指令的情况: lzcntF3 0F BD /r. 在不支持该指令的 CPU 上(在其 CPUID 中缺少 LZCNT 功能标志),它解码为rep bsr,其运行方式与bsr. 所以在旧的 CPU 上,它产生32 - expected_result, 并且在输入为零时是未定义的。

但是tzcntbsf对非零输入做同样的事情,所以编译器可以并且确实使用,tzcnt即使不能保证目标 CPU 将其作为tzcnt. AMD CPU 有 fast tzcnt、 slow bsf,在 Intel 上它们都很快。只要对正确性无关紧要(您不依赖标志设置,或者在 input=0 情况下保留目标未修改的行为),让它tzcnt在支持它的 CPU 上解码是有帮助的。


rep可能永远不会以不同方式解码的无意义前缀的一种情况:rep ret默认情况下,gcc 在针对“通用”CPU 时使用(即不针对特定 CPU 使用-marchor -mtune,而不针对 AMD K8 或 K10。)这将比任何人早几十年可以使 CPU 解码rep ret为除 之外的任何内容ret,因为它存在于大多数 Linux 发行版的大多数二进制文件中。请参阅 `rep ret` 是什么意思?

于 2015-11-10T20:46:44.853 回答