17

在 Intel 体系结构 IA32 中,movl、movw 等指令不允许同时作为内存位置的操作数。例如,指令 movl (%eax), (%edx) 是不允许的。为什么?

4

4 回答 4

19

答案涉及对 RAM 的更全面了解。简单地说,RAM 只能处于两种状态,读模式或写模式。如果您希望将 ram 中的一个字节复制到另一个位置,则当您从读取切换到写入时,您必须在 RAM 之外有一个临时存储区域。

架构当然有可能拥有这样的 RAM 到 RAM 指令,但这将是一条高级指令,在微码中将转换为将数据从 RAM 复制到寄存器然后再复制回 RAM。或者,可以将 RAM 控制器扩展为具有这样一个临时寄存器,仅用于这种数据复制,但它不会为 CPU/硬件交互的增加复杂性提供太多好处。

编辑:值得注意的是,最近的进步,如混合内存立方体和高带宽内存是其中 RAM 拓扑变得更像 PCI-e 和直接 RAM 到 RAM 传输现在可能的架构,但这是由于支持逻辑对于技术,而不是 RAM 本身。在 CPU 架构中,这将是一次巨大的 RAM 块的形式,如 DMA,而不是单条指令的形式,加上 CPU 缓存的行为类似于传统 RAM,因此架构必须将其抽象为按照我原来的解释

编辑2:根据@PeterCordes 的评论,我最初的理解并不完全正确;x86 实际上确实有一些内存到内存指令。它们不适用于大多数指令(例如 movl 和 movw)的真正原因是保持指令编码复杂度较低,但它们本可以实现它们。但是,我最初的答案中的基本想法是,在 RAM 之外有一个以锁存器或寄存器形式存在的临时存储位置是正确的,但认为这就是这些指令不存在的原因的想法是不正确的。即使是 1970 年代的较旧芯片(例如 6502 和 8086)也具有内存到内存指令,您可以轻松地直接在 RAM 位置执行诸如 INC 之类的操作。

于 2012-08-14T17:28:46.663 回答
7

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 位、十进制、字符串
  • •适用于所有数据大小的内存-内存指令
  • • 特殊insns:crc、insque、polyf 和数百个演员表

这是 VAX 的 OpenBSD memcpy 源(指令集手册http://h20565.www2.hpe.com/hpsc/doc/public/display?docId=emr_na-c04623178):

https://es.osdn.jp/projects/openbsd-octeon/scm/git/openbsd-octeon/blobs/master/src/sys/lib/libkern/arch/vax/memcpy.S

         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 中编码。

于 2016-07-17T04:27:05.573 回答
3

据我所知,作为这种架构的一般规则,每条指令只允许一次内存访问。这是因为每条指令处理两次内存访问会使处理器的执行流水线复杂化。

于 2012-08-14T13:40:52.563 回答
0

RAM 支持输入和输出,但不支持复制。因此,内存到内存的移动实际上是内存到 CPU 到内存的移动。理论上可以实现这样的指令,但可能不是,因为它不是很实用。

以下是实施此类指令需要考虑的一些事项:

  • 我们使用什么临时存储位置?寄存器?

  • 如果我们使用寄存器,我们会劫持哪个寄存器?

不提供这样的指令将上述问题留给程序员。

于 2012-08-14T13:41:12.017 回答