rep; nop
是什么意思?pause
指令相同?rep nop
相同(没有分号)?nop
指令有什么区别?在another question的评论中进行了一些讨论之后,我意识到我不知道x {(或x86-64)汇编中rep; nop;
的含义。而且我也无法在网上找到一个好的解释。
我知道rep
是一个前缀,意味着“重复下一条指令cx
次”(或者至少它是旧的16位x86程序集中) 。根据此summary table at Wikipedia,似乎rep
只能与movs
,stos
,cmps
,lods
,scas
一起使用(但可能在新处理器上删除了此限制)。因此,我认为rep nop
(没有分号)会重复nop
次操作cx
次。
然而,经过进一步搜索,我更加困惑。似乎rep; nop
和pause
map to the exactly same opcode和pause
的行为与nop
的行为略有不同。有些old mail from 2005说了不同的话:
有了这些不同的意见,我无法理解正确的意思。
它在Linux内核中使用(在i386和x86_64上)以及此评论:/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
它也是being used in BeRTOS,具有相同的注释。< / p>
答案 0 :(得分:66)
rep; nop
确实与pause
指令(操作码F390
)相同。它可能用于尚不支持pause
指令的汇编程序。在以前的处理器上,这根本没有做任何事情,就像nop
一样,只有两个字节。在支持超线程的新处理器上,它用作处理器的提示,您正在执行spinloop以提高性能。来自Intel's instruction reference:
改善了自旋等待循环的性能。当执行“自旋等待循环”时,Pentium 4或Intel Xeon处理器在退出循环时会遭受严重的性能损失,因为它检测到可能的内存顺序违规。 PAUSE指令向处理器提供代码序列为自旋等待循环的提示。在大多数情况下,处理器使用此提示来避免内存顺序违规,从而大大提高了处理器性能。因此,建议在所有自旋等待循环中放置PAUSE指令。
答案 1 :(得分:8)
忽略不适用于指令的前缀。但是,未来的CPU可以使用该字节序列来编码新指令。 (是的,x86操作码空间是如此有限,以至于他们做了这样的疯狂的事情,是的,这使得解码器变得复杂。)
在这种情况下,表示您可以在spinloops中使用pause
而不会向后突破compat 。不知道pause
的旧CPU会将其解码为NOP而不会造成任何伤害。在新CPU上,您可以获得省电/ HT友好性的好处,并且当您正在旋转的内存确实发生变化并且您正在离开旋转循环时,avoiding memory-ordering mis-speculation。
在x86标签维基信息页面上链接到英特尔手册和大量其他好东西:https://stackoverflow.com/tags/x86/info
另一个无意义rep
前缀成为新CPU指令的情况:lzcnt
为F3 0F BD /r
。在不支持该指令的CPU上(在其CPUID中缺少LZCNT功能标志),它将解码为rep bsr
,其运行方式与bsr
相同。因此,在旧CPU上,它会生成32 - expected_result
,并且在输入为零时未定义。
一个无意义的rep
前缀可能永远不会以不同的方式解码:rep ret
默认情况下由gcc用于定位“通用”CPU(即不使用{{1}定位特定CPU }或-march
,而不是针对AMD K8或K10。)几十年前,任何人都可以制作一个将-mtune
解码为除rep ret
以外的任何内容的CPU,因为它存在于大多数二进制文件中在大多数Linux发行版中。见What does `rep ret` mean?