Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
like image 878
Chemita Gomez Avatar asked Mar 10 '23 08:03

Chemita Gomez


1 Answers

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.

like image 148
Cody Gray Avatar answered Mar 24 '23 11:03

Cody Gray