Although BDD did a good job above, I started this earlier and got called away just before I could finish. I might as well finish and post it.
I have no idea what Lua is, but here are some stack basics.
A stack is generally a last-on-first-off storage area, meaning that the last number put on is the first one to come off. This is the oposite of FIFO (first-in-first-out). A processor's instructions that use the hardware stack will have the incrementing and decrementing of the pointer integrated and automatic so your program doesn't have to use more instructions to take care of that part.
The most basic use is probably storing return addresses for subroutines, because you need to be able to nest them, ie, have one subroutine call another, which calls another, etc., and neither the one doing the calling nor the one being called should have to worry about how many subroutine calls were made before it that have not been returned to yet. On the 6502, the normal subroutine call instruction is JSR (Jump to SubRoutine, or, more accurately, Jump, Saving Return address). It puts the address on the stack so the program pointer can get back to where it left off in the calling routine before it did the subroutine. The subroutine's RTS (ReTurn from Subroutine) uses this address left on the stack to know where to jump back to.
You can also pass parameters to your subroutine on the hardware stack, using PHA for example. If a subroutine doesn't need more than three bytes passed to it, you can get away with using A, X, and Y unless you really need to leave one of those undisturbed for something else. For more, you can use variables in RAM, or, if it proves to be rather poor use of memory to set up tons of variables that only get used in one place, pass them via the stack instead, so they only exist when they're in use. Right away you might see a problem there. If the subroutine starts pulling bytes off the stack, the first two bytes will be the address it will need to return to when it's done. If it pulls them off, where is it going to keep them? It defeats the purpose of the stack. Wat you can do is TSX then something like ADC 103,X. This way you can reach different depths into the stack (by using 104, 105, 106, etc., not using extra instructions to increment and decrement X) without taking everything off the top to get to those elements. Going in order then is not required, and you're not limited to just PLA, PLX, and PLY, (as I showed with the ADC example). To make things easier, the 65816 added stack-relative addressing modes (as BDD mentioned).
JSR and RTS have other uses too, but we'll keep this simple here.
The interrupts do use the stack to store the address where to resume execution of the background routine when the interrupt service is finished, and to keep the processor status to restore when you go back to the background routine. If the interrupt-service routine (ISR) uses A, X, or Y, it needs to store those as well to restore later. I frequently find though that A is the only one I need in the ISR, and there's the rare case where the interrupt can be serviced without even using A (like to increment bytes in memory). This is to say you don't automatically have to push A, X, and Y in every ISR and pull them back off the stack at the conclusion of the ISR.
The Forth programming language and environment (since BDD mentioned it) has two stacks standard: a return stack and a data stack. It's almost like the 6502 was designed partly with Forth in mind, because the 6502's hardware stack works out perfectly for Forth's return stack, and zero page with its added addressing modes (like indirect indexed) works out perfectly for Forth's data stack. Sometimes Forth will have an additional stack for floating-point or other uses, but two is standard.
_________________ http://WilsonMinesCo.com/ lots of 6502 resources The "second front page" is http://wilsonminesco.com/links.html . What's an additional VIA among friends, anyhow?
|