Reputation: 755
I'm very new to assembly, and have some very basic questions.
What is the difference between these four commands?
mov ebx, eax
mov [ebx], eax
mov ebx, [eax]
mov [ebx], [eax]
They say that the brackets mean "get the value of the address". But what, then, does that very first line really do? Does it not move the value of eax into ebx? If it does, then what are the point of the brackets?
Upvotes: 49
Views: 38596
Reputation: 29022
You were missing the operand delimiter ,
in the instructions. I don't know (yet) of any assembler without it. I fixed that in the quotes.
In x86 assembly some registers can be used as data registers or as address registers (a difference to other architectures). These registers are called GPRs ("General Purpose Registers"). They can contain 32-bit-values or 32-bit addresses. Their "names" are EAX
,EBX
,ECX
,EDX
,ESI
,EDI
,ESP
,EBP
.
mov ebx, eax
does move the value in EAX
to EBX
.
mov [ebx], eax
does move the value in EAX
to the 32-bit DWORD value pointed to by the 32-bit address in EBX
mov ebx, [eax]
does move the 32-bit DWORD value pointed to by the 32-bit address in EAX
to EBX
mov [ebx], [eax]
is an invalid instruction in 32-bit Intel assembly, because x86 machine code does not support two arbitrary memory operands in one instruction, only in special cases where at least one memory operand is implicit, like push dword [ebx]
reading memory at [ebx]
and writing memory at [esp - 4]
. See What x86 instructions take two (or more) memory operands?
Upvotes: 5
Reputation: 31393
Let's make a very simple example and imagine we have a CPU with only two registers, EAX and EBX.
mov ebx, eax
Simply copies the value in eax
to the ebx
register
| EAX : 01234567 | ----> | EAX : 01234567 |
| EBX : 00000000 | ====> | EBX : 01234567 |
Now let's add some memory space
ADDRESS VALUE
00000000 6A43210D
00000004 51C9A847
00000008 169B87F1
0000000C C981A517
00000010 9A16D875
00000014 54C9815F
mov [ebx], eax
Moves the value in eax
to the memory address contained in ebx
.
| EAX : 01234567 | --no--> | EAX : 01234567 |
| EBX : 00000008 | --change--> | EBX : 00000008 |
ADDRESS VALUE
00000000 6A43210D -> 6A43210D
00000004 51C9A847 -> 51C9A847
00000008 169B87F1 =====> 01234567
0000000C C981A517 -> C981A517
00000010 9A16D875 -> 9A16D875
00000014 54C9815F -> 54C9815F
mov ebx, [eax]
Moves the value from the memory address contained in eax
to ebx
.
| EAX : 00000008 | -> | EAX : 00000008 |
| EBX : 01234567 | ====> | EBX : 169B87F1 |
[No change to memory]
ADDRESS VALUE
00000000 6A43210D
00000004 51C9A847
00000008 169B87F1
0000000C C981A517
00000010 9A16D875
00000014 54C9815F
mov [ebx], [eax]
This, finally, you would think would move the value from the memory address contained in eax
to the memory address contained in ebx
.
| EAX : 00000010 | --no--> | EAX : 00000010 |
| EBX : 00000008 | --change--> | EBX : 00000008 |
ADDRESS VALUE
00000000 6A43210D -> 6A43210D
00000004 51C9A847 -> 51C9A847
00000008 169B87F1 =====> 9A16D875
0000000C C981A517 -> C981A517
00000010 *9A16D875 -> 9A16D875
00000014 54C9815F -> 54C9815F
But this combination is disallowed by the x86 architecture. You cannot move from memory to memory.
The use of brackets is therefore equivalent to a dereferencing operation.
Upvotes: 107