Something about calling conventions

I thought I understood calling conventions, until this popped into my head:

In the API calling convention (stdcall), on x86, the parameters are pushed on to the stack from right to left. Then the function is called. The return value is stored in eax. Where is the return address? The call instruction pushes the return address on the stack. So is it on the stack right after the parameters?

Side question: if I write a bunch of naked functions, do I need to manually work with their return addresses or that isn't my job?

Let's say I have __declspec(naked) f() and __decl(naked) g() and in g() I call f(). After f() is executed, will g() resume from the next instruction or do I need to __asm my way into this? (this is more a theoretical situation to help my understand this).
Where is the return address? The call instruction pushes the return address on the stack. So is it on the stack right after the parameters?
Almost, there are a few other things saved, bu that aside, yes.

I hadn't previously encountered __declspec(naked), but it still saves the return address on the stack, so I expect it to behave normally. It just just drops the other things I mentioned above.

This page suggests to you shouldn't use it unless you're writing ring 0 code.
http://www.cs.cornell.edu/courses/cs412/2001sp/resources/microsoft-calling-conventions.html
Last edited on
I hadn't previously encountered __declspec(naked), but it still saves the return address on the stack, so I expect it to behave normally. It just just drops the other things I mentioned above.

This means that if I want to change it's return address I should first pop the old one, then push the new address if I want to not mess things up in the stack.

Also, in both __cdecl and __stdcall after a call to foo(int a, int b) the stack will look like:
b
a
return address

?

I think it should look like
1
2
3
push b
push a
call foo ; which saves the return address on the stack


Is this assumption correct?
Last edited on
This means that if I want to change it's return address I should first pop the old one, then push the new address if I want to not mess things up in the stack.
Yes.

I am not sure what you mean by c and b in your question as you pass a and b as parameters; but yes, the call stack will look as you described. The reason it looks that way is to support variadic functions (like printf), where the called function can discover the arguments rather than having fixed args. And that's why the caller pops the stack, because only the caller is sure of how many args were actually passed.

Just remember that with __stdcall, the called function pops the call stack, because there is no support for variadic functions and it generates smaller code if the called pops the stack, because it's done in one place.
Last edited on
^ oops, I messed up the letters.
Things are clear now.
param n
param n-1
....
param 0
return address

for both __cdecl and __stdcall, with the exception that for __stdcall the function that is called does the stack clean up.

Also, in general, a function will refer to it's arguments relative to the ebp after the stack frame is made?
Yes, except for naked, because the frame pointer isn't set up.
Last edited on
Topic archived. No new replies allowed.