assembly - Intel 上带偏移量和不带偏移量的内存获取之间的差异

标签 assembly x86 intel

Appel 在第 8 页的“Runtime Tags Aren't Necessary”中解释了如何通过标记指针来区分整数和指针:

Some implementations use a low-order tag of 0 for integers, then integer addition can then be done with the ordinary machine add instruction, and no shifting or correction will be necessary (since 2x + 2y = 2(x + y)). This requires that pointers have a tag of 1; but pointer-fetches can be done with odd offsets to compensate.

这个想法是:如果指针对齐,则该值是 2 或 4 的倍数。在这种情况下,低 1 或 2 位始终为零,并且可以设置为某个值来实现标记以区分整数来自指针。

英特尔语法中无偏移的无标记指针获取是:

mov    eax, DWORD PTR [ebx]

带有偏移量的等效标记指针获取是这样的:

mov    eax, DWORD PTR [ebx-0x1] 

两次提取的周期有什么区别?

最佳答案

寻址模式的复杂度一般对加载指令的吞吐量没有影响,但可能会对延迟产生1个周期的影响1 .

特别是简单寻址模式,即 [base][base + offset]哪里offset < 2048通常需要 4 个周期,而复杂模式(即任何不简单的事物)需要 5 个周期。这适用于加载到通用寄存器中:对于矢量加载,您通常会添加 1 或 2 个以上的周期。

因此,在您的情况下,您仅使用 base偏移量非常小,因此您应该获得 4 个周期的最快加载延迟。

这适用于 Intel,我不确定 AMD 是否适用。

详细信息位于英特尔优化指南中,但这里是 the source我能最快找到。

正如罗斯在评论中提到的,使用偏移量至少还有一个小缺点:指令是 one byte longer对于带有偏移量的版本(如果偏移量超出 -128 到 127 的范围,则会多出 4 个字节),这会稍微增加 icache 的压力。

<小时/>

1 不用说,这是针对 L1 中的命中的。如果你错过了 L1,延迟会更长 - 也许长很多,在这种情况下你是否仍然支付额外的周期可能并不重要(但我想你平均会这样做,因为错过了在计算地址之前不会开始)。

关于assembly - Intel 上带偏移量和不带偏移量的内存获取之间的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43893612/

相关文章:

x86 - 使用和不使用 IO 位图创建适当的任务状态段 (TSS) 结构?

assembly - 为什么这段代码在调用函数后两次弹出到同一个寄存器?

assembly - "fh"后缀对于 Intel 汇编中的 "38fh"这样的数字意味着什么

optimization - Intel Skylake 的统一调度器与 AMD Zen 的单独调度器

c - 这两个循环中哪个更快?

使用 RDTSC 的 nanosleep 循环计数

c - 如何查看我编译的机器语言/汇编代码?

c++ - 让编译器生成 adc 指令

assembly - 将 2 字节变量截断为 1 字节

performance - x86_64 : is IMUL faster than 2x SHL + 2x ADD?