The stack is a special type of "table" which is located inside the SNES RAM. Imagine the stack as a stack of plates. You can only add (push) or remove (pull/pop) a plate from the top. You can visualize it as something like this:
The empty "boxes" in above example are basically the values inside the stack, and they can hold any value. The collection of boxes are closed off from all sides, except from the top.
"Pushing" is the act of adding a value on top of the stack. Here's an example:
| | |[$32]|
|[$A9]| > |[$A9]|
As you can see, the value $32 is added on top of the stack. The stack now has five values instead of four.
"Pulling" (or "popping") is the act of reading a value from the top of the stack. Here's an example:
|[$32]| | |
|[$A9]| > |[$A9]|
As you can see, the value $32 is retrieved from the top of the stack.
There are opcodes to push the current value inside the A, X or Y registers onto the stack:
There are also opcodes to pull the current value from the stack into the A, X or Y registers:
Imagine the following scenario: The X register has to stay at the value $19, no matter what, but you really have to use X for something else. How would one do that? You use PHX to preserve the value in X in the stack, before you use an instruction which modifies the contents of X:
; Imagine X has the value $19 in the stack
PHX ; Push X ($19) onto stack. Result: Stack 1st value = $19
LDX $91 ; Load the value in address $7E0091 into X
LDA $1000,x ; \ X is now modified, and we use it to index RAM
STA $0100 ; /
PLX ; Restore X. X is now $19 again
All the previous explanations and behaviours apply to 16-bit stack operations as well. It's just that you're pushing and pulling 16-bit values, not 8-bit values.
This also means that if you push two 8-bit values onto the stack, you can pull a single 16-bit value later.
There are also other push and pull commands, which are not affected by 8-bit or 16-bit mode A, X and Y: