tags:

views:

1760

answers:

5

I am preparing some training materials in C and I want my examples to fit the typical stack model.

What direction does a C stack grow in Linux, Windows, Mac OSX (PPC and x86), Solaris, and most recent Unixes?

+1  A: 

Stack grows down on x86 (defined by the architecture, pop increments stack pointer, push decrements.)

Michael
+19  A: 

Stack growth doesn't usually depend on the operating system itself, but on the processor it's running on. Solaris, for example, runs on x86 and SPARC. Mac OSX (as you mentioned) runs on PPC and x86. Linux runs on everything from my big honkin' System z at work to my puny little wristwatch (not really, but I'm sure it could).

The processors and their direction are:

x86          down
SPARC        in a circle, very clever architecture, see below.
PPC          down, I think.
System z     in a linked list, I kid you not.
             (but still down, at least for zLinux).
ARM          selectable (thanks, Michael Burr).
Mostek6502   down (but only 256 bytes).
RCA1802A     any way you want, subject to SCRT implementation.
PDP11        down.

Showing my age on those last few, the 1802 was the chip used to control the early shuttles (sensing if the doors were open, I suspect, based on the processing power it had :-) and my second computer, the COMX-35 (following my ZX80).

As an aside:

PDP11 details gleaned from here.

The SPARC architecture, by the way, is one example of a strange stack architecture - it's a circular buffer with a sliding window, giving a limited depth stack. See here for details.

The afore-mentioned SCRT technique is another - the 1802 used some or it's sixteen 16-bit registers for SCRT (standard call and return technique). One was the program counter, you could use any register as the PC with the SEP Rn instruction. One was the stack pointer and two were set always to point to the SCRT code address, one for call, one for return. No register was treated in a special way. Keep in mind these details are from memory, they may not be totally correct.

For example, if R3 was the PC, R4 was the SCRT call address, R5 was the SCRT return address and R2 was the "stack" (quotes as it's implemented in software), SEP R4 would set R4 to be the PC and start running the SCRT call code.

It would then store R3 on the R2 "stack" (I think R6 was used for temp storage), adjusting it up or down, grab the two bytes following R3, load them into R3, then do SEP R3 and be running at the new address.

To return, it would SEP R5 which would pull the old address off the R2 stack, add two to it (to skip the address bytes of the call), load it into R3 and SEP R3 to start running the previous code.

Very hard to wrap your head around initially after all the 6502/6809/z80 stack-based code but still elegant in a bang-your-head-against-the-wall sort of way. Also one of the big selling features of the chip was 16 16-bit registers, and you immediately lost 7 of those (5 for SCRT, two for DMA and interrupts from memory). Ahh, the triumph of marketing over reality.

System z is actually quite similar, using its R14 and R15 registers for call/return.

paxdiablo
To add to the list, ARM can grow in either direction, but can be set to one or the other by a particular silicon implementation (or can be left selectable by software). The few I've dealt with have always been in grow-down mode.
Michael Burr
Wow, this is revelatory - I've always assumed it was down for every architecture. Linked lists!
Bayard Randel
I think PPC is selectable, but it grows down on OS X (since the 68k that Mac ran on before had a downward stack.)
Michael
שׁAny idea what it was on PDP11? I learn assembly on that one...
Uri
PDP11 was downward, according to http://history.dcs.ed.ac.uk/archive/docs/psrthesis/psrthesis.html
Michael
In the little bit of the ARM world I've seen so far (ARM7TDMI) the stack is entirely handled in software. Return addresses are stored in a register which is saved by software if needed, and pre-/post-increment/decrement instructions allow to put it and other stuff on the stack in either direction.
starblue
@starblue - you are right - my mistake. It's endianness used by the ARM that's selectable, but can be fixed one way or the other by the silicon OEM.
Michael Burr
PPC stack growth is compiler convention (stack pointer is just an ordinary register), but it's been down in every implementation I've ever seen.
Crashworks
the 8051 micro-controller family grows up in the 128 byte "IDATA" portion of memory, and most local variables are compiled to use static locations in the larger external memory.
Tom Leys
A: 

It grows down because the memory allocated to the program has the "permanent data" i.e. code for the program itself at the bottom, then the heap in the middle. You need another fixed point from which to reference the stack, so that leaves you the top. This means the stack grows down, until it is potentially adjacent to objects on the heap.

Kai
+3  A: 

In C++ (adaptable to C) stack.cc:

static int
find_stack_direction ()
{
    static char *addr = 0;
    auto char dummy;
    if (addr == 0)
    {
        addr = &dummy;
        return find_stack_direction ();
    }
    else
    {
        return ((&dummy > addr) ? 1 : -1);
    }
}
J.F. Sebastian
Wow, it's been a long time since I've seen the "auto" keyword.
paxdiablo
sigjuice
Trying to investigate the layout of your own stack -- something which C/C++ don't specify at all -- is "unportable" to begin with, so I wouldn't really care about that. It looks like this function will only work correctly once, though.
ephemient
A: 

The advantage of growing down is in older systems the stack was typically at the top of memory. Programs typically filled memory starting from the bottom thus this sort of memory management minimized the need to measure and place the bottom of the stack somewhere sensible.

mP