在 x64 中,使用 "pop [RAX]",值暂时存储在哪里?

In x64, using "pop [RAX]", where is the value temporarily stored?

我找到了解释直接内存到内存复制在 x86 平台上是不可能的,除非值存储在两者之间的某个地方。

mov rax,[RSI]
mov [RDI],rax

我使用 pop 大量使用 64 位内存写入,它似乎直接将值从内存复制到内存,没有任何明显的 "middle-man"。

写入前和读取后的值在哪里?

pop [rax] 是进行内存到内存操作的方法之一。弹出的值可能存储在两者之间的某个位置,但这是一个实现细节。这些答案的意思是,使用 modr/m 字节作为操作数的指令最多只能有一个内存操作数。这些是大多数指令,但不是像 movsb [rdi], [rsi] 这样的指令,它们的操作数内置在指令中。

临时位置是 CPU 内部某处的缓冲区,不属于架构状态。

在像 Skylake 这样的现代 x86 上,pop [mem] 解码为 2 微指令,所以大概第一个微指令是 pop 进入内部寄存器,第二个是存储。

我们知道现代 x86 CPUs 确实保留了一些额外的逻辑寄存器供微码和像这样的多 uop 指令使用。它们以与体系结构寄存器相同的方式重命名到物理寄存器文件中。例如http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/ 提及 "some extra architectural registers for internal use"。 Henry 称它们为 "architectural" 寄存器,但这可能是一个令人困惑的术语。他只是指逻辑而不是物理,就像 架构寄存器。这些临时寄存器不(AFAIK)跨指令边界使用,仅在一条 x86 指令中使用。

原始 8086 是非流水线的(指令预取除外),因此实现 pop [mem] 的内部微代码或逻辑可能只是从某个专用缓冲区加载然后存储。与 add [mem], reg 类似,但加载地址与存储地址不同,并且不通过 ALU 馈送。

direct memory-to-memory copy is not possible on x86.

您可能指的是诸如 Why IA32 does not allow memory to memory mov? 上已接受的答案之类的事情,不幸的是,对原因的解释完全错误且极具误导性。

这是一个指令 encoding 限制使得 mov [mem], [mem] 不可能,而不是 CPU 内部的限制。参见
pop [mem] 是其中之一,因为其中一个内存操作数是 implicit。即使是原始的 8086 也可以做到这一点。


I make heavy use of 64bit writes to memory using pop

如果前端 uop 吞吐量或端口 2/3 压力是瓶颈,请考虑使用 128 位 SSE 从堆栈加载,然后使用 movlpsmovhps 存储 64 位一半.在当前的 Intel CPUs(如 Skylake)上,movhps [mem], xmm0 是单 uop 指令。 (实际上是微融合;所有存储都是存储地址 + 存储数据。但是无论如何,不​​需要像 pextrq 的无用内存目标形式那样的端口 5 shuffle uop)。

或者,如果您的目的地是连续的,则执行 128 位或 256 位副本。

pop [mem] 的用例,但它并不好,而且在主流 Intel 上通常不会比 pop reg / mov [mem], reg 快,因为它仍然是 2 微指令。它的代码大小安全,但不需要 tmp reg。

https://agner.org/optimize/