How function works internally

M

marydeepthy

Hi,

I would like to know what happens internally when a c programme is
executed. LIke,
when we call a function, all the previous values will be pushed on to
stack and the local variables of that particular function will be
pushed in to the stack. when the function returns, all the local
variables will be poped out..

like this, what happens when we call a strcpy function. what happens in
stack??

i would like to know from where we can get this information. any
sites..

i searched alot, but couldnt find.

Thanks in advance

Deepthy
 
C

Cong Wang

Hi,

I would like to know what happens internally when a c programme is
executed. LIke,
when we call a function, all the previous values will be pushed on to
stack and the local variables of that particular function will be
pushed in to the stack. when the function returns, all the local
variables will be poped out..

like this, what happens when we call a strcpy function. what happens in
stack??

i would like to know from where we can get this information. any
sites..

i searched alot, but couldnt find.

Thanks in advance

Deepthy

If you really want to know this, please see the assembly code generated
by gcc. ;-p
 
J

jmcgill

like this, what happens when we call a strcpy function. what happens in
stack??

i would like to know from where we can get this information. any
sites..

The specific details of the function call are defined by the
implementation, not the standard.

It is very easy to inspect the procedure call in some implementations.

For example, if you use GCC, just give it the -S switch and look at the
asm output.

Or if you really want to go in depth, you can study the GCC
documentation (for example), http://gcc.gnu.org/onlinedocs/
or the GCC internals (a separate manual).

If you don't use GCC for some reason, you will have to go elsewhere for
documentation.
 
K

Keith Thompson

I would like to know what happens internally when a c programme is
executed. LIke, when we call a function, all the previous values
will be pushed on to stack and the local variables of that
particular function will be pushed in to the stack. when the
function returns, all the local variables will be poped out..

like this, what happens when we call a strcpy function. what happens in
stack??

This is not defined by the language, and different compilers can and
do handle this differently.

Not every implementation has a "stack", in the sense of a contiguous
region of memory that grows in a particular direction. There are
implementations that do the equivalent of a heap allocation to
allocate memory for a function call.

There are de facto standards for some systems. I think what you're
looking for is an ABI (Application Binary Interface, I think).
Searching for that might give you some information -- but keep in mind
that anything you find will be system-specific.

If you want to know what the language actually requires, you can get
the latest draft of the ISO C standard by search for "n1124.pdf".
(It's definitely not light reading.)
 
K

kondal

Keith said:
This is not defined by the language, and different compilers can and
do handle this differently.

Not every implementation has a "stack", in the sense of a contiguous
region of memory that grows in a particular direction. There are
implementations that do the equivalent of a heap allocation to
allocate memory for a function call.

There are de facto standards for some systems. I think what you're
looking for is an ABI (Application Binary Interface, I think).
Searching for that might give you some information -- but keep in mind
that anything you find will be system-specific.

If you want to know what the language actually requires, you can get
the latest draft of the ISO C standard by search for "n1124.pdf".
(It's definitely not light reading.)

Could you please tell me which compiler does a heap allocation for a
function call. I haven't heard of it and I feel its interesting to
know. Any document/paper would be sufficient.

-kondal
 
K

Keith Thompson

kondal said:
Could you please tell me which compiler does a heap allocation for a
function call. I haven't heard of it and I feel its interesting to
know. Any document/paper would be sufficient.

Barry Schwartz mentioned one such system here just recently:

| On Sat, 23 Sep 2006 00:10:26 GMT, Keith Thompson <[email protected]>
| wrote:
|
| >[...]
| >> pop() was a function you introduced to start the discussion. From the
| >> code you've shown, there is no push(). How the compiler chooses to
| >> handle intermediate results while evaluating expressions is an
| >> implementation detail that will vary from system to system. My system
| >> doesn't have a hardware stack and intermediate results are stored in
| >> temporary variables which the compiler keeps track of (and attempts to
| >> reuse efficiently).
| >
| >Out of curiosity, what system are you using that doesn't have a
| >hardware stack? It would be good to have a specific example in the
| >recurring argument about whether C defines a "stack".
|
| An IBM Multiprise 2003 S/390 running OS/390 2.10.

Though I realize now that (a) he was talking about intermediate
expression results, not function call activation records, and (b) he
didn't actually mention a heap.
 
C

Clever Monkey

I would like to know what happens internally when a c programme is
executed. LIke,
when we call a function, all the previous values will be pushed on to
stack and the local variables of that particular function will be
pushed in to the stack. when the function returns, all the local
variables will be poped out..

like this, what happens when we call a strcpy function. what happens in
stack??

i would like to know from where we can get this information. any
sites..
This stuff is often implementation and platform specific. For a very
readable overview of some typical ways this is done, see van der
Linden's "Deep C Secrets".
 
C

Chris Torek

[The context, which the poster below snipped, was questions about
the internal mechanisms of C runtime systems, with particular
respect to function calls.]

learn(and understand) any x86 based assembly lang.

While there is nothing *wrong* with learning any particular assembly
language, it is a huge mistake to learn *only* x86 assembly and
assume that this is the way "everything" works. In particular,
the x86 is largely based on 1970s-era architectures (specifically
the Intel 4004, 8008, and 8080). x86 implementations carry a huge
burden of "backwards compatibility" with a system optimized for
the conditions that held at the time. It is true that, through
great cleverness, modern CPUs that implement the IA32 architecture
squeeze tremendous performance from this klunky instruction set;
but the instruction set itself remains klunky nonetheless.

Compare, for instance, the call sequence:

/* compute three parameters, then: */
push parm3 /* write 3rd parameter to RAM, adjust stack pointer */
push parm2 /* write 2nd parameter to RAM, adjust stack pointer */
push parm1 /* write 1st parameter to RAM, adjust stack pointer */
call func
addl $12,%esp /* remove 12 bytes of parameter from stack */

with:

/* compute three parameters directly into arg registers */
call func
/* no stack adjustment required */

in which we have removed four out of five instructions from the
caller (by using a more-sensible instruction set). Suppose further
that the target function "func" is a "leaf function" -- one that
makes no calls of its own -- so that the x86 version reads, e.g.:

func:
enter /* instruction that builds stack frame; actually faster
to open-code this as several instructions */
... code to work with the three parameters using the frame ptr ...
leave
ret

while the more-modern architecture just does:

func:
... work directly with the parameters in their registers ...
retl /* "return from leaf" */

which eliminates the frame-building (admittedly, a good compiler
can do this on the x86 in some cases, although register pressure
often forces at least some pushes and pops) and 100% of the CPU<->RAM
traffic. The modern architecture's debug system understands that
"leaf functions" do not build stack frames, and use the "return
from leaf" instruction to branch back to the caller (whose return
address is stored in the "caller's return address" register, rather
than RAM, by the "call" instruction).

For a decent smattering of assembly languages, one might learn (at
least the rudiments of) x86, MIPS or SPARC, PowerPC, and ARM.
Investigating the moribund Itanium instruction set, and perhaps
some vector processor instruction sets (Cray or Convex for instance),
might also be worthwhile. Some Data General Nova or Eclipse
experience could also broaden one's concept of "pointers". None
of these are *required* to understand C code, but they will certainly
give you a better idea of the possible ranges for underlying
architectures, and an appreciation for how well (or in some cases
poorly) C maps onto them.

(I might include IBM AS/400 "MIL" above if I had any idea what was
in it. :) )
 
C

Coos Haak

Op 28 Sep 2006 19:01:22 GMT schreef Chris Torek:
[The context, which the poster below snipped, was questions about
the internal mechanisms of C runtime systems, with particular
respect to function calls.]

learn(and understand) any x86 based assembly lang.

While there is nothing *wrong* with learning any particular assembly
language, it is a huge mistake to learn *only* x86 assembly and
assume that this is the way "everything" works. In particular,
the x86 is largely based on 1970s-era architectures (specifically
the Intel 4004, 8008, and 8080).
I beg to differ, x86 carries a lot of 8080, less of 8008 any most nothing
of the 4040. You could then say _every_ CPU carries a lot of the 4040, be
it 6502, 6800, 68K, because they are IC's. I don't buy that.
x86 implementations carry a huge
burden of "backwards compatibility" with a system optimized for
the conditions that held at the time. It is true that, through
great cleverness, modern CPUs that implement the IA32 architecture
squeeze tremendous performance from this klunky instruction set;
but the instruction set itself remains klunky nonetheless.

Compare, for instance, the call sequence:

/* compute three parameters, then: */
push parm3 /* write 3rd parameter to RAM, adjust stack pointer */
push parm2 /* write 2nd parameter to RAM, adjust stack pointer */
push parm1 /* write 1st parameter to RAM, adjust stack pointer */
call func
addl $12,%esp /* remove 12 bytes of parameter from stack */

with:

/* compute three parameters directly into arg registers */
call func
/* no stack adjustment required */

This has nothing to do with processors, the first is (perhaps was) the C
way, because this language has variadic functions, Pascal (the second type)
does not, here the called function always knows the number of parameters
and can discard them. I don't know how a printf is implemented at the
moment, perhaps that is changed. This same schema could easily done on a
68K.
<skipped more ranting>
Leave the CPU-bashing to their own news groups. It's very OT here.
 
R

Richard Tobin

Compare, for instance, the call sequence:

/* compute three parameters, then: */
push parm3 /* write 3rd parameter to RAM, adjust stack pointer */
push parm2 /* write 2nd parameter to RAM, adjust stack pointer */
push parm1 /* write 1st parameter to RAM, adjust stack pointer */
call func
addl $12,%esp /* remove 12 bytes of parameter from stack */

with:

/* compute three parameters directly into arg registers */
call func
/* no stack adjustment required */
[/QUOTE]
This has nothing to do with processors, the first is (perhaps was) the C
way, because this language has variadic functions, Pascal (the second type)
does not, here the called function always knows the number of parameters
and can discard them.

Your claim is clearly wrong, because the two call sequences (or
something very like them) are commonly used to implement C on
different processor architectures.

A calling convention that uses several registers for arguments is
practical on a processor with many registers, but not on one that has
only a few registers.

-- Richard
 
I

Ian Gay

(e-mail address removed) (Richard Tobin) wrote in

This has nothing to do with processors, the first is (perhaps was)
the C way, because this language has variadic functions, Pascal
(the second type) does not, here the called function always knows
the number of parameters and can discard them.

Your claim is clearly wrong, because the two call sequences (or
something very like them) are commonly used to implement C on
different processor architectures.

A calling convention that uses several registers for arguments is
practical on a processor with many registers, but not on one that
has only a few registers.

-- Richard
[/QUOTE]

SOmetime hava a look at the Watcom-generated code for x86...
 
K

Keith Thompson

Hello,
If u r using a gcc compiler just type gcc -E program_name

Please don't top-post. Read <http://www.caliburn.nl/topposting.html>
and <http://www.cpax.org.uk/prg/writings/topposting.php>.

Please don't use silly abbreviations like "u r"; take the time to
spell out words. This is a technical discussion forum, not a chat
room.

I also recommend <http://clc-wiki.net/wiki/Introduction_to_comp.lang.c>.

gcc's "-E" option has nothing to do with the question; it tells the
compiler to stop after preprocessing, *before* function calls are
processed.
 
M

Michael Wojcik

For a decent smattering of assembly languages, one might learn (at
least the rudiments of) x86, MIPS or SPARC, PowerPC, and ARM.
[snip other good recommendations]

When I did my undergrad work at Northeastern, the assembly classes
were taught on VAX, which was an interesting choice because it was
so extremely CISC. (VAX assembly, for those unfamiliar with the
machine, has opcodes for things like "insert item into linked list".
And it comes with an extensive macro library.)

Working in an assembly language that includes things like formatted
I/O and exception handling might give someone a rather rosy view of
what assembly programming is typically like, but it was a useful look
at what the CISC movement was aiming for.
(I might include IBM AS/400 "MIL" above if I had any idea what was
in it. :) )

Anyone who's interested can take a look at a message I posted here
back in July:

http://groups.google.com/group/comp.lang.c/msg/46980104ffa09593

It has a link to the IBM docs, and discusses the three kinds of
CALL operations (not including program activation and transfer-
control) available in MI.

OPM MI in particular was an odd beast; one of the CALL instructions
lets the callee return to a location other than the one it was
called from, for example.

--
Michael Wojcik (e-mail address removed)

Q: What is the derivation and meaning of the name Erwin?
A: It is English from the Anglo-Saxon and means Tariff Act of 1909.
-- Columbus (Ohio) Citizen
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top