I'm reading Professional Assembly Language by Richard Blum,and I am confusing about a Inconsistency in the book and I wondering what exactly is program stack's growth direction?
This is the picture from page 312, which is suggesting that program stack grows up.
But when I reached page 322,I see another version, which suggesting that program stack grows down.
and this
The book is not inconsistent; each drawing shows higher addresses at the top.
The first drawing illustrates a stack that grows downward. The caller pushes parameters onto the stack, then calls the new function. The act of calling pushes the return address onto the stack. The callee then pushes the current value of the base pointer onto the stack, copies the stack pointer into the base pointer, and decrements the stack pointer to make room for the callee's local variables.
Stack growth direction varies with OS, CPU architecture, and probably a number of other things.
The most common layout has the stack start at the top of memory and grow down, while the heap starts at the bottom and grows up. Sometimes it's the other way around, eg. MacOS prior to OSX put the stack just above the code area, growing up, while the heap started at the top of memory and grew down.
Some background:
For different processors the meaning of the stack pointer and the direction of the stack may differ. For TMS Piccolo controllers stack is growing up so that "PUSH" will increment the stack pointer. The stack pointer may point to the value last pushed or to the location where the next value to be pushed is written to. The ARM processor allows all 4 possible combinations for the stack so there must be a convention on how to use the stack pointer.
On x86 processors:
On x86 processors stack ALWAYS grows downwards so a "PUSH" instruction will decrement the stack pointer; the stack pointer always points to the last value pushed.
The first picture shows you that the addresses after the stack pointer (address > stack pointer) already contain values. If you store more values to the stack they are stored to locations below the stack pointer (the next value will be stored to address -16(%ebp)). This means that the picture from page 312 also shows a down-growing stack.
-- Edit --
If a processor has a "PUSH" instruction the direction of stack growth is given by the CPU. For CPUs that do not have a "PUSH" instruction (like PowerPC or ARM without ARM-THUMB code) the Operating System has to define the direction of stack growth.
Even more compelling definition of stack growth direction is (if the processor has it) interrupt stack. Some architectures (like PowerPC) don't really have a HW stack at all. Then the system designer can decide which way to implement the stack: Pre-incrementing, post-incrementing. pre-decrementing or post-decrementing.
In PPC the calls use link register, and next call overwrites it, if the return address is not programmatically saved.
PPC interrupts use 2 special registers - the "return address" and machine status. That's because instructions can be "restarted" after interrupt - a way to handle interrupts in pipelined architecture.
pre-increment: stack pointer is incremented before store in push - stack pointer points to the last used item. Seen in few more strange 8-bit architectures (some forth-processors and the like).
post-incrementing: store is done before stack pointer incrementing - stack pointer points to the first free stack element.
pre- and post decrementins: similar to the above, but stack grows downwards (more common).
Most common is post-decrementing.