assemblyx86cpu-registersmov

Understanding the differences between mov and lea instructions in x86 assembly


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.


Solution

  • 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 just movl 0x001000, %eax. can i say the same for this: movl %eax, %eax. is just movl 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.