rhialto made a quick patch
http://www.falu.nl/~rhialto/watchpoints1.diff.txt
eg
break load 0 $ffff if @cpu:(pc) < $80
Stack Watching in VICE
Moderator: Moderators
Re: Stack Watching in VICE
I'm just a Software Guy who has no Idea how the Hardware works. Don't listen to me.
- chysn
- Vic 20 Scientist
- Posts: 1204
- Joined: Tue Oct 22, 2019 12:36 pm
- Website: http://www.beigemaze.com
- Location: Michigan, USA
- Occupation: Software Dev Manager
Re: Stack Watching in VICE
Ooh, cool!groepaz wrote: ↑Fri Oct 06, 2023 1:37 pm rhialto made a quick patch
http://www.falu.nl/~rhialto/watchpoints1.diff.txt
eg
break load 0 $ffff if @cpu:(pc) < $80
My stack saga is coming to a happy conclusion. I wanted to preserve stack structure between breakpoints in wAx. This was made tricky because I'd always get return addresses onto the stack when executing with G. But now I'm assuming that if you're continuing execution with G alone, those return addresses are down there in the stack somewhere, and they don't need to be added again. This allows code like this:
which is how a monitor should behave after a breakpoint. VICmon gets it right, even though you have to enter an explicit address, you can't just hit G:
and HES Mon allows you to continue, but blows up the stack:
Anyway, that's what I've been doing today, figuring out the stack! Thanks to everyone who helped, I learned a lot today.
- Mike
- Herr VC
- Posts: 5134
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Re: Stack Watching in VICE
As you can infer from my edited, earlier post in the thread, MINIMON also manages this feat. During execution of any of its commands, the stack is essentially 'flat' *) and the commands all return to the command prompt with an explicit JMP instruction. The G command only pushes the 3 bytes of PC and SR onto stack to be pulled again by RTI; A, X and Y are directly loaded from the register dump just before RTI.chysn wrote:[...] which is how a monitor should behave after a breakpoint [...]
You might want to take a look at the thread "Fire-and-forget register saving" on 6502.org for even more serious stack-fu.I learned a lot today.

*) this does not hold, of course, for the two dozen or so auxiliary sub-routines called by the commands. But one can, for example, wipe the entire stack area with the F command and MINIMON still returns to the command line, relatively unharmed (just the register dump has been overwritten).
- chysn
- Vic 20 Scientist
- Posts: 1204
- Joined: Tue Oct 22, 2019 12:36 pm
- Website: http://www.beigemaze.com
- Location: Michigan, USA
- Occupation: Software Dev Manager
Re: Stack Watching in VICE
Oh, I had no doubts whatsoever about MINIMON behaving itself!
Interesting concept but I don't care for it for VIC-20, where memory is tight. I have no problems with bespoke routines having bespoke register effects to save bytes. It's not that much of a hardship.You might want to take a look at the thread "Fire-and-forget register saving" on 6502.org for even more serious stack-fu.![]()
Perhaps off-topic for this thread, but how does MINIMON handle an RTS during execution, then? What return address gets pulled?The G command only pushes the 3 bytes of PC and SR onto stack to be pulled again by RTI; A, X and Y are directly loaded from the register dump just before RTI.
- Mike
- Herr VC
- Posts: 5134
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Re: Stack Watching in VICE
I just wanted to mention it for completeness.chysn wrote:Oh, I had no doubts whatsoever about MINIMON behaving itself!

The Acorn MOS had that register preserving policy for intra-OS calls. There were obviously enough routines involved so it was sensible to exchange the 10 bytes necessary for the prologue and epilogue by a 3 byte JSR for each callee plus this single stack shuffle procedure.Interesting concept but I don't care for it for VIC-20, where memory is tight. I have no problems with bespoke routines having bespoke register effects to save bytes. It's not that much of a hardship.
Most likely, $E144 - 1 of the SYS command used to invoke MINIMON. BASIC then continues with whatever it finds in the input area behind the position of the last digit it read from the SYS address. The result likely is a ?SYNTAX error, as MINIMON also uses this area for its command line. You'd normally end routines called by the G command with the BRK instruction instead. Alternatively, a small JSR $xxxx/BRK stub somewhere in RAM can supply the necessary return address for RTS. Likewise, to return to BASIC you'd normally use the X command.Perhaps off-topic for this thread, but how does MINIMON handle an RTS during execution, then? What return address gets pulled?
It is no error to have a BRK instruction somewhere, when that routine was not directly called by the G command. You end up in the monitor with all registers and the current stack frame preserved.
I show an example of this in the start post of "A sample debugging session with MINIMON".
Edit:
chysn wrote:HES Mon allows you to continue, but blows up the stack: [...]

Re: Stack Watching in VICE
chysn, does your assembler JSR to the PC instead of RTI'ing to it as Mike said? I guess based on your question regarding RTS behavior that your assembler returns to the monitor in such a scenario? I've been working on my own assembler and went with the push PC, P, Y, X, A, RTI approach as well.
Some monitors offer a separate command for the JSR behavior (usually J IIRC), but AFAIK GO typically behaves as Mike described.
Some monitors offer a separate command for the JSR behavior (usually J IIRC), but AFAIK GO typically behaves as Mike described.
- chysn
- Vic 20 Scientist
- Posts: 1204
- Joined: Tue Oct 22, 2019 12:36 pm
- Website: http://www.beigemaze.com
- Location: Michigan, USA
- Occupation: Software Dev Manager
Re: Stack Watching in VICE
I do not use RTI. I'm basically enclosing execution in the SYS code, retrieving register and PC values from SYS's storage locations and then setting those locations upon both RTS and BRK. I see how RTI is the best choice for a self-contained monitor, as you have total control over what's left when control is handed over to user code.Wilson wrote: ↑Sat Oct 07, 2023 2:04 pm chysn, does your assembler JSR to the PC instead of RTI'ing to it as Mike said? I guess based on your question regarding RTS behavior that your assembler returns to the monitor in such a scenario? I've been working on my own assembler and went with the push PC, P, Y, X, A, RTI approach as well.
Some monitors offer a separate command for the JSR behavior (usually J IIRC), but AFAIK GO typically behaves as Mike described.
However, wAx is a BASIC extension, which complicates that a little. There are actually two sets of return addresses that get added to the stack. When user code returns via RTS, it returns from SYS, then from the GO tool, then jumps to the warm start vector at $0302 (if in direct mode) or to the interpreter inner loop (if within a BASIC program). RTS doesn't "return to the monitor" because you're never "in" a monitor. Even BRK returns to BASIC. In direct mode, it puts the wedge prompt in the keyboard buffer so that it seems like you're still "in" the monitor.
Because BASIC is involved, I don't have much control over what BASIC puts on the stack. But I can take BASIC's stuff off the stack, and whittle it down to where it was before the BRK. At this point, I'm relying on the notion that the aforementioned return addresses are already on the stack, a bit further down*, so that a program continued from breakpoints can eventually exit gracefully.
* My mental model of the 6502 stack is backwards. Further up is arguably more accurate.