[Question]activities of stack pointer and frame pointer when function called

S

S.Tobias

Please don't top-post. Top-posting is considered rude here.
[top-posting fixed]


You have used the word "post", which here usually means "article/message
sent to Usenet". You have mislead me (and probably others), because
what you are (later) referring to is an Internet-published article.
With questions about an article you should go to the proper forum which
the publishing site has dedicated for it.
Your description doesn't make much sense.
Next time supply some pointers to the article you read, it'll be
easier to answer your query.


I suspect you don't understand what as stack frame is.

First try to read:
[snip]

Thanks your reply.
The article I read is from
www.hakin9.org/en/attachments/stackoverflow_en.pdf. [at page 5]
And you're right. I don't know it very clearly. And that's why I want
to understand it; for it's useful to help me to solve some basic
problem which I may not perceive before.
I appreciate your help,
sincerely.

The article ("Overflowing the stack on Linux x86" by Piotr Sobolewski)
deals with a specific implementation on a specific OS. In this context
your question is really OT, because what you ask about is how a function
call in C language is implemented by gcc on Linux-i386 (and how you can
(ab)use it for your own mischievous or educational purposes); it could
just as well be any other functional language. Since I promised,
I'll give you an answer, but I'll try to keep within certain bounds
of generality.


[very OT]
What I write below is OT, I might be slightly wrong, quite wrong, or
I might totally make an idiot of myself. Don't rely on anything I've
written. I intend this to be only a general introduction to how a function
call in C might be implemented. I try to present just one out of many
possibilities. It is also very simplified. It's surely of no
interest to most c.l.c. members.

In the C language each function "owns" its automatic (local) variables
and arguments. You can call a function recursively; the new invocation
obtains a new instance of its variables (they are new objects, although
they are referred to with the same identifiers in the C code); when
you return to the previous invocation, the values of its variables and
arguments are restored.

A processor is a very simple device; it has only a finite number of
registers, whereas the number of recursive function calls is unlimited
(well, actually it is). We have to use memory to store local context
(variables, arguments and everything else that belongs to the function
invocation). Memory is only one-dimensional, and the number of parameters
and local variables may vary from function to function (and is also
unlimited). A function stack frame is a method to keep track of function
calls and their context. It has nothing to do with the languages itself,
it's just how a compiler implements it. Another compiler might do it
a completely different way.

A frame is simply a pool of data that form the context. When we call
a function, we only need to prepare a new frame (pool) for the called
function and just jump into it. At the point of creation the caller is
responsible for setting up some data (arguments), and for some other
(local variables) - it's the callee. When the callee returns to its
caller, it only has to restore the previous context (frame) and just
jump back to the position where the call was made (and also to mark the
previous frame as available for reuse). From there, the caller should
be able to continue as if nothing happened (almost).

In the real machine (with 1-dim memory) frames are often kept on stack
(this means both an abstract LIFO structure, and hardware facilities
to access memory in a stack like manner). A stack frame might look
like this:
--- (higher addresses)
Arguments
<-- FP (frame pointer)
Local Variables
--- (lower addresses)
One register FP (that's in the processor) is specially dedicated to
keeping track of function calls, and points into the middle of the frame.
Above that point are arguments, below - variables; in the machine code
when a function wants to access an argument, it adds some offset to the
address kept in FP, if it wants a variable it subtracts something from FP
(it knows what to add or subtract, because for each function that has been
decided by the compiler at the time of translation). When a function is
called, the caller pushes on stack Arguments, sets new value of FP and
jumps into the callee. The callee sets Local Variables and does its
own stuff. At this point we have two frames:
---
Arguments caller's context

Local Variables
---
Arguments current (callee's) context
<-- FP
Local Variables
---

When the callee returns it just has to reset FP to the old value and
leave its own frame alone (it'll be overwritten by next function calls).

But how does the callee know the old value of FP and what is the address
it is to return to (from which it was called)? That information is
also remembered in the stack frame too; we need more information than just
Arguments and Variables. So the stack frame might look like this:
---
Arguments
Old FP <-- FP
Return address
Local Variables
---
Each caller, when preparing a new frame for a callee additionally pushes
on stack the current value of FP (which it perfectly knows) and the
return address (this will usually be helped by a machine instruction).
The callee (and every other function) references its arguments and
variables relative to the current address in FP, and it also has the
old FP value and return address (these may be considered as a kind of
arguments too), so now it knows how to return to its caller.

The caller machine-code might look like:
push Arguments
push FP
FP = SP ; SP = stack pointer, current end of stack,
; SP is modified automatically by push and pop instructions
call callee ; pushes IP (instruction pointer) on stack and jumps
; to callee
The callee code might look like:
*(FP-8) = 7 ; set variables (access is relative to FP value)
*(FP-12) = 11 ;
*(SP+4) ; access argument
and the return part of the callee might look like:
AX = *(FP-4) ; remember return-address in a register
FP = *(FP) ; restore the old FP value
IP = AX ; jump to where we came from
; the caller will have to adjust SP (it would be better if
; we saved old SP value in the stack frame as well)

The moral: the stack operations are little more than handling linked
list of objects (frames), in a stack-like manner. I haven't told yet
many other details, like returning a value, dynamic stack allocations
(non-standard alloca, or VLA), saving other data, variadic functions etc.
An implementation might have more than one stack, or no stack at
all. A stack might grow upwards or downwards (I assumed downwards).
There might be no stack frame at all (often referred to as "fastcall").
A stack frame might be a dynamic "structure", ie. frames might look
different for different invocations of the *same* function. These are
just a few little problems that are up to the compiler to solve in order
to fulfill the C language and optimization demands, and have nothing to
do with the language itself (the solution will usually be driven by the
hardware architecture, conventions and common sense; this is not hi-tech).

It is now a good time to define what a stack frame is: it is a known
_layout_ of data, in which current function invocation context is stored.
It's worth to note that a debugger must know this layout (among other
things) in order to be able to inspect the current state of a program;
it might work with one compiler, it might not with another (usually there
are some "standards", so it's probably not a problem in practice).

I haven't answered your question directly, but the answer is there.

Advice: it's worth to know roughly the things I said above, but it's not
essential for learning C. If you're interested more in the subject,
study Assembly language(s). Your question is OT here, if you have more
similar questions ask them in a news group dedicated to a particular
compiler, operating system or hardware architecture.
 
A

anonymous

Sorry, I'm aware of it, for originally I simply want to know how a
function was called in C language generally; not relying on any
specific underlying detail implementation. However, being lack of such
background knowledge I post to the wrong forum. I apologize to it.
And thanks your help, sincerely.

S.Tobias said:
Local Variables
---
Arguments current (callee's) context
<-- FP
Local Variables
---

When the callee returns it just has to reset FP to the old value and
leave its own frame alone (it'll be overwritten by next function calls).

But how does the callee know the old value of FP and what is the address
it is to return to (from which it was called)? That information is
also remembered in the stack frame too; we need more information than just
Arguments and Variables. So the stack frame might look like this:
---
Arguments
Old FP <-- FP
Return address
Local Variables
---
Each caller, when preparing a new frame for a callee additionally pushes
on stack the current value of FP (which it perfectly knows) and the
return address (this will usually be helped by a machine instruction).
The callee (and every other function) references its arguments and
variables relative to the current address in FP, and it also has the
old FP value and return address (these may be considered as a kind of
arguments too), so now it knows how to return to its caller.
....
 
S

S.Tobias

anonymous said:
Sorry, I'm aware of it, for originally I simply want to know how a
function was called in C language generally; not relying on any
specific underlying detail implementation. However, being lack of such
background knowledge I post to the wrong forum. I apologize to it.

No problem. I tried to be general enough in my reply and give you
a few directions.
And thanks your help, sincerely.

You're welcome with your C questions here.
 

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,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top