views:

581

answers:

6

I know that in the architectures I'm personally familiar with (x86, 6502, etc), the stack typically grows downwards (i.e. every item pushed onto the stack results in a decremented SP, not an incremented one).

I'm wondering about the historical rationale for this. I know that in a unified address space, it's convenient to start the stack on the opposite end of the data segment (say) so there's only a problem if the two sides collide in the middle. But why does the stack traditionally get the top part? Especially given how this is the opposite of the "conceptual" model?

(And note that in the 6502 architecture, the stack also grows downwards, even though it is bounded to a single 256-byte page, and this direction choice seems arbitrary.)

Thanks!

+1  A: 

IIRC the stack grows downwards because the heap grows upwards. It could have been the other way around.

Christian Vik
+3  A: 

One good explanation I heard was that some machines in the past could only have unsigned offsets, so you'd want to the stack to grow downward so you could hit your locals without having to lose the extra instruction to fake a negative offset.

anq
A: 

One possible reason might be that it simplifies alignment. If you place a local variable on the stack which must be placed on a 4-byte boundary, you can simply subtract the size of the object from the stack pointer, and then zero out the two lower bits to get a properly aligned address. If the stack grows upwards, ensuring alignment becomes a bit trickier.

jalf
+4  A: 

As to the historic rationale, I can't say for certain (because I didn't design them). My thoughts on the matter are that early CPUs got their original program counter set to 0 and it was a natural desire to start the stack at the other end and grow downwards, since their code naturally grows upward.

Note that this setting of the program counter to 0 on reset is not the case for all early CPUs.

One of the first things some historical CPUs would do would be to scan memory from the top until if found a location that would read back the same value written, so that it would know the actual RAM installed (e.g., a z80 with 64K address space didn't necessarily have 64K or RAM, in fact 64K would have been massive in my early days). Once it found the top actual address, it would set the stack pointer appropriately and could then start calling subroutines.

With regard to the stacks growth, not all of them grow downwards, see this question, and my excellent answer to it :-), for details.

paxdiablo
I like the Z80 RAM detection strategy story. Makes some sense that text segments are laid out growing upwards-- programmers of yore had somewhat more direct contact with dealing with the implications of that than the stack.Thanks paxdiablo. The pointer to the set of alternative forms of stack implementations is also super interesting.
quixoto
+1  A: 

I believe it's purely a design decision. Not all of them grow downward -- see this SO thread for some good discussion on the direction of stack growth on different architectures.

Kaleb Brasee
A: 

I'm not certain but I did some programming for the VAX/VMS back in the days. I seem to remember one part of memory (the heap??) going up and the stack going down. When the two met, then you were out of memory.

Martin