x86 Assembly MOV instruction - Register to Registe

2019-08-05 17:06发布

问题:

It's known that the MOV instruction allows register to register moves while memory to memory moves are not possible. Why is this?

I've read here that memory to memory moves are disallowed because it complicates the CPU and that RAM has to be in either a read mode or write mode with any given instruction. Is anyone able to expand on this? Why does RAM have to be in either read mode and write mode? How is it possible to read and write from registers but not from RAM within a single instruction?

回答1:

Because Intel designed it that way, and having the flexibility to encode or [di], [si] would have made the instruction longer even when you were using or al, [si].

What you read about read or write mode doesn't make sense, because or [rdi], rax does a read-modify-write. So there always were instructions that did both, even apart from the few instructions that could read one location and write another (see below).

When Intel designed x86, they decided to limit the complexity of instruction encoding by only allowing a choice of addressing modes for one operand per instruction. The other register operand is selected by 3 bits in the byte that also selects an addressing mode. (Or 3 bits as part of the opcode, or 3 bits stuffed somewhere else... current x86 instruction encoding has so many special cases...)

x86-64 added an extra bit to double the amount of registers, but didn't change anything fundamental. (It did add RIP-relative addressing, though.)

See links to Intel manuals from https://stackoverflow.com/tags/x86/info.

Most x86 instructions take one of these forms

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

The r being one of the gp registers, and the r/m32 being a register or memory operand, depending on the addressing-mode.

The two versions are usually different opcodes, even though they share the same mnemonic. So from a hardware / machine-language POV, the memory source and memory dest versions are two separate instructions. mov itself has many different opcodes, for various special cases. (especially if you count move to/from control registers.)

As people note in comments, there are instructions that both read and write memory, with at least one of the operands having an implicit location not encoded in the usual mod/rm addressing mode encoding.

  • movs: string move. (don't use except with rep, it's super slow)
  • push r/m32 (e.g. push [rax]).