6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Jul 12, 2024 8:33 am

All times are UTC




Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Fri Dec 21, 2012 6:23 pm 
Offline
User avatar

Joined: Wed May 30, 2012 7:45 pm
Posts: 58
Location: Dallas, TX
Having a background in programming, I am familiar with common
data structures including Stacks. My experience with using them has not
been extensive. My development using Lua relied on the Lua Virtual Stack,
while hooking into the VM from C to Lua. I also have written a small scripting
language that has stack based operations...
I suppose it should be stated that my 6502 assembler is NESASM because I
am learning NES programming...
I'm having a hard time understanding how the Stack is used. Can it be compared
to the way Lua provides an omni-present bridge from one environment to another?
Is it just a way of loading a procedure that is called outside of normal memory?
Is it used with interrupts?
Thanks, I know this is as clear as mud, but I'm on my lunch and didn't have a whole
lot of time to gather my thoughts.

_________________
http://www.thestarrlab.com


Top
 Profile  
Reply with quote  
PostPosted: Fri Dec 21, 2012 8:53 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8264
Location: Midwestern USA
Johnny Starr wrote:
Having a background in programming, I am familiar with common
data structures including Stacks. My experience with using them has not
been extensive. My development using Lua relied on the Lua Virtual Stack,
while hooking into the VM from C to Lua. I also have written a small scripting
language that has stack based operations...
I suppose it should be stated that my 6502 assembler is NESASM because I
am learning NES programming...
I'm having a hard time understanding how the Stack is used. Can it be compared
to the way Lua provides an omni-present bridge from one environment to another?
Is it just a way of loading a procedure that is called outside of normal memory?
Is it used with interrupts?
Thanks, I know this is as clear as mud, but I'm on my lunch and didn't have a whole
lot of time to gather my thoughts.

I don't know anything about Lua, but as you mentioned a "virtual stack," it must be that this is a software stack about which you are talking. Such stacks are manipulated by sequences of machine instructions, and are typically used to store and retrieve parameters that are passed to called functions (aka subroutines). Software stacks are defined by the programmer who wrote the code and relatively speaking, tend to demand a fair amount of processing to manage.

A feature of virtually all microprocessors (MPU) is the "hardware stack," which the MPU uses to store subroutine return addresses and, in some case, copies of registers during interrupt processing. The hardware stack is an area of main memory that may be accessed like any other memory, but is normally utilized via special instructions built into the MPU. The 6502 and 65C02 "hard wire" the stack to $0100 in memory and use an eight bit stack pointer (SP), giving a usable stack address range of $0100-$01FF, or 256 bytes. It is customary in the system reset routine to initialize SP to $FF, as each time a byte is pushed to the stack SP is decremented.

The more advanced 65C816 utilizes a 16 bit SP, which gives a usable stack address range of $000000-$00FFFF, or 65,536 bytes. Again, the system reset routine initializes SP to a specific starting point, e.g., $00CDFF in my POC V1 unit. Unlike the 65(c)02, the 65C816's hardware stack can be readily relocated "on the fly" by merely loading a new value into SP, making it possible to assign temporary stacks to subroutines. This feature has important implications in languages that facilitate recursive techniques.

For the most part, usage of the hardware stack is automatic in nature. The JSR (Jump to SubRoutine) instruction automatically pushes the return address minus one, and the RTS (ReTurn from Subroutine) instruction, normally found at the end of a subroutine, pulls the address pushed by the most recent JSR, increments it and loads it into the program counter (PC) to resume execution. A response to an interrupt pushes PC and the status register (SR), a process that is reversed by the RTI (ReTurn from Interrupt) instruction. The 65C816 has instructions that facilitate using the stack as a "scratchpad" for passing parameters into subroutines, which makes this MPU more adept at handling stack-based environments, such as Forth.

Outside of the "automatic" stack handling of JSR, etc., you can address the stack like ordinary memory, for example, to retrieve a copy of SR after it has been pushed during interrupt processing. Such an operation is a common idiom in 6502 code to distinguish a hardware interrupt request from a software interrupt request, since both jump through the same vector.

Hope this answers at least part of your query.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Fri Dec 21, 2012 9:45 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8465
Location: Southern California
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?


Top
 Profile  
Reply with quote  
PostPosted: Sat Dec 22, 2012 11:21 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10842
Location: England
Hi Johnny.
Let me add some general thoughts. The 6502 stack is very like the C stack, in that it can hold data and return addresses. Indeed, during an interrupt it holds additional data and a return address - an interrupt being somewhat like a subroutine taken without warning.

However, the 6502 stack is small, and there is only weak support for addressing data within it, so it is often used only for return addresses (and for interrupts) - parameters for subroutines may instead be passed in the (limited) registers, or by shared memory (whether at agreed locations or by passing an address.)

As BDD says, the 65816 extends the 6502 in several ways, including better support for use of the stack.

I'm not sure what you might mean by 'outside of normal memory' - the 6502 has a simple and small memory model, within which the stack occupies a fixed 256-byte area. As to how memory is allocated between routines, the 6502 has nothing to say about it: it's a question of the prevailing conventions and the installed software.

There's another use of the concept of a stack, which is for operands, as seen in the Java VM but not the Lua VM, and as seen in Forth but not in C. I don't think this relates to your question.

I hope this helps a little!

Cheers
Ed


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 01, 2013 11:24 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8465
Location: Southern California
Johnny Starr, did the above responses answer your questions? Did they produce more questions? I was looking for something else and came across this again and figured I should find out if we're missing the question or if we addressed it adequately, since I'm little by little writing a primer on stacks [Edit: It's up, at http://wilsonminesco.com/stacks/ ] and I want to address the real questions people have that they might even be afraid to ask, in addition to giving some stack tricks that are simple but have not occurred to many. Any other questions or problems or misunderstandings you care to mention may end up helping quite a few others.

_________________
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?


Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 02, 2013 4:47 am 
Offline

Joined: Mon Jan 07, 2013 2:42 pm
Posts: 576
Location: Just outside Berlin, Germany
GARTHWILSON wrote:
Any other questions or problems or misunderstandings you care to mention may end up helping quite a few others.


As a complete aside, I was confronted with a Towers of Hanoi problem a while ago (in Mass Effect, of all places), which I remembered was one of the more interesting uses of stacks. Not something that has to go in a text, but might be a reference to "thinking with stacks" if you are planing to include something like that.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: