What is the difference between mov (%rax),%eax
and mov %rax,%eax
? I'm sure this is a simple question, but I can't find the answer anywhere.
Here is the original code that prompted my question:
mov -0x8(%rbp),%rax
mov (%rax),%eax
lea (%rax,%rax,1),%edx
mov -0x8(%rbp),%rax
mov %edx,(%rax)
mov -0x8(%rbp),%rax
mov (%rax),%eax
In AT&T syntax, the instruction:
mov (%rax), %eax # AT&T syntax
or, equivalently in Intel syntax:
mov eax, DWORD PTR [rax] ; Intel syntax
dereferences the memory address stored in rax
, reads a 32-bit value from that memory address, and stores it in the eax
register.
Because the memory address being dereferenced is stored in rax
, it can be a 64-bit address, which is necessary when running on a 64-bit operating system.
However, the data pointed to by that memory address is only 32 bits in size, so it can be stored in the 32-bit eax
register.
Note that this instruction will implicitly zero the upper 32 bits of the rax
register, so that the lower 32-bit half (called eax
) will contain the loaded data, and the upper 32-bit half will be empty.
The parentheses in AT&T syntax (or the square brackets in Intel syntax) are your clue that this instruction treats the contents of the register as if they were a pointer.
This is what makes it different from, for example:
mov %rcx, %rax # AT&T syntax
mov rax, rcx ; Intel syntax
This simply copies the contents of the rcx
register into the rax
register. There is no dereferencing being done. The values in the register(s) are acted on directly.
Note that the above example was similar to the other example from your question:
mov %rax, %eax # AT&T syntax (INVALID!)
mov eax, rax ; Intel syntax (INVALID!)
but not identical. This last case is actually an invalid instruction because there is an operand-size mismatch. If it were valid, the instruction would be copying the contents of the 64-bit rax
register into the 32-bit eax
register. Of course, this is impossible. Narrowing conversions are not allowed, so it will not assemble.
If you really wanted to do this, you would have to decide which half of the 64-bit value in rax
that you wanted to throw away. If you decided to throw away the upper bits and copy only the lower bits to eax
, you wouldn't need to do anything—just use eax
directly. If, however, you wanted to throw away the lower bits and use only the upper bits, you would first do a right-shift by 32.
Note that this is a fairly simple, general-reference question. You could have looked up the answer in any book on x86 assembly language, and a tutorial should have taught you about the significance of the parentheses/brackets syntax. Please see the x86 tag wiki for some tutorials and other general-reference information.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With