Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MOVing between two memory addresses

Tags:

I'm trying to learn assembly (so bear with me) and I'm getting a compile error on this line:

mov byte [t_last], [t_cur] 

The error is

error: invalid combination of opcode and operands 

I suspect that the cause of this error is simply that its not possible for a mov instruction to move between two memory addresses, but half an hour of googling and I haven't been able to confirm this - is this the case?

Also, assuming I'm right that means I need to use a register as an intermediate point for copying memory:

mov cl, [t_cur] mov [t_last], cl 

Whats the recommended register to use (or should I use the stack instead)?

like image 205
Justin Avatar asked Aug 19 '09 10:08

Justin


People also ask

Does memory address change?

Yes, they change. The OS loads the process into different offsets each time it launches, and anything allocated with new or malloc is very likely to get different addresses each time the code is run.

What does MOV instruction do?

The MOV instruction moves data bytes between the two specified operands. The byte specified by the second operand is copied to the location specified by the first operand. The source data byte is not affected.

Is memory and address same?

Therefore, the address space is the set of addresses generated by programs as they reference instructions and data. The memory space holds the actual main memory locations that are directly addressable for processing.


2 Answers

Your suspicion is correct, you can't move from memory to memory.

Any general-purpose register will do. Remember to PUSH the register if you are not sure what's inside it and to restore it back once done.

like image 192
Federico klez Culloca Avatar answered Sep 28 '22 02:09

Federico klez Culloca


That's correct, x86 machine code can't encode an instruction with two explicit memory operands (arbitrary addresses specified in [])

  • Why isn't movl from memory to memory allowed?
  • What x86 instructions take two (or more) memory operands?

Whats the recommended register

Any register you don't need to save/restore.

In all the mainstream 32-bit and 64-bit calling conventions, EAX, ECX, and EDX are call-clobbered, so AL, CL, and DL are good choices. For a byte or word copy, you typically want a movzx load into a 32-bit register, then an 8-bit or 16-bit store. This avoids a false dependency on the old value of the register. Only use a narrow 16 or 8-bit mov load if you actively want to merge into the low bits of another value. x86's movzx is the analogue of instructions like ARM ldrb.

    movzx   ecx,  byte [rdi]       ; load CL, zero-extending into RCX     mov    [rdi+10], cl 

In 64-bit mode, SIL, DIL, r8b, r9b and so on are also fine choices, but require a REX prefix in the machine code for the store so there's a minor code-size reason to avoid them.

Generally avoid writing AH, BH, CH, or DH for performance reasons, unless you've read and understood the following links and any false dependencies or partial-register merging stalls aren't going to be a problem or happen at all in your code.

  • Why doesn't GCC use partial registers?
  • How exactly do partial registers on Haswell/Skylake perform? Writing AL seems to have a false dependency on RAX, and AH is inconsistent

(or should I use the stack instead)?

First of all, you can't push a single byte at all, so there's no way you could do a byte load / byte store from the stack. For a word, dword, or qword (depending on CPU mode), you could push [src] / pop [dst], but that's a lot slower than copying via a register. It introduces an extra store/reload store-forwarding latency before the data can be read from the final destination, and takes more uops.

Unless somewhere on the stack is the desired destination and you can't optimize that local variable into a register, in which case push [src] is just fine to copy it there and allocate stack space for it.

See https://agner.org/optimize/ and other x86 performance links in the x86 tag wiki

like image 34
Peter Cordes Avatar answered Sep 28 '22 03:09

Peter Cordes