当前指令旁边的RIP相对负载会发生什么情况?缓存命中?



我正在阅读Agner Fog关于x86汇编的书。我想知道在这种情况下RIP相对寻址是如何工作的。具体来说,假设我的 RIP 偏移量为 +1。这表明我要读取的数据就在内存中的此指令旁边。

这段数据可能已经提取到L1指令缓存中。假设这些数据不在L1d中,那么CPU上究竟会发生什么?

让我们假设它是一个相对较新的英特尔架构,如 Kaby Lake。

是的,在 L1i 缓存和 uop 缓存中可能很热。 该页面在L1iTLB中也很热门。 但所有这些都与数据加载无关。

由于指令获取,L2 中可能很热,但从那时起它可能已被驱逐(L2 是 NINE wrt。一级缓存(。所以最好的情况是在 L2 中命中

L1iTLB 和 L1dTLB 是分开的,因此如果这是从该页面加载的第一个数据,它将在 L1dTLB 中丢失。 如果统一的第二级 TLB 是受害者缓存,尽管在 L1iTLB 中很热,但它可能会错过那里,甚至触发页面浏览,但我不知道 L2TLB 是否真的是受害者缓存在最近的英特尔 CPU 中。 不过,这是有道理的;同一页面中的代码和数据通常很少见。 (尽管不如同一中的代码和数据罕见。

参见 为什么编译器将数据放在 PE 和 ELF 文件的 .text(code( 部分中,以及 CPU 如何区分数据和代码?以获取一些细节和讨论。 但请注意,这是一个错误的说法,编译器在 x86 上不会这样做,因为它对性能有帮助(浪费 TLB 覆盖占用空间和浪费缓存容量(相反,不像在 ARM 上,函数之间的常量池是正常的,因为 PC 相对寻址的范围非常有限。 只有一些混淆者可能会这样做。


具体来说,假设我的 RIP 偏移量为 +1。 这表明我要读取的数据就在内存中的此指令旁边

rel32相对于当前指令的末尾。 所以不,不是旁边;那将是一个 1 字节的差距。

例如像这样:

movzx eax, byte [rip + 1]  
ret
; could be a page boundary here
load_target:  int3        ; db 0xcc

请注意,如果指令在页面边界的 0 或 1 字节内结束,则[RIP+1]可能与使用该寻址模式的指令位于不同的缓存行甚至页中。

那 1 个字节甚至可能是ret,因此该指令可能已经在执行,而前端已经(或曾经(从另一行或页面获取,就像它本来会那样。 我认为您对从包含当前指令的同一行获取的情况更感兴趣。 不妨说mov eax, [RIP - 4]从当前指令的机器代码中获取 rel32 本身-4

加载不会触发自修改代码管道核弹,只会存储,所以这很好。

最新更新