-
September 27th, 2005, 08:23 PM
#1
Call, push, and pop question
To call a function (eg. printf), I push the values in reverse order and then "call printf". Then I have to pop them after the call. How does a function get the parameters from the stack? My instinct tells me by using pop, but then I'd have to push them back on so they can be popped after the call? Seems like wasted instructions. Can someone shed some light on this please? Thanks.
-
September 27th, 2005, 11:44 PM
#2
Re: Call, push, and pop question
Originally Posted by Yasoo
To call a function (eg. printf), I push the values in reverse order and then "call printf". Then I have to pop them after the call. How does a function get the parameters from the stack? My instinct tells me by using pop, but then I'd have to push them back on so they can be popped after the call? Seems like wasted instructions. Can someone shed some light on this please? Thanks.
(Assuming x/86 processor)
What normally happens is that a stack frame is built around the ebx register, then uses addressing [ebx +parm. offset] to get the parameters of the function and [ebx - var. offset] to get the automatic local variables.
The offset must also take into account the return address, which is also pushed onto the stack.
Here is a simple example that does not take into account more complex ideas such as a display and stack-alignmentm, also this example does not take automatic variables into account:
Assume 2 dword-sized arguments pushed onto stack prior to call foo
Code:
foo: ; procedure foo
; fasm syntax
push ebp ; preserve this
mov ebp, esp ; grab current stack pointer
mov eax, dword [ebp + 12 ] ; get 1st pushed parameter into eax
mov ebx, dword [ebp + 8 ] ; get 2nd pushed parameter into ebx
; ... do other stuff
; .. done, restore stuff before leaving
mov esp, ebp ; restore esp to its original position
pop ebp ; restore ebp
ret ; this returns popping only the address pushed by 'call'
Note that the offsets are +4 more than you would expect, this is because the x/86 'call' instruction pushes the current EIP address onto the stack before transferring control to the procedure (and 'ret' pops that address out).
Noramlly, you should not write your own procedures this way. It is far better to have the procedure pop the paramters off the stack using 'ret n' where 'n' is the size in bytes of the pushed paramters.
-sevagK
www.geocities.com/kahlinor
-
September 28th, 2005, 09:27 AM
#3
Re: Call, push, and pop question
Just an additional info.
The reason why they did not use the "ret n" for functions such as printf is because they (the one who coded printf) don't now in advance how many paramaters does the caller want to pass. They don't know how much bytes need to be poped from the stack on return. For such functions like this, they made a way to determine how many parameters you passed. For example is the printf function, you have the first parameter as the "format specification" and you have to pass sufficient parameter to fill the values with %s, %d etc. Some other functions use a termination indicator to determine the end of the parameter. They go to the parameters until they reach a value of -1 for example.
If you know in advance how many paramaters your function will get (fixed parameters), using the "ret n" is better. It is faster and is less code than the simple "retn".
-
September 28th, 2005, 11:22 AM
#4
Re: Call, push, and pop question
Thanks guys, that's some great info.
Kahlinor, that's exactly what I was looking for.
Rxbagain, I was wondering how unknown number of parameters is handled in assembly last night after I posted this. You read my mind. So, how do you know in assembly how many parameters were passed in a function like printf?
-
September 29th, 2005, 01:23 AM
#5
Re: Call, push, and pop question
So, how do you know in assembly how many parameters were passed in a function like printf?
Formatting functions (like printf) always take a format string as first parameter, and parsing this string lets function 'know' how many parameters was passed. Without some additional information passed during function call it would be not possible to determine how many parameters the call had. It is said that functions with variable number of arguments (those using '...' in prototype) always should have at least one fixed parameter, which makes possible to determine number (and type) of arguments passed.
Hob
B+!
'There is no cat' - A. Einstein
Use [code] [/code] tags!
Did YOU share your photo with us at CG Members photo gallery ?
-
September 29th, 2005, 09:10 AM
#6
Re: Call, push, and pop question
Ah, right. I now remember reading that somewhere. Thanks Hobson.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|