0
votes

Let's say that register %eax contains address 0x100 and at address 0x100 there is a value 0x3999.

From what I understand "%eax" returns the address, for example movl $0x4050, %eax, moves the value 0x4050 at address 0x100.

But "(%eax)" returns the value at the address, meaning 0x3999. So what does movl $0x4050, (%eax) do? Is it going to treat the constant 0x3999 as an address?

2
movl $0x4050, %eax puts the value 0x4050 into the register eax. It does not in any way use the value that was already in eax. movl $0x4050, (%eax) stores the value 0x4050 to memory at address 0x100. It does not in any way use the value that was previously at that address. X86 assembly is difficult because mov is overloaded to mean load from memory, store to memory, and move to register. Other assembly languages might have different opcodes for each type of move. - JS1

2 Answers

2
votes

If you're familiar with C, think of it like this:

movl $0x100, %eax     // int* eax = (int*)0x100;
movl $0x4050, (%eax)  // *eax = 0x4050;

movl $0x4050, %eax just overwrites %eax with the value 0x4050. Nothing is interpreted as an address in this case.

1
votes

Do not generally think about registers containing addresses, think of registers containing values. Those values might be treated as addresses if they are used in certain contexts.

%eax just is an expression that refers to the register called eax. Even if I started to write this paragraph in a different way, %eax is not the same as 0x100, even if the register %eax contains the value 0x100. It depends on the context in which you name a register whether the value of that register is relevant at all.

Now, you are putting parenthesis around an expression, you are indicating that you are talking about a memory location, whose address is the value of the expression. In a context where just the value of an expression is used, an expression naming a register may be replaced by a constant expression having the same value as the register. In this case (%eax) is equivalent to ($0x100) (if you may write it that way), that is, the memory location at the address 0x100. The AT&T syntax used by the GNU assembler by default lets you write just 0x100 instead of ($0x100) to refer to the memory location at address 0x100. If an instruction is going to access memory, you need to tell that instruction, what location it should access. Note that I did not talk about the way that memory is accessed, as this depends on the specific instruction.

Now, you were talking about movl $0x4050, (%eax). So the memory location is mentioned in the second operand of the move instruction. In AT&T syntax, this is the target operand of the move instruction. The target of the move instruction is in this case: "The memory location at the address indicated by the value stored in %eax", so if %eax is 0x100, the target of the move is "The memory location at the address 0x100". Note that up to now we did not talk about the contents of that memory location, just about the location itself. The mov instruction (you have to learn these specifics for any instruction) does not care about the value stored in the location indicated by the target operand, but it will store a copy of the value of the source operand at the location indicated by the second operand, overwriting the previous value. So the 0x3999 stored at address 0x100 does not matter at all, but after execution, it has been replaced by 0x4050.