What is the difference between "mov (%rax),%eax" and "mov %rax,%eax"?

16,334

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 tag wiki for some tutorials and other general-reference information.

Share:
16,334
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    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