I'm trying to understand the differences between the mov
and lea
instructions in x86 assembly language. I've written a simple assembly code snippet , and I've added comments to explain my understanding of these instructions.
.data
num: .int 2 # Declare an integer variable num with value 2
.text
.globl _start
_start:
movl num, %eax # num stores an address, take the value inside that address into eax
movl $num, %ebx # num stores an address, $ tells us to take the address itself into ebx
leal num, %ecx # num stores an address, take the address itself into ecx (lea)
#initialize
movl $0, %eax
movl $0, %ebx
movl $0, %ecx
movl $num, %edx # num stores an address, take the address itself into edx
movl %edx, %eax # edx is an address, take the value inside that address into eax
leal (%edx), %ecx # () tells us to go to the address inside edx, take the address itself into ecx (lea)
movl (%edx), %ebx # () tells us to go to the address inside edx, take the value inside that address into ebx
# Exit
movl $1, %eax # System call number for exit
xorl %ebx, %ebx # Exit status 0
int $0x80 # Invoke the syscall
However, I'm a bit confused about how these instructions work with registers. and I'll be glad if someone will give me his explanation.
Most of your comments are fine.
Others may need some rewording:
movl %edx, %eax # edx is an address, take the value inside that address into eax
"take the value inside that address"
This just puts a copy of what is in the EDX register into the EAX register. The fact that in this case EDX contains an address is of no importance.
leal (%edx), %ecx # () tells us to go to the address inside edx, take the address itself into ecx (lea)
"go to the address inside"
We're not going to an address. The CPU calculates the address that the leftmost operand represents and stores it as such into the destination register ECX.
From a comment:
just to make sure, when i write
movl num, %eax
, assembly see num as adress, for example its justmovl 0x001000, %eax
. can i say the same for this:movl %eax, %eax
. is justmovl 0x002000, %eax
.
No, you can't say the same:
The movl %eax, %eax
instruction is a copy from one register to another. And since source and destination are the same register it is also a 'silly' operation. Now if you know that EAX contains the value 0x002000, what you wrote (movl 0x002000, %eax
) is certainly not the same as that mere register copy. In your assembler the absence of the $ prefix makes the instruction de-reference, and thus movl 0x002000, %eax
will fetch a dword from the memory at the address 0x002000.
In summary and based on num equaling 0x001000 and EAX equaling 0x002000:
movl num, %eax fetches a dword at address 0x001000
movl 0x001000, %eax fetches a dword at address 0x001000
movl %eax, %eax copies register EAX to itself
movl 0x002000, %eax fetches a dword at address 0x002000
Now add the $ prefix and
movl $0x002000, %eax stores the number 0x002000 in the EAX register
making this instruction the equivalent of movl %eax, %eax
.