在x64中,使用“ pop [RAX]”将值临时存储在哪里?

z0r*_*g's 2 x86 assembly x86-64 cpu-architecture

我找到了答案,说明无法在x86平台上直接存储到内存的复制,而不能将值存储在两者之间。

mov rax,[RSI]
mov [RDI],rax
Run Code Online (Sandbox Code Playgroud)

我大量使用pop来对内存进行64位写入,pop似乎直接将值复制到内存中,而没有任何明显的“中间人”。

值在写入之前但在读取之后在哪里?

Pet*_*des 5

临时位置是CPU内部某个缓冲区,它不是体系结构状态的一部分。

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

我们知道,现代的x86 CPU确实保留了一些额外的逻辑寄存器,供诸如此类的微代码和多uu指令使用。它们与架构寄存器一样被重命名到物理寄存器文件中。例如http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/提到“一些内部使用的额外体系结构寄存器”。亨利称它们为“建筑”登记册,但这可能会使术语混淆。他只是表示逻辑而不是物理,例如架构寄存器。这些临时寄存器(AFAIK)不能跨指令边界使用,只能在一条x86指令中使用。

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

在x86上无法直接进行内存到内存的复制。

您可能是指诸如为什么IA32不允许内存移动到内存? 不幸的是,对原因的解释只是明显的错误,而且极具误导性。

这是一条指令编码的限制,这使得mov [mem], [mem]不可能,而不是CPU内部的限制。请参阅哪些x86指令采用两个(或更多)内存操作数?
pop [mem]是其中之一,因为其中一个内存操作数是隐式的。即使是原始的8086也可以做到这一点。


我使用pop大量使用64位写入内存

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

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

有一些用例,pop [mem]但效果并不理想,并且在主流Intel上通常不会比pop reg/ 快,mov [mem], reg因为它仍然只有2微秒。它具有安全的代码大小,并且不需要tmp reg。

参见https://agner.org/optimize/