什么是“代表” nop;“是指在x86程序集?
-
rep; nop
什么?rep; nop
意思? - 这与
pause
指令是一样的吗? - 它是否与
rep nop
(没有分号)相同? - 简单的
nop
指令有什么区别? - 它在AMD和Intel处理器上的performance有何不同?
- (奖金)这些说明的正式文件在哪里?
这个问题的动机
在对另一个问题的评论进行了一些讨论之后,我意识到我不知道是什么rep; nop;
rep; nop;
是指在x86(或x86-64)程序集中。 而且我在网上找不到一个好的解释。
我知道rep
是一个前缀,意思是“重复下一个指令cx
次” (或者至less是在旧的16位x86汇编中)。 根据维基百科的这个汇总表 ,似乎rep
只能用于movs
, cmps
, cmps
, lods
, scas
(但是也许这个限制在更新的处理器上被删除了)。 因此,我认为rep nop
(不用分号)会重复一次nop
操作。
然而,经过进一步的search,我更加困惑。 rep; nop
似乎是rep; nop
rep; nop
和pause
映射到完全相同的操作码 , pause
有一点不同,只是nop
行为。 2005年的一些旧邮件说了不同的事情:
- “尽量不要烧太多的权力”
- “这相当于只用2字节编码的”nop“。
- “这是intel的魔法,它就像'但是让另一个HT兄弟运行'”
- “在intel和intel Athlon上快速填充是暂停的”
有了这些不同的意见,我不明白正确的意思。
它被用在Linux内核(在i386和x86_64上 )以及这个注释: /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
BeRTOS也正在使用,同样的评论。
rep; nop
rep; nop
的确与pause
指令(操作码F390
)相同。 它可能用于不支持pause
指令的汇编程序。 在以前的处理器上,这只是没有做任何事情,就像nop
一样,只是两个字节。 在支持超线程的新处理器上,它被用作向处理器提示您正在执行spinloop以提高性能。 从英特尔的指令参考 :
改善了旋转等待循环的性能。 当执行“旋转等待循环”时,Pentium 4或Intel Xeon处理器在退出循环时会受到严重的性能损失,因为它会检测到可能的内存顺序违规。 PAUSE指令向处理器提供代码序列是自旋等待循环的提示。 处理器使用此提示来避免在大多数情况下违反内存顺序,这大大提高了处理器的性能。 出于这个原因,build议在所有旋转等待循环中放置一个PAUSE指令。
不适用于指令的前缀将被忽略。 但是,未来的CPU可以使用该字节序列来编码新的指令。 (是的,x86操作码空间是非常有限的,他们做这样的疯狂的东西,是的,这使得解码器复杂。)
在这种情况下, 这意味着您可以在spinloops中使用pause
而不会破坏向后兼容 。 不知道pause
旧CPU会将其解码为NOP,而不会造成任何损害。 在新的CPU上,您可以获得省电/ HT友好的好处,并避免当您正在旋转的内存发生变化并且您正在离开旋转循环时内存sorting错误的猜测 。
链接到英特尔的手册以及x86标签wiki信息页上的其他好东西: https : //stackoverflow.com/tags/x86/info
另一种无意义的lzcnt
前缀成为新CPU的新指令: lzcnt
是F3 0F BD /r
。 在不支持该指令的CPU上(在其CPUID中缺lessLZCNTfunction标志),它解码为rep bsr
,它与bsr
运行相同。 所以在旧CPU上,它产生32 - expected_result
,并且当input为零时是未定义的。
一个无意义的rep
前缀的情况下,可能永远不会解码不同:默认情况下,gcc针对“通用”CPU时使用rep ret
(即没有使用-march
或-mtune
定位特定CPU,而不是针对AMD K8或K10。 )任何人都可以制作一个解码rep ret
的CPU作为ret
以外的任何东西,因为它在大多数Linux发行版中都存在于大多数二进制文件中。 看看`rep ret`是什么意思?