Search code examples
memoryassemblyx86att

x86 mov / add Instructions & Memory Addressing


I'm learning x86 assembly in class and I'm very lost as to how you differentiate between what a register operand and what a memory reference does. I had several confusions I was hoping to clear up.

The following code is what my textbook says is the long way to do push and pop respectively:

subl $4, %esp
movl %ebp, (%esp)

movl (%esp), %eax
addl $4, %esp

So in the subl instruction, can we always expect %esp to hold an address value?

Also what is the difference between the two movl functions? Can the first one be written as

movl (%ebp), %esp

? And for the second movl, does that move the address of %esp or does it move the value pointed to by %esp?

As a follow-up then, why can't we have the source and destination be memory references like so?

movw (%eax), 4(%esp)

And lastly, for the following code:

movb (%esp, %edx, 4), %dh

if the source is more than 1 byte (the size of %dh), then what happens? Does it just truncate the value?

Sorry, this was a ton of questions but any help would be greatly appreciated.


Solution

  • The following code is what my textbook says is the long way to do push and pop respectively:

    subl $4, %esp
    movl %ebp, (%esp)
    
    movl (%esp), %eax
    addl $4, %esp
    

    So in the subl instruction, can we always expect %esp to hold an address value?

    Yes. The ESP register holds the memory address of the last value pushed into the stack.

    Also what is the difference between the two movl functions? Can the first one be written as

    movl (%ebp), %esp
    

    ? And for the second movl, does that move the address of %esp or does it move the value pointed to by %esp?

    The MOV instruction, in AT&T syntax, expects two operands: source and destination. MOV copies data (in this case, 32 bits, as denoted by the L suffix) from the first operand written at the left, to the second operand, written at the right. If one of them is enclosed in parenthesis, that means that the operand is a memory operand, and the value in parenthesis is its memory address, rather than the actual value)

    So, movl %ebp,(%esp) means: copy the value of register EBP into memory, at the address pointed by the value of register ESP.

    What you meant with movl (%ebp),%esp is: copy 32 bits of data starting at the memory address pointed by the value of EBP, into the ESP register.

    So you are changing the direction of the movement.

    As a follow-up then, why can't we have the source and destination be memory references like so?

    movw (%eax), 4(%esp)
    

    Short answer: because the encoding used by Intel doesn't allow that. Long answer: the way Intel designed the ISA, available resources to calculate two effective addresses in the good old 8086, etc

    And lastly, for the following code:

    movb (%esp, %edx, 4), %dh
    

    if the source is more than 1 byte (the size of %dh), then what happens? Does it just truncate the value?

    The source is the same size as the destination. This is imposed both by the B suffix and the fact that the destination is an 8-bit register. The value iin parenthesis is then the address of a single memory byte. By the way, this address is ESP+EDX*4