The biggest use of the stack in a computer is in implementing procedures. Every procedural programming language in wide-spread use today uses a stack as its model for procedure call and return.
We can see how the procedure call instructions work by using another simple example. In C, the example would be
int main() { int i; p2(); return 0; } void p1() { int i; return; } void p2() { int i; return; }
(this is an admittedly really useless program!)
Let's think for just a moment about how this program executes. First,
the main()
function starts.
In the hc11, this gets translated to:
STACK equ $00ff EEPROM equ $f800 org $EEPROM * main program main lds #STACK jsr p1 eloop bra eloop * procedure p1 p1 bsr p2 rts *procedure p2 p2 rts end main
It's probably worth while to execute this example. What it'll do is:
Initialize the stack pointer to the top of RAM,
$00ff
Call procedure p1
. This will change the PC to the
address of P1
, subtract two from the SP, and put
the return address (the address of the instruction
after the jsr
) on the stack.
Call procedure p2
from p1
. Notice
that the call to p1
was a jsr
, while
this call is a bsr
. Once again, SP is decremented
and the return address is put on the stack.
Return from procedure p2
to p1
. It'll
land on the instruction after the bsr
(which is a
rts
). The SP is incremented to point to the other
return address.
An important thing to notice here is that the data isn't actually removed from the stack: it's still there, and there is a strong temptation to go ahead and use it. Don't. When we get into interrupts, it turns out that stale data like that can be corrupted at any moment without warning. Best to think of the data as just gone.
Return from procedure p1
to the main program. SP is
now back to original value, 00ff
.