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.
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