Stack Watching in VICE

You need an actual VIC.

Moderator: Moderators

groepaz
Vic 20 Scientist
Posts: 1188
Joined: Wed Aug 25, 2010 5:30 pm

Re: Stack Watching in VICE

Post by groepaz »

rhialto made a quick patch

http://www.falu.nl/~rhialto/watchpoints1.diff.txt

eg

break load 0 $ffff if @cpu:(pc) < $80
I'm just a Software Guy who has no Idea how the Hardware works. Don't listen to me.
User avatar
chysn
Vic 20 Scientist
Posts: 1205
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

Post by chysn »

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
Ooh, cool!

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:
Screen Shot 2023-10-06 at 9.25.37 PM.png
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:
Screen Shot 2023-10-06 at 9.37.55 PM.png
and HES Mon allows you to continue, but blows up the stack:
Screen Shot 2023-10-06 at 9.34.31 PM.png
Anyway, that's what I've been doing today, figuring out the stack! Thanks to everyone who helped, I learned a lot today.
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Stack Watching in VICE

Post by Mike »

chysn wrote:[...] which is how a monitor should behave after a breakpoint [...]
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.
I learned a lot today.
You might want to take a look at the thread "Fire-and-forget register saving" on 6502.org for even more serious stack-fu. ;)


*) 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).
User avatar
chysn
Vic 20 Scientist
Posts: 1205
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

Post by chysn »

Mike wrote: Sat Oct 07, 2023 11:06 am
chysn wrote:[...] which is how a monitor should behave after a breakpoint [...]
As you can infer from my edited, earlier post in the thread, MINIMON also manages this feat.
Oh, I had no doubts whatsoever about MINIMON behaving itself!
You might want to take a look at the thread "Fire-and-forget register saving" on 6502.org for even more serious stack-fu. ;)
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.
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.
Perhaps off-topic for this thread, but how does MINIMON handle an RTS during execution, then? What return address gets pulled?
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Stack Watching in VICE

Post by Mike »

chysn wrote:Oh, I had no doubts whatsoever about MINIMON behaving itself!
I just wanted to mention it for completeness. :)
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.
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.
Perhaps off-topic for this thread, but how does MINIMON handle an RTS during execution, then? What return address gets pulled?
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.

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: [...]
:shock: ... I just realized what you actually meant by that: the contents of A and X are lost as can be seen in the final register dump (A=X=$0D instead of A=$55, X=$44). That should not happen indeed.
User avatar
Wilson
Vic 20 Enthusiast
Posts: 190
Joined: Mon Sep 28, 2009 7:19 am
Location: Brooklyn, NY

Re: Stack Watching in VICE

Post by Wilson »

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.
User avatar
chysn
Vic 20 Scientist
Posts: 1205
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

Post by chysn »

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.
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.

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.
Post Reply