rep; nop
是什么意思?pause
指令一样吗?rep nop
(没有分号)一样吗?nop
指令有什么区别?这个问题的动机
在另一个问题的评论中进行了一些讨论之后,我意识到我不知道rep; nop;
在x86 (或x86-64)程序集中意味着什么。而且我在网上找不到一个很好的解释。
我知道rep
是一个前缀,意思是“重复下一个指令cx
时间”(或者至少在旧的16位x86程序集中是这样)。根据这个维基百科汇总表,rep
似乎只能与movs
、stos
、cmps
、lods
、scas
一起使用(但在较新的处理器上可能消除了这个限制)。因此,我认为rep nop
(没有分号)会重复nop
操作cx
次数。
然而,经过进一步的搜索,我更加困惑了。rep; nop
和pause
映射到完全相同的操作码以及pause
似乎有着与nop
不同的行为。一些2005年的旧邮件说了不同的话:
有了这些不同的意见,我无法理解正确的含义。
它正在Linux内核中使用(在i386和64上),以及下面的注释:/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
,它也是在BeRTOS中使用,具有相同的注释。
发布于 2011-08-16 23:22:37
rep; nop
确实与pause
指令(操作码F390
)相同。它可能用于不支持pause
指令的汇编程序。在以前的处理器上,这只是不起任何作用,就像nop
一样,只是用了两个字节。在支持超线程的新处理器上,它被用作对处理器的提示,提示您正在执行一个spinloop以提高性能。来自英特尔指令参考
提高自旋等待循环的性能。当执行“自旋等待循环”时,奔腾4或Intel Xeon处理器退出循环时会受到严重的性能损失,因为它检测到可能的内存顺序违规。暂停指令向处理器提供了一个提示,表明代码序列是自旋等待循环。在大多数情况下,处理器使用这个提示来避免内存顺序冲突,这大大提高了处理器的性能。因此,建议在所有自旋等待循环中放置暂停指令。
发布于 2015-11-10 20:46:44
rep nop
= F3 90 = pause
的编码,以及它如何在不支持pause
的旧CPU上解码。
lock
**)前缀(不适用于指令的除外)实际上被现有CPU忽略。
文档称,使用不适用于is 的指令的将“保留并可能导致不可预测的行为”,因为未来的CPU可能会将其识别为某些新指令的一部分。一旦使用f3 xx
建立任何特定的新指令编码,就会记录其在旧CPU上的运行方式。(是的,x86的操作码空间是如此的有限,以至于他们会做这种疯狂的事情,而且是的,这会使解码器变得复杂。)
在本例中,pause
意味着您可以在自旋循环中使用,而无需向后中断compat。不知道pause
的旧CPU会将其解码为NOP,不会造成任何伤害,英特尔的ISA ref手册pause
保证了这一点。在新的CPU上,您可以获得节能/ HT友好性的好处,而当您正在运行的内存发生变化时,避免记忆有序的错误推测就会发生变化,而您将留下自旋循环。
链接到英特尔的手册和大量其他x86标签wiki信息页面上的好东西
另一种情况是,无意义的rep
前缀成为新CPU上的新指令:lzcnt
是F3 0F BD /r
。在不支持该指令的CPU上(在其CPUID中缺少LZCNT功能标志),它将解码为rep bsr
,运行与bsr
相同的代码。因此,在旧CPU上,它生成32 - expected_result
,并在输入为零时未定义。
但是tzcnt
和bsf
对非零输入做同样的事情,所以编译器可以也确实使用tzcnt
,即使不能保证目标CPU以tzcnt
的形式运行。AMD有快速的tzcnt
,慢的bsf
,而在英特尔,它们都是快速的。只要正确性不重要(您不依赖于标记设置,或者在input=0情况下不依赖于目标未修改的行为),在支持它的CPU上让它解码为tzcnt
是有帮助的。
一种无意义的rep
前缀可能永远不会有不同的解码方式: gcc在针对“通用”CPU时默认使用rep ret
(即不使用-march
或-mtune
来访问特定的CPU,也不使用K8或K10)。再过几十年,任何人都可以将rep ret
解码为ret
以外的任何东西,因为它存在于大多数Linux发行版的大多数二进制文件中。请参阅卑劣?
https://stackoverflow.com/questions/7086220
复制相似问题