Links

The stack

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.
Technically speaking, because the stack is an area inside the RAM, you can access any value you want, using special stack-relative addressing modes rather than using only push and pull opcodes. For the purposes of this chapter, we'll assume the stack indeed is a perfect stack of plates.

Push

"Pushing" is the act of adding a value on top of the stack. Here's an example:
[$32]
| push
v
| | |[$32]|
|[$B0]| |[$B0]|
|[$A9]| > |[$A9]|
|[$82]| |[$B2]|
|[$14]| |[$14]|
‾‾‾‾‾‾‾ ‾‾‾‾‾‾‾
As you can see, the value $32 is added on top of the stack. The stack now has five values instead of four.

Pull/Pop

"Pulling" (or "popping") is the act of reading a value from the top of the stack. Here's an example:
[$32]
^ pull
|
|[$32]| | |
|[$B0]| |[$B0]|
|[$A9]| > |[$A9]|
|[$82]| |[$B2]|
|[$14]| |[$14]|
‾‾‾‾‾‾‾ ‾‾‾‾‾‾‾
As you can see, the value $32 is retrieved from the top of the stack.
All pulling instructions affect the Negative and the Zero processor flags.

Push A, X, Y

There are opcodes to push the current value inside the A, X or Y registers onto the stack:
Opcode
Full name
Explanation
PHA
Push A onto stack
Pushes the current value of A onto the stack
PHX
Push X onto stack
Pushes the current value of X onto the stack
PHY
Push Y onto stack
Pushes the current value of Y onto the stack

Pull A, X, Y

There are also opcodes to pull the current value from the stack into the A, X or Y registers:
Opcode
Full name
Explanation
PLA
Pull into A
Pulls a value from the stack into the A register
PLX
Pull into X
Pulls a value from the stack into the X register
PLY
Pull into Y
Pulls a value from the stack into the Y register

Example

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
The A, X and Y registers do not have a separate stack. There is only one stack, specified by the "stack pointer register". For detailed explanations about the stack pointer register, see: Stack pointer register​

16-bit mode stack operations

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.

Other push and pull operations

There are also other push and pull commands, which are not affected by 8-bit or 16-bit mode A, X and Y:
Opcode
Full name
Explanation
Value size
PHB
Push data bank register
Pushes the data bank register's current value onto the stack
8-bit
PLB
Pull data bank register
Pulls a value from the stack into the data bank register
8-bit
PHD
Push direct page register
Pushes the direct page register's current value onto the stack
16-bit
PLD
Pull direct page register
Pulls a value from the stack into the direct page register
16-bit
PHP
Push processor flags
Pushes the processor flags register's current value onto the stack
8-bit
PLP
Pull processor flags
Pulls a value from the stack into the processor flag register
8-bit
PHK
Push program bank
Pushes the bank value of the currently executed opcode (which is PHK) onto the stack
8-bit
PEA $XXXX
Push effective address
Pushes the specified 16-bit value onto the stack. Don't let the name of the opcode mislead you. This doesn't read out any address
16-bit
PEI ($XX)
Push effective indirect address
Pushes the value at the given direct page address onto the stack. The direct page register can affect the given address
16-bit
PER label
Push program counter relative
A rather complicated push. In short: it pushes the absolute address of the given label onto the stack. What happens during assembly is that the assembler calculates the relative distance between PER and the given label. This relative distance is a signed 16-bit value and is used as the parameter for PER. The opcode finally assembles into PER $XXXX. Because of its relative nature, the opcode can also be used in the SNES RAM
16-bit