2015-08-09 131 views
1

众所周知,当存储器到存储器的移动不可能时,MOV指令允许寄存器注册移动。为什么是这样?x86程序集MOV指令 - 寄存器到寄存器和存储器到存储器

我读过here内存到内存的移动是不允许的,因为它使CPU复杂化,并且RAM必须处于读模式或写模式,并且有任何给定的指令。有没有人能够在此扩大?为什么RAM必须处于读取模式和写入模式?在单个指令中,如何从寄存器中读取和写入数据,而不是从RAM中读取数据?

+2

使用movs [b/w/d]指令可以将一个字节,一个字或一个双字从一个存储位置复制到另一个存储位置。 http://x86.renejeschke.de/html/file_module_x86_id_203.html –

+0

这是合理的写作,使事情变得复杂,因为它应该是原子。搜索读取 - 修改 - 写入。 –

+8

在x86的情况下,实际的原因是指令编码对于两个内存(有效地址)操作数没有空间。解决方法是某些指令具有隐式操作数,例如上面提到的'MOVS',甚至是'PUSH'/'POP',并且这些操作数可以执行内存到内存的拷贝。 – Jester

回答

2

因为英特尔这样设计的,并且具有编码的灵活性or [di], [si]即使在使用or al, [si]时也会使指令更长。

你读到关于读或写模式的内容没有意义,因为or [rdi], rax做了读 - 修改 - 写。所以总是有两个指令,即使除了几条可以读取一个位置并写入另一个位置的指令(见下文)之外。

当英特尔设计x86时,他们决定限制编码为的指令的复杂性,因为每个指令只允许为一个操作数选择寻址模式。另一个寄存器操作数在也选择寻址模式的字节中由3位选择。 (或者3位作为操作码的一部分,或者3位填充到其他地方......当前的x86指令编码有这么多特殊情况......)

x86-64增加了一个额外的位来增加寄存器的数量,但没有改变任何根本。 (虽然它确实添加了RIP相对寻址。)

请参阅https://stackoverflow.com/tags/x86/info的英特尔手册链接。

大多数x86指令采取这些形式

op r, r/m32 
op r/m32, r 

在GP寄存器的r是一个一个,和R/M32是寄存器或存储器的操作数,这取决于寻址模式。

这两个版本通常是不同的操作码,即使它们共享相同的助记符。因此,从硬件/机器语言POV中,内存源和内存目标版本是两个单独的指令。 mov本身有许多不同的操作码,适用于各种特殊情况。 (特别是如果您计算移入/移出控制寄存器)。

正如人们在注释中注意到的那样,存在读和写存储器的指令,其中至少一个操作数具有不在通常的mod/rm中编码的隐式位置寻址模式编码。

  • movs:string move。 (除rep之外不要使用,超慢)
  • push r/m32(例如push [rax])。