direction of stack growth

J

junky_fellow

Hi all,

Is there any way by which we mat determine the direction of stack
growth (from
higher address to lower address Or from lower address to higher
address) ?
I know this question is implementation specific and this may not be the
correct place
to ask this. But any hints would help me a lot.

I thought of the following way (assuming that the implementation uses
stack to
save the local variables as for instance in m68k processor).
In a function f1(), declare a local variable (local1).
save its address. Call another function f2() from f1 and in f2()
declare another local
variable (local2) and return its address to f1(). Now, compare the
addresses of local1
and local2 to determine the direction of stack growth.

Is this the right way of doing it ? Can we compare the adresses of the
local variables
local1 and local ? If not, what is the right of doing it ?
Also, some of the implementations don't use stack to store the local
variables. They store
the local varaibles in registers. In those implementations what would
happen if I try
to print address of local variable (using &local1) ? I am asking this,
as the local
variable may not have been allocated on stack or some memory location.
The compiler
might have used some general purpose register for that. In that case,
what output
we will get if we print the address of a local variable ?


Thanx for any help/hint ....
 
C

Chris Dollin

Hi all,

Is there any way by which we mat determine the direction of stack
growth (from
higher address to lower address Or from lower address to higher
address) ?

There is no portable way to do this. On an given implementation, the
question might even be meaningless. (Consider a C implementation on
a Lispy machine where stack frames are allocated from the heap.)

Why do you want to know, anyway?
 
J

junky_fellow

Chris said:
There is no portable way to do this. On an given implementation, the
question might even be meaningless. (Consider a C implementation on
a Lispy machine where stack frames are allocated from the heap.)

Why do you want to know, anyway?

I know, this cannot be done portably. But, can you suggest some way for
a
specific implementation (as for instance motorola's 68k processor) ?
 
K

Keith Thompson

Hi all,

Is there any way by which we mat determine the direction of
stack growth (from higher address to lower address Or from lower
address to higher address) ? I know this question is implementation
specific and this may not be the correct place to ask this. But any
hints would help me a lot.

There is no portable way to determine this.
I thought of the following way (assuming that the implementation
uses stack to save the local variables as for instance in m68k
processor). In a function f1(), declare a local variable (local1).
save its address. Call another function f2() from f1 and in f2()
declare another local variable (local2) and return its address to
f1(). Now, compare the addresses of local1 and local2 to determine
the direction of stack growth.

Relational operators on pointer values are defined only when both
pointers point within the same object (or just past the end of it).
A comparison like "&local1 < &local2" invokes undefined behavior.

It's likely to work as you expect on most implementations, but it's
not guaranteed by the standard.

Is this the right way of doing it ? Can we compare the adresses of
the local variables local1 and local ? If not, what is the right of
doing it ? Also, some of the implementations don't use stack to
store the local variables. They store the local varaibles in
registers. In those implementations what would happen if I try to
print address of local variable (using &local1) ? I am asking this,
as the local variable may not have been allocated on stack or some
memory location. The compiler might have used some general purpose
register for that. In that case, what output we will get if we print
the address of a local variable ?

You can legally take the address of any object that's not declared
with the "register" keyword. If the implementation chooses to store
the object in a register, it must also store it in memory if you take
its address. (Most likely, taking the address of an object will cause
the compiler *not* to store it in a register.)
 
F

Flash Gordon

I know, this cannot be done portably.

Then you know it is not topical here since you've been around here before.
> But, can you suggest some way for
a
specific implementation (as for instance motorola's 68k processor) ?

Yes, read the documentation.
 
C

Chris Dollin

I know, this cannot be done portably. But, can you suggest some way for
a
specific implementation (as for instance motorola's 68k processor) ?

Not apart from the non-portable method you suggest.

But /why/ do you want to know this?
 
T

Tim Prince

Chris said:
Not apart from the non-portable method you suggest.

But /why/ do you want to know this?
Are you trying to second guess the way it's done in gcc build? Surely
it worked at some time in the past, if not now. Why not go to a
newsgroup where this is on topic?
 
D

Duncan Muirhead

I know, this cannot be done portably. But, can you suggest some way for
a
specific implementation (as for instance motorola's 68k processor) ?
You could look at the assembly code output from the compiler.
Duncan
 
J

junky_fellow

Keith said:
There is no portable way to determine this.


Relational operators on pointer values are defined only when both
pointers point within the same object (or just past the end of it).
A comparison like "&local1 < &local2" invokes undefined behavior.

It's likely to work as you expect on most implementations, but it's
not guaranteed by the standard.

Thanx a lot for your help. I have one more doubt that why it is illegal
to
compare the addresses of two local variables ? One reason I may think
of
is that pointers are not plain integers and they may be composed of
base and offset. But, in that case as well, the base address of the
segment
(stack segment ) should be the same as both the local variables are on
the same stack (although the stack frames are different).
So, why their comparison is illegal ?
 
C

Chris Dollin

Thanx a lot for your help. I have one more doubt that why it is illegal
to
compare the addresses of two local variables ?

It's not /illegal/. It's /undefined/.

I believe it's to allow implementations the leeway to implement pointer
comparision as efficiently as possible. By only specifying the behaviour
of pointer comparison when the pointers point into the same array [1],
the implementation is at liberty to assume compared pointers point
into the same entity.

So a (some) segmented implementation(s) might only compare the offset
and not the segment, if that was more efficient than comparing both.

Also note that local variables can be stored in any order the compiler
wants, independantly of the order the stack grows in. EG it might put
the most-used locals in registers, the next-most-used in stack locations
that are cheap to access [2], and the less-used ones in more expensive
locations. The declaration `int a, b;` could put `a` before or after
`b`, depending on their use patterns. The compiler is not obliged
to discard efficiency just because of an accident of source ordering.

[1] Or array-like entity - mallocated store - or one-past-the-end.

[2] Like `(sp)` on the PDP-11.
 
R

Richard Tobin

Thanx a lot for your help. I have one more doubt that why it is
illegal to compare the addresses of two local variables ? One reason
I may think of is that pointers are not plain integers and they may
be composed of base and offset. But, in that case as well, the base
address of the segment (stack segment ) should be the same as both
the local variables are on the same stack (although the stack frames
are different). So, why their comparison is illegal ?

Typical C implementations use a stack, but there's no requirement to.
An implementation is free to store each function call's variables in a
different segment for example. So the standard doesn't require
comparisons (except equality comparisons) to work.

For typical implementations on current hardware, comparing the
addresses will do what you expect. If I remember correctly, Doug
Gwyn's "portable" alloca() used this method.

-- Richard
 
C

Chris Dollin

Chris said:
I believe it's to allow implementations the leeway to implement pointer
comparision as efficiently as possible. By only specifying the behaviour
of pointer comparison when the pointers point into the same array [1],

<fx:mumble face="red">can't remember whether this is for equality too</>.
 
K

Kenneth Brody

I know, this cannot be done portably. But, can you suggest some way for
a specific implementation (as for instance motorola's 68k processor) ?

Well, if you know the processor, you know that stack order already. :)

However, something like this _may_ work in a stack-based implementation:

#include <stdio.h>

void foo(int *);
int main(int argc,char *argv[])
{
int i;
foo(&i);
}
void foo(int *ii)
{
int j;
if ( &j < ii )
printf("I think the stack grows down.\n");
else if ( &j > ii )
printf("I think the stack grows up.\n");
else
printf("I'm really confused now.\n");
}

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
R

Richard Tobin

Kenneth Brody said:
Well, if you know the processor, you know that stack order already. :)

Not at all! Many processors make it easier to run stacks in some
particular direction, but it would be quite possible to write a C
implementation that didn't follow the convention.

-- Richard
 
K

Kenneth Brody

Richard said:
Not at all! Many processors make it easier to run stacks in some
particular direction, but it would be quite possible to write a C
implementation that didn't follow the convention.

True, but probably the only reason to do so would be to break programs
that assumed otherwise. :)

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
W

Walter Roberson

Richard Tobin wrote:
True, but probably the only reason to do so would be to break programs
that assumed otherwise. :)

Or to increase compatability with programs that assumed a particular
direction.

Another point is that some processors are able to run in multiple modes,
not all of which will necessarily have the same optimal stack direction.

[I'm thinking of the MIPS ability to run either endian; I don't recall
whether that has any effect on best stack growth or upon "conventional"
stack growth.]
 
F

Flash Gordon

Richard said:
Not at all! Many processors make it easier to run stacks in some
particular direction, but it would be quite possible to write a C
implementation that didn't follow the convention.

On one processor I've used it is just as easy (and has no performance
penalty) to make the stack grow in either direction.
 
K

Keith Thompson

Chris Dollin said:
Chris said:
I believe it's to allow implementations the leeway to implement pointer
comparision as efficiently as possible. By only specifying the behaviour
of pointer comparison when the pointers point into the same array [1],

<fx:mumble face="red">can't remember whether this is for equality too</>.

Equality comparison is defined for pointers to distinct objects (and
yields 0).

C99 6.5.9:

Two pointers compare equal if and only if both are null pointers,
both are pointers to the same object (including a pointer to an
object and a subobject at its beginning) or function, both are
pointers to one past the last element of the same array object, or
one is a pointer to one past the end of one array object and the
other is a pointer to the start of a different array object that
happens to immediately follow the first array object in the
address space.

And n1124 adds:

For the purposes of these operators, a pointer to an object that
is not an element of an array behaves the same as a pointer to the
first element of an array of length one with the type of the
object as its element type.
 
J

Jack Klein

Well, if you know the processor, you know that stack order already. :)

Not really. ARM, for example, can build stacks in either direction,
with no difference in code size or execution speed.
 

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,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top