在英特尔架构IA32中,像movl,movw这样的指令不允许同时作为内存位置的操作数。例如,不允许使用指令movl(%eax),(%edx)。为什么呢?
答案 0 :(得分:15)
答案是更全面地了解RAM。简单地说,RAM只能处于两种状态,即读模式或写模式。如果您希望将ram中的一个字节复制到另一个位置,则当您从读取切换为写入时,必须在RAM之外具有临时存储区域。
架构当然可以有这样的RAM到RAM指令,但它将是一个高级指令,在微码中将转换为将数据从RAM复制到寄存器然后再复制到RAM。或者,可以扩展RAM控制器以使这种临时寄存器仅用于此数据复制,但它不会为CPU /硬件交互的复杂性带来更多好处。 / p>
编辑:值得注意的是,混合内存多维数据集和高带宽内存等最近的进步是一种架构,其中RAM拓扑变得更像PCI-e,直接RAM到RAM传输现在可能,但这是由于技术的支持逻辑,而不是RAM本身。在CPU架构中,这将是一次大块RAM的形式,如DMA,而不是单个指令的形式,加上CPU缓存的行为类似于传统RAM,因此架构必须将其抽象为根据我原来的解释
EDIT2:根据@PeterCordes评论,我原来的理解并不完全正确;事实上,x86确实有一些内存到内存指令。它们不适用于大多数指令(例如movl和movw)的真正原因是保持指令编码复杂度低,但是他们可以实现它们。但是,我原来的答案中的基本思想是,在锁存器或寄存器形式的RAM之外存在临时存储位置是正确的,但是这就是为什么这些指令不存在的想法不是。即使是20世纪70年代的老式芯片,如6502和8086,也有内存到内存指令,您可以直接在RAM位置轻松执行INC等操作。这是通过将存储器提取直接锁存到ALU并再次返回存储器而不通过指令集使用的寄存器来实现的。
答案 1 :(得分:5)
ia32是x86,x86是从intel 8086(iAPX 86)演变而来的。它是基于8位指令集的小巧便宜的芯片,没有" mov"有两个显式内存操作数。
维基百科的作者给出了关于8086的指令编码的解释:
由于受8位处理器启发的紧凑编码,大多数指令是单地址或双地址操作,这意味着结果存储在其中一个操作数中。最多一个操作数可以在内存中,但是这个内存操作数也可以是目标,而另一个操作数,即源,可以是寄存器或立即数。单个内存位置通常也可以用作源和目标,除其他因素外,还可以进一步提高与当时大多数8位机器相当的代码密度。(/通常优于)。
有一些具有存储器存储器指令的CISC(单个指令用于操作两个存储器操作数)。讲座https://www.cis.upenn.edu/~milom/cis501-Fall05/lectures/02_isa.pdf说VAX可以编码内存记忆指令:
DEC VAX(PDP-11的虚拟地址扩展):1977
- •可变长度指令:1-321字节!!!
- •14个GPR + PC +堆栈指针+条件代码
- •数据大小:8,16,32,64,128位,十进制,字符串
所有数据大小的- •内存存储器指令
- •特殊情节:crc,insque,polyf和数百个演员
这是VAX的OpenBSD memcpy源代码(指令集手册http://h20565.www2.hpe.com/hpsc/doc/public/display?docId=emr_na-c04623178):
movq 8(ap),r1 /* r1 = src, r2 = length */
movl 4(ap),r3 /* r3 = dst */
...
1: /* move forward */
cmpl r2,r0
bgtru 3f /* stupid movc3 limitation */
movc3 r2,(r1),(r3) /* move it all */
" movc3"这里的指令有两个存储器操作数,这些地址存储在寄存器中。
x86有几个"字符串"将执行内存操作的指令(* s,尤其是movs - http://x86.renejeschke.de/html/file_module_x86_id_203.html),但该指令将使用预定义的寄存器SI& DI作为地址(隐式操作数),两个存储器操作数仍然不能在x86中编码。
答案 2 :(得分:3)
据我所知,作为该架构的一般规则,每条指令只允许一次内存访问。这是因为每条指令处理两次内存访问会使处理器的执行流程复杂化。
答案 3 :(得分:1)
RAM支持输入和输出,但不支持复制。因此,内存到内存的移动实际上是内存到CPU到内存的移动。理论上可以实现这样的指令,但可能不是因为它不太实用。
以下是实施此类指令需要考虑的一些事项:
我们使用什么临时存储位置?注册?
如果我们使用一个寄存器,我们会劫持哪一个?
不提供此类指令会将上述问题留给程序员。