libdis
,并尝试查找哪些指令访问内存。参考这两个指令:
mov eax, [ebx + 10]
lea eax, [ebx + 10]
在
libdis
中,这两种情况都列为指令类型insn_mov
,并且地址操作数在两种情况下具有相同的标志。因此,我唯一能判断内存是否被访问的方法是查看指令助记符。因此我的问题是:LEA是唯一使用不会实际访问内存的内存操作数的指令吗?任何参考链接都可以。
libdis
,并尝试查找哪些指令访问内存。mov eax, [ebx + 10]
lea eax, [ebx + 10]
libdis
中,这两种情况都列为指令类型insn_mov
,并且地址操作数在两种情况下具有相同的标志。因此,我唯一能判断内存是否被访问的方法是查看指令助记符。prefetch
指令系列(包括prefetcht1、prefetcht2、prefetcht3和prefetchnta)要求处理器将那些即将需要的内存行拉入高速缓存中。然而,英特尔的文档明确表示,错误地址传递给预取指令也不会导致任何故障。这是为了使软件能够在未经检查的情况下传递潜在的越界地址,以便数据可以在执行这些检查的同时被预先获取。LEA
不同,预取指令也没有“输出”。0F 1F /0
,它采用内存寻址操作数。根据英特尔的手册:nop
的操作码字节放在未映射页面的末尾,并且如果无法读取包括ModR/M和位移字节在内的完整指令,则代码提取故障。这与此问题无关。
nop
之外的任何特殊硬件即可处理它。 整个指令格式与大多数指令相同。prefetch
/ prefetchw
和其他答案中提到的nop
。
任何使用全零掩码进行AVX512掩码加载或存储的指令,例如vmovaps [rdi]{k1}, zmm1
。或者使用AVX的vmaskmovps
/vpmaskmovd
、AVX2 gather/AVX512 gather或scatter。所有这些指令都对无效地址执行故障抑制。(速度较慢,但没有实际的内存访问。)
invlpg m8
接受一个ModRM,它指定了一个虚拟地址。(特权指令)。它不会从该地址中加载数据,而是使该地址的TLB条目以及存储在页行走器中的更高级别的页目录条目无效。
verr
/verw
- 验证读取或写入段:它们采用ModRM寻址模式,并检查地址是否符合段限制,设置FLAGS。(并且有最近的微代码更新。verw
还清除内部CPU缓冲区,以便操作系统可用于缓解L1TF/MDS漏洞)。
rep cmpsb
或其他RCX = 0的字符串指令执行零次迭代,不访问隐式内存操作数[RDI]
或[RSI]
。我认为这意味着即使出现错误的地址,它也不会出错。微码肯定足够慢了。
cldemote
(Intel Tremont中新引入的指令)- 是一种相反于预取的性能提示,用于将数据推送到共享L3以加速另一个核心对其的首次访问。在不支持此功能的硬件上,该指令解码为NOP。预取不会因地址无效而故障(尽管它们可能在需要微代码帮助抑制故障时变慢);手册对于cldemote
没有100%明确的说明,但确实将其称为一种推测提示。
在某些处理器实现中,CLDEMOTE指令可能会在页表中设置
A
位但不设置D
位。如果在缓存中未找到该行,则该指令将被视为NOP。
MPX bndcl bnd, r/m64
/ bndcu
/ bndcn
/ bndmk
- 内存源形式内置了LEA:操作部分的伪代码甚至说 TEMP ← LEA(mem);
。寄存器源形式直接使用寄存器值作为地址。正如手册所说,该指令不会引起任何内存访问,并且不读/写标志位。(它会在越界时引发#BR
异常)。请注意,MPX已经被弃用。
clflush
/ clflushopt
/ clwb
都采用内存操作数来指定要刷新或回写到DRAM的缓存行,对于使用非易失性DIMMs以确保提交到NV存储器的情况很有用(因此与cldemote
不同,这些操作不仅仅是CPU可以随意丢弃的提示)。它们确实需要一个有效的虚拟地址,并且确实会影响相应缓存行的MESI状态。但如果L1d缓存中没有该缓存行,则不会将其带入并再次刷新。我认为它会驱逐所有核心的缓存,因此一个核心在一条线上不断使用clflush
会影响另一个核心对其进行读写。
CLFLUSHOPT指令可以在所有权限级别下使用,并且与字节加载相关的所有许可检查和故障都适用(此外,CLFLUSHOPT指令允许刷新执行-只读段中的线性地址)。类似于加载操作,CLFLUSHOPT指令在页表中设置A位,但不设置D位。
MONITOR
将内存地址作为隐式DS:RAX/EAX/AX
,而不是编码在ModRM中。它实际上并没有从中加载数据,只是设置核心以注意到其他核心何时更改该内存。然而,它的工作原理类似于加载操作。(假设将行置于MESI共享状态,以便在写入之前,它可以注意到另一个核心使其无效。)
MONITOR指令按照加载操作的顺序与其他内存事务排序。该指令受到与字节加载相关的许可检查和故障的约束。类似于加载操作,MONITOR在页表中设置A位,但不设置D位。
umonitor
(用户空间版本)与此相同。
bt/btc/btr/bts
,这些指令确实访问内存,但不一定在指令中指定的有效地址处访问。 - Nate Eldredge