I'm learning assembly now and I don't get one thing about the (presumably) standard function template.
So, based on this really nice book, "the form to remember for functions is as follows:"
function_label:
pushl %ebp
movl %esp, %ebp
< normal function code goes here>
movl %ebp, %esp
popl %ebp
ret
OK, I'm perfectly fine with it, but there is one small thing that I don't understand. After the "normal function code" we restore the initial (pre-call) value of esp, which was previously stored in ebp.
Now, I understand it clearly why we want to serve the esp value back to the calling context untouched. What I do not understand is under which conditions the esp value can be changed at all during the function's execution.
Is it some kind of protection against ourselves (in case we somehow corrupt the stack somewhere in our code) included in this template? Or maybe changing stack values inside a function is a normal practice?
Or it is possible that the initial esp value may end up changed during execution even if we don't do anything with it? (I can't figure out how this can be, in fact.)
I felt rather silly while thinking about this and checked the esp value with gdb in this simple code:
.section .data
message:
.asciz "> Hello from function #%d\n"
.section .text
.globl main
main:
nop
call overhere
pushl $0
call exit
overhere:
pushl %ebp
movl %esp, %ebp
pushl $1
pushl $message
call printf
add $8, %esp
movl %ebp, %esp
popl %ebp
ret
And esp (as I actually expected) was untouched, so moving ebp to esp didn't actually change anything.
Now, I hope that it's clear what I want to find out:
- Can
espvalue eventualy change by itself? (I would bet it can't.) - If it can't, then this template above, obviously, assumes that the programmer might change it somehow inside the function. But I can't figure out why on Earth one might need to do that, so - is changing
espvalue a mistake?
Thank you in advance and excuse my ignorance.
I am puzzled how you missed the instruction that explicitly changes
esp:add $8, %esp. So the answer is clearly yes, it may change during a function and is not a mistake. Note thatpushandcallalso change it, in fact theaddis to compensate for the twopushinstructions (theretat the end ofprintfwill balance thecall). Other typical reason for changingespis the allocation of local variables. This has been omitted from the function template you showed, it typically looks likesub $size_of_locals, %espright after themovl %esp, %ebp.That said, you don't need to use
ebpto remember the stack pointer, as long as you ensure it has the same value at the exit of the function as it had upon entry. Recent versions of gcc don't useebpwhen optimization is enabled, otherwise you can use-fomit-frame-pointerto do so.