What happens on stack when a function calls another one

A

Adam

Hello list,

Could you please explain what happens on stack when a function calls
another one? Where the argument will be put? How is the auto
variables?

Best regards,
/Adam
 
T

Tom St Denis

Hello list,

Could you please explain what happens on stack when a function calls
another one? Where the argument will be put? How is the auto
variables?

Best regards,
/Adam

The standard doesn't define how exactly the stack mechanism works.

But if you want an idea of how your compiler makes machine code use
it's "emit assembler" option. With GCC it's -S [for instance].
 
F

Felix Palmen

* Adam said:
Could you please explain what happens on stack when a function calls
another one? Where the argument will be put? How is the auto
variables?

I don't think the C standard requires parameter passing by stack, in
fact, I have seen implementations using processor registers for that --
but most implementations will do so. If a stack is used, your question
seems a little pointless -- of course a stack will overflow eventually,
then you program will crash. But under normal conditions, the answer is
quite straight-forward: The arguments will be put, well, on the stack ;)

Maybe read up a little on how a stack works, start e.g. here:
<http://en.wikipedia.org/wiki/Stack_(data_structure)>
 
A

Adam

I don't think the C standard requires parameter passing by stack, in
fact, I have seen implementations using processor registers for that --
but most implementations will do so. If a stack is used, your question
seems a little pointless -- of course a stack will overflow eventually,

Thanks for reply. I mean what kind of role stack plays when function
calling happens? Where the return address of the called function will
be?
then you program will crash. But under normal conditions, the answer is
quite straight-forward: The arguments will be put, well, on the stack ;)

I have read somewhere that the first 4 arguments will be put into
registers, however, the extra arguments would be put on stack. Is this
true for gcc on x86?

/Adam
Maybe read up a little on how a stack works, start e.g. here:
<http://en.wikipedia.org/wiki/Stack_(data_structure)>

--
 Felix Palmen       (Zirias)  + [PGP] Felix Palmen <[email protected]>
 web:  http://palmen-it.de/ |            http://palmen-it.de/pub.txt
 my open source projects:     |   Fingerprint: ED9B 62D0 BE39 32F9 2488
 http://palmen-it.de/?pg=pro +                5D0C 8177 9D80 5ECF F683
 
F

Felix Palmen

* Adam said:
Thanks for reply. I mean what kind of role stack plays when function
calling happens? Where the return address of the called function will
be?

Well, these are definitely implementation details.
I have read somewhere that the first 4 arguments will be put into
registers, however, the extra arguments would be put on stack. Is this
true for gcc on x86?

And as I realize now, you're interested in implementation details.
Honestly, I have no idea. But I assume you'd have a better chance to
find out in a newsgroup or mailing list dealing with GCC, or, the GNU
toolchain :)

Regards, Felix
 
O

osmium

Adam said:
I have read somewhere that the first 4 arguments will be put into
registers, however, the extra arguments would be put on stack. Is this
true for gcc on x86?

I suggest you get a handle on the fundamentals (as suggested upstream with
the Wiki link) before trying to understand specific implementations. Get a
*lot* of paper and figure out how a recursive solution of a factorial
function can work.
 
M

Mark Bluemel

Hello list,

Could you please explain what happens on stack when a function calls
another one? Where the argument will be put? How is the auto
variables?

What platform? Which compiler implementation? What compiler
optimisation level options are enabled?

The C language specification says nothing about this. It doesn't even,
as far as I know, mention a stack...

Indeed the question isn't specific to the C language, as far as I can
tell - the last discussion on this subject I read in any detail was in
the Power architecture assembly language guide, which explained how
arguments were allocated to the available registers or overflowed into
the stack and how storage for a invocation of a "procedure" was
allocated.
 
N

Nick Keighley

Could you please explain what happens on stack when a function calls
another one? Where the argument will be put? How is the auto
variables?

As others have noted there doens't have to be a stack. But it is
common way to implement languages like C.

int g (int i)
{
int m;
m = i + 2;
return m;
}

int f (int i, int j)
{
int k;
k = g(j) + i;
return k;
}

f(2, 4); /* in a real C program this would be in another function */

I don't claim the program is particularly sane. Lets start by calling
the function f. Push the actual parameters 2 and 4 onto the stack.
They correspond to i and j. Call f to put the return address on the
stack. Add another entry to the stack to hold the auto variable k
(it's a bit more complicated with real compilers but you should see
teh idea)

k-cell (?) <-- SP
ret
j-cell (4)
i-cell (2)

the code for function f can find all its variables as offsets from the
stack pointer.

Now consider the call to fucntion g. Push i onto the stack. Call g.
Bump the stack to make room for m.

m-cell (?) <-- SP
ret
i-cell (4)
k-cell (?)
ret
j-cell (4)
i-cell (2)

the code for function g can find all its variables as offsets from the
new stack pointer. The progarm doesn't even get confused taht you#ve
got two variables called i.

Returning just involves undoing all that.
 
G

Gene

I don't think the C standard requires parameter passing by stack, in
fact, I have seen implementations using processor registers for that --
but most implementations will do so. If a stack is used, your question
seems a little pointless -- of course a stack will overflow eventually,

Thanks for reply. I mean what kind of role stack plays when function
calling happens? Where the return address of the called function will
be?
then you program will crash. But under normal conditions, the answer is
quite straight-forward: The arguments will be put, well, on the stack ;)

I have read somewhere that the first 4 arguments will be put into
registers, however, the extra arguments would be put on stack. Is this
true for gcc on x86?

/Adam


Maybe read up a little on how a stack works, start e.g. here:
<http://en.wikipedia.org/wiki/Stack_(data_structure)>
--
 Felix Palmen       (Zirias)  + [PGP] Felix Palmen <[email protected]>
 web:  http://palmen-it.de/ |            http://palmen-it.de/pub.txt
 my open source projects:     |   Fingerprint: ED9B 62D0 BE39 32F9 2488
 http://palmen-it.de/?pg=pro +                5D0C 8177 9D80 5ECF F683- Hide quoted text -

- Show quoted text -

This isn't a C question. It's a language implementation question.
Better placed at comp.compilers. Some implementations of C don't have
a single contiguous area of memory called a stack.

See http://en.wikipedia.org/wiki/Call_stack . It's not a bad
explanation.
 
N

Nick Keighley

As others have noted there doens't have to be a stack. But it is
common way to implement languages like C.

A more abstract way of viewing things is that the executor (the
hardware) has a current program counter (the current instruction being
executed) and a current environment (where its parameters and auto
variables are stored).

calling
-------
create a new environment
evaluate and store the paramters in the new environment
save the old environment in the new environment
set the environment to the new environment
call the new function
(that is save the value of the pc in the environment
and load the pc with the new pc value)

Inside the function auto-variables are added to the environment. Auto
variables in calling functions can be accessed by following the chain
of environments (the environment holds a reference to the function's
caller's environment).

This can obviously be applied recursivly as many times as required.

returning
---------
get previous environment from environment
store the return value in the previous environment
set the environment to the previous environment
load pc with pc value from environment

At some point unused environments may need to be destroyed.
 
S

Seebs

Thanks for reply. I mean what kind of role stack plays when function
calling happens? Where the return address of the called function will
be?

Wherever it wants. There is no general rule.

This is like asking "what is a man's favorite color?"

Well, that depends on the man.
I have read somewhere that the first 4 arguments will be put into
registers, however, the extra arguments would be put on stack. Is this
true for gcc on x86?

Probably sometimes but not always, depending on the arguments. (Consider
the case where an argument is a structure which is larger than any register.)

Why do you care? There are two possibilities:

1. You're doing compiler maintenance, and actually need to know this.
2. You don't really need to know it, and as a result, you're not going to
learn all the special cases and boundary conditions. You will mistakenly
think you know what's happening, and you will rely on that information, and
when you are wrong, you will be totally screwed because you're relying on
something which isn't true.

If you don't need to know this, don't waste your time thinking about it;
anything you learn will be true some of the time but not all of the time,
and reliance on it will make you make significant mistakes.

-s
 
N

Nobody

I have read somewhere that the first 4 arguments will be put into
registers, however, the extra arguments would be put on stack. Is this
true for gcc on x86?

No; all arguments are pushed onto the stack, right to left. An int-sized
or smaller result is returned in EAX. Registers other than EAX, ECX and
EDX must be preserved by the callee. This is true for Linux and for the
cdecl and stdcall conventions on Windows.

Some Windows compilers implement other conventions (e.g. passing arguments
in registers), but such conventions are compiler-specific, so you can't
realistically use them for "public" interfaces.

x86-based platforms don't use registers for arguments due to the
relatively small number of registers. This means that the callee
would usually end up having to put them on the stack so that it can use
the registers for its own purposes, which defeats the point of using
registers.

RISC architectures (which have more registers) tend to pass some arguments
in registers; particularly SPARC, which uses a "register window" design.
 
I

Ian Collins

No; all arguments are pushed onto the stack, right to left. An int-sized
or smaller result is returned in EAX. Registers other than EAX, ECX and
EDX must be preserved by the callee. This is true for Linux and for the
cdecl and stdcall conventions on Windows.

Some Windows compilers implement other conventions (e.g. passing arguments
in registers), but such conventions are compiler-specific, so you can't
realistically use them for "public" interfaces.

x86-based platforms don't use registers for arguments due to the
relatively small number of registers.

Not so for 64 bit versions, which have a richer register set.
 
T

Thad Smith

Seebs said:
Probably sometimes but not always, depending on the arguments. (Consider
the case where an argument is a structure which is larger than any register.)

Why do you care? There are two possibilities:

1. You're doing compiler maintenance, and actually need to know this.
2. You don't really need to know it, and as a result, you're not going to
learn all the special cases and boundary conditions. You will mistakenly
think you know what's happening, and you will rely on that information, and
when you are wrong, you will be totally screwed because you're relying on
something which isn't true.
Or, when your first model fails, instead of being total screwed you expand your
thinking to include other scenarios that you weren't aware of before, developing
a deeper understanding.

3. You're learning to program and want to understand how things work, perhaps
knowing that different techniques are used on different implementations.

4. You're learning to program and are curious how some of the problems are
solved, perhaps how large structures are passed as parameters.

5. You find looking at solutions inspirational.

6. You want to improve the way things work and study implementations to find
weaknesses that could be improved.

7. You want to prevent security flaws and study implementations to find
weaknesses that could be exploited.

8. You do debugging and find that understanding the underlying mechanisms make
complex debugging easier.

Personally, I have learned useful information looking at the design of real-time
operating systems, the output of compilers, the run-time support for page
switching on small systems. I enjoyed the challenge of improving on existing
implementations.

Why do _you_ study system implementations?
 
S

Seebs

Or, when your first model fails, instead of being total screwed you expand your
thinking to include other scenarios that you weren't aware of before, developing
a deeper understanding.

In my experience, that only happens if you already have the notion of the
abstract semantics as separate from any specific implementation. As long as
you have someone asking "what happens" as though there's a single answer,
that won't happen.
3. You're learning to program and want to understand how things work, perhaps
knowing that different techniques are used on different implementations.

The problem is that this nearly always decays into Case 2 unless headed off
preemptively with "ACTUALLY THERE IS NO ONE ANSWER".
8. You do debugging and find that understanding the underlying mechanisms make
complex debugging easier.

This, again, only works if you know the distinction between abstract and
specfic.
Why do _you_ study system implementations?

Because I'm doing compiler support. :)

-s
 
S

Seebs

And one learns the distinction by learning different implementations of
a single abstraction.

You know, I bet that's right for a lot of people. It's not how I learn,
so it didn't occur to me. I do best by starting with an abstraction and
then finding specific implementations, so being told right up front that
there's an abstraction works better for me than learning two specific
instances first.

So for me, being told "there is no underlying answer to this, different
implementations do it differently" is very helpful, while getting an answer
specific to any system first would be unhelpful.

-s
 
T

Thad Smith

Seebs said:
In my experience, that only happens if you already have the notion of the
abstract semantics as separate from any specific implementation. As long as
you have someone asking "what happens" as though there's a single answer,
that won't happen.

A. "I'm sorry, but your simple question indicates you aren't ready for an
answer. Come back next year and try again"?

B. "It varies. Using compiler X, library Y, with target Z, its done this way to
be compatible with the previous foobar implementation ported from V. On target
Q, there is a lookup function, rather than a table, in order to save memory on a
constrained system. The language allows these implementations and more."
The problem is that this nearly always decays into Case 2 unless headed off
preemptively with "ACTUALLY THERE IS NO ONE ANSWER".

Good point.
This, again, only works if you know the distinction between abstract and
specfic.

And one learns the distinction by learning different implementations of a single
abstraction.
 
N

Nick Keighley

Wherever it wants.  There is no general rule.

This is like asking "what is a man's favorite color?"

Well, that depends on the man.


Probably sometimes but not always, depending on the arguments.  (Consider
the case where an argument is a structure which is larger than any register.)

Why do you care?  There are two possibilities:

There are only two sorts of people
- those that divide everyone up into rwo catagories
1.  You're doing compiler maintenance, and actually need to know this.
2.  You don't really need to know it, [...]

3. having an idea about how something could be implemented has
pedagogical uses

I used to know the innards of two different compiler calling
conventions. I don't happen to know the details of the compilers I
currently use but I have a comfortable enough feel for the ideas to be
able to program in C. I've no doubt I could find out the details of
current compilers if I really felt the urge.

I've taken the same attitude to TCP/IP and to OSs

You can go too far though

Q: "so what does this [telecomms switch] actually do"
A: "it's all shift registers!!"
[...] and as a result, you're not going to
learn all the special cases and boundary conditions.  You will mistakenly
think you know what's happening, and you will rely on that information, and
when you are wrong, you will be totally screwed because you're relying on
something which isn't true.

If you don't need to know this, don't waste your time thinking about it;
anything you learn will be true some of the time but not all of the time,
and reliance on it will make you make significant mistakes.
 
N

Nick Keighley

In my experience, that only happens if you already have the notion of the
abstract semantics as separate from any specific implementation.

some people just don't work well with complete abstraction. I like the
idea of knowing how it *could* be implemented. And from then on I'm
happy to be abstract. I read Plauger's Library book with interet. I'm
learning about things called "continuations" in the Scheme language- I
needed a model implemtnaion before they made any sense. Not everyone
thinks or learns th same way.

My replies to the OP tried to steer a midway between complete
abstraction (saving and restoring execution environments), "typical"
implementation (pushing and popping a stack). I didn't get down to
Compiler XYZ version 42 saves the current therblig registers on a
dynamic RAM stack unless its the third tuesday in the month or we have
more than 10 registers when...

Sometimes abstract descriptions are just too abstract!
 As long as
you have someone asking "what happens" as though there's a single answer,
that won't happen.


The problem is that this nearly always decays into Case 2 unless headed off
preemptively with "ACTUALLY THERE IS NO ONE ANSWER".

absolutely and completely disagree with this attitude.

This, again, only works if you know the distinction between abstract and
specfic.


Because I'm doing compiler support.  :)
Yes, in the same sense that a shoe is a form of aircraft carrier.
(comp.lang.scheme)
 
R

Richard Bos

Thad Smith said:
And one learns the distinction by learning different implementations of a single
abstraction.

But one doesn't learn those different implementations by asking for, and
assuming that there even is, "the" way things "are" implemented.

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top