assembly - 当前指令旁边的 RIP 相关加载会发生什么情况?缓存命中?

标签 assembly x86 x86-64 cpu-architecture cpu-cache

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

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

假设它是相对较新的英特尔架构,例如 Kaby Lake。

最佳答案

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

由于指令提取,L2 中可能很热,但从那时起它可能已被逐出(L2 是 9 个 L1 缓存)。 所以最好的情况是在 L2 中取得成功

L1iTLB 和 L1dTLB 是分开的,因此如果这是从该页面加载的第一个数据,L1dTLB 中将会丢失。如果统一的二级 TLB 是受害者缓存,它可能会错过那里,甚至触发页面遍历,尽管在 L1iTLB 中很热,但是I don't know if L2TLB actually is a victim cache or not in recent Intel CPUs 。不过,这是有道理的;同一页面中的代码和数据通常很少见。 (尽管比同一中的代码和数据少见。)

另请参阅Why do Compilers put data inside .text(code) section of the PE and ELF files and how does the CPU distinguish between data and code?一些细节和讨论。但请注意,这是一个错误的说法,编译器在 x86 上不会这样做,因为这与提高性能相反(浪费 TLB 覆盖范围和缓存容量),这与 ARM 不同,在 ARM 上函数之间使用常量池这是正常的,因为 PC 相对寻址的范围非常有限。只有一些混淆器可以做到这一点。


Specifically, assume my RIP offset is +1. This suggests the data I want to read is right next to this instruction in memory

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] 从当前指令的机器代码中获取 -4 rel32 本身。

加载不会触发自修改代码管道核武器,只会触发存储,所以没关系。

关于assembly - 当前指令旁边的 RIP 相关加载会发生什么情况?缓存命中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62637943/

相关文章:

c++ - 精细控制GCC的输出

c - 在 c 代码中显示溢出的工具

assembly - 为什么我的代码显示垃圾?

assembly - 在堆栈上为 execve 创建一个 arg 数组

objective-c - 应用程序在 i386 上崩溃,在 x86_64 上工作

assembly - 使先前的内存存储对后续的内存加载可见

x86 - 如何查找 256 位 AVX 向量中的水平最大值

assembly - 为什么gcc会产生额外的寄信人地址?

x86 - AVX512 比较和交换

java - 在 Solaris 中设置 JDK 的库路径