Agola wrote:While calling assembly code from c, all examples use:
Why they use that? Using directly %esp should work also.
That's to set up the stack frame for the function's activation record. I gave a detailed explanation of activation records
here, and the wiki covers it well
here, though to revisit the subject:
The activation record is the record of the function's local variables. In order to allow the function to be re-entrant (that is, to make it so that it could be called recursively), each call of the function has to have it's own activation record, which is created at the time the function is called and either freed or (for certain kinds of tail call optimization) reused. As a general rule, a stack is used to keep track of the order in which activation records are created, and in most modern systems where there is a process-wide stack pointer register (either dedicated or by convention), the activation records are pushed onto the system stack as the first thing the function does, and popped off it as the last thing it does.
The stack frame is a block of memory on the stack set up to hold the activation record (or at least a pointer to it). The process needs a pointer to the starting address of the stack frame in the stack, so it can find the local variables' addresses - the locals are accessed using that address plus an offset.
Most systems have a dedicated register (or one set aside by convention) for this base pointer (also called a frame pointer). However, before a function can set up it's own base pointer, either the caller or the callee has to save the caller's base pointer, and again, since this is supposed to be re-entrant, it uses the stack for this. So, for most calling conventions, this means pushing the current base pointer before the function's body starts, and popping it back when the function ends.
Who does this depends on the language and the calling convention. Most C-oriented conventions, such as
cdecl, have the caller push their own frame pointer before the call, and pop it off afterwards. However, the Pascal-style conventions such as
stdcall have the callee do this.
And what does C push before calling function? I googled it but somewhere says it is for return value, and somewhere says it is for eip.
I think it is for eip, because return value is already handled with eax. Also ret pops off eip, so C should push the eip before calling function.
Again, it depends on the calling convention. At the very least, for x86, the CALL instruction will automatically push the return address (IP in early models, [(E|R)]IP + wordsize in later implementations) which the RET instruction uses later. However, if there are any function arguments, those have to be pushed first, and in C they are usually pushed in reverse order - for foo(x,y,z), the caller would push z first, then y, then x. This is to allow for variable argument sizes, such the
printf() formatting arguments. Then (for a caller-cleaned convention such as cdecl) it would save the base pointer and stack pointer as already explained, then make the CALL operation. On return, it would then clear it's base pointer off the stack (the callee already had to restore caller's stack pointer in order to return, so all that it needs to do is increment the stack pointer by the word size).
This means that (assuming that the params are all of the system word size), the stack at the start of the function would be "z, y, x, caller's base pointer, return address". The function would then push it's own locals onto the stack, and use a positive offset to access arguments and negative offsets to access locals. If the locals are
a and
b, then (using AT&T mnemonics):
Code: Select all
a == (%ebp)
b == -4(%ebp)
z == 8(%ebp)
y == 12(%ebp)
z == 16(%ebp)