6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Wed May 08, 2024 11:14 pm

All times are UTC




Post new topic Reply to topic  [ 28 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Sat Nov 27, 2021 8:11 pm 
Offline

Joined: Sat Aug 14, 2021 6:04 pm
Posts: 10
I'm using cc65 and the included ca65 assembler. I'm having a hard time debugging code I've written and am surprised by the lack of tools; I feel like I must be missing something obvious. I'm wondering how other people deal with this.

Some background. I'm writing code for my own 6502 board, and it's actually a 65C02, so my code has some 65C02-specific instructions here and there. I've written unit tests that I run with the sim65 emulator that's part of the cc65 package. But sometimes (usually?) the tests just crash the simulator when they don't work, and it's hard for me to figure out what's going on.

I tried using VICE, but apparently it doesn't support the 65C02. In general, tools that are intended for C64 and Atari development tend to have this problem.

I'm kind of wondering why sim65 doesn't support debugging. It is obviously emulating the CPU and the cc65 package includes a disassembler, so seems like it would be straightforward to put the pieces together.

If you have a solution that works for you, please let me know.


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 27, 2021 8:30 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10800
Location: England
It's not good if sim65 crashes - or does that just mean that your program has gone into the weeds and the sim65 is continuing to operate, but not usefully to you?

If you can get the simulator to report a trace of the program counter, or the instruction-by-instruction machine state, that can be very helpful. Even for moderately long-running programs, an editor can cope with a very large log file these days.

Adding instrumentation to your code can help: did it reach this point? this point? this point? That could be a case of adding a BRK. Expect to run the code over and over, learning a little each time.

Perhaps you can load up a suitable monitor into the emulated environment - one which can single step.

In the end, if you're relatively new to 6502 land, you will be simulating in your head or on paper, figuring out the register changes as you go round a loop.


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 27, 2021 10:17 pm 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1405
Location: Scotland
WillisBlackburn wrote:
I'm using cc65 and the included ca65 assembler. I'm having a hard time debugging code I've written and am surprised by the lack of tools; I feel like I must be missing something obvious. I'm wondering how other people deal with this.


My "solution" may not be helpful, however with a lot of 6502 experience behind me, but not having done much for about 35 years I started from scratch with some trivial programs in assembler very bare-bones (which is what I did "back then" in 1980 or so). Write a loop, check with a 'scope, then get an LED blinking and take it from there. I was bringing up new hardware at the same time, so doubly challenging.

Once I knew I could light an LED I could implement print character, then string, then numbers and so on. Today, printf is my debugger but while my RubyOS can dump memory (and disassemble). It's not a "monitor" as such though.

Not helpful if starting the debugger is your normal way of working though - it's a very different world.

I did use the symon emulator very briefly though but it's memory map wasn't what I was after in my target.

but once I could run some simple asm programs (I used ca65 to assemble them) I moved on to writing my own monitor, then OS, then I created a cc65 target for my system. That was relatively easy, but that was also after I had a good enough operating system to run EhBASIC and BBC Basic.

Good luck with the route you take, but I'd strongly suggest starting with blinking an LED.

Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 27, 2021 10:39 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8432
Location: Southern California
Quote:
How do you debug your 6502/65C02 code?

http://wilsonminesco.com/6502primer/debug.html
(Do go through the whole 6502 primer though. It's in 22 logically organized pages, and was written to answer questions and problems that kept coming up on the forum. The primer is continually getting updated.) I should probably add a couple of paragraphs, with diagrams, about using as little as a single VIA pin to output status in serial which you can watch on the oscilloscope, as I mentioned at viewtopic.php?p=88499#p88499 .

_________________
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 Nov 27, 2021 10:44 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1928
Location: Sacramento, CA, USA
BigEd wrote:
Adding instrumentation to your code can help: did it reach this point? this point? this point? That could be a case of adding a BRK. Expect to run the code over and over, learning a little each time.

That's how I got my VTL02 interpreter working (at ~1KB of dense machine code, my largest hobby software project to date). Most problems seemed to boil down to off-by-ones and errant INYs and DEYs, which updated the text offset pointer. The interpreter itself was of no help, since the concept of an error is completely foreign to it, a situation that I may rectify when I eventually get a VTLC02 version completed and integrated with my still-unfinished HEGEMON 65c02 debugger/monitor/mini-assembler/disassembler, all in a ROMable ~2.5KB package.

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Last edited by barrym95838 on Mon Nov 29, 2021 1:25 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 28, 2021 12:03 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
The fastest way for me is not from the assembler, but from the ML code listing itself. I change each JSR to a JMP, and then call each subroutine separately until I find the culprit causing the crash. Usually can find the routine that causes the crash within a half dozen tries. After that I quickly scan the code to make sure the branches are not branching to the middle of another instruction, which is usually the case, or if something is pushed on the stack to make sure it gets pulled off.

Very rarely do programs crash due to some erroneous value in one of the registers. But I do have a "BETTER.BRK" (better break) that shows all the values of all the registers,including the processor register, wherever the BRK instruction is inserted. I rarely use it though as it becomes more time consuming to figure out where to insert the BRK. The first method works way faster for me.


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 28, 2021 12:13 am 
Offline

Joined: Wed Jan 08, 2014 3:31 pm
Posts: 575
I break code into modules, write a test harnesses to run it under Py65mon. The test harness uses print statements to indicate pass or fail of each test. After I am fairly certain it works I will run it on real hardware.


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 28, 2021 8:21 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10800
Location: England
Oh, py65mon - good thought! It's very like the kind of machine monitor you'd run on the machine, and of course you can tweak it if you need to.
https://github.com/mnaberez/py65#monitor
https://py65.readthedocs.io/en/latest/


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 28, 2021 5:05 pm 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1373
Whenever I have a coding problem, I first try to isolate anything I've done which might be wrong, then examine in a larger context of how the failure is happening. My Monitor code has the ability to call a routine and also load the registers with user data before calling the routine. It then captures the register data on return and I can display it.

In other cases, I'll use a BRK instruction at certain code points. My Monitor also captures the BRK instruction, so I can get register data and also use a BRK signature byte if I'm using more than a single BRK in the code. This certainly helps... but debugging can be tricky, depending on what's going on.

Having a mix of routines that interact with an interrupt service routine can also be tricky to debug, especially if there are multiple paths and routines in the ISR. In some worse case scenarios, it might require using a logic analyzer to get a better view what the hardware is actually doing, versus what you think it should be doing based on the code you're running.

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 28, 2021 10:50 pm 
Offline
User avatar

Joined: Fri Aug 03, 2018 8:52 am
Posts: 746
Location: Germany
to be honest i just do the same thing i do in any programming language, use print statements to see if the code reaches a certain point and print out any variable i might be able to check.

like if i know that after function xyz the variable "num" is supposed to be equal to something specific like "204" for example i can just have the system print it out so i can manually check it after running it.
so far it worked pretty well but it's obviously not ideal compared to an NMI-Button powered Memory Monitor or similar debugging tool.


Top
 Profile  
Reply with quote  
PostPosted: Mon Nov 29, 2021 1:35 pm 
Offline

Joined: Thu Apr 23, 2020 5:04 pm
Posts: 45
WillisBlackburn wrote:
I'm using cc65 and the included ca65 assembler. I'm having a hard time debugging code I've written and am surprised by the lack of tools; I feel like I must be missing something obvious. I'm wondering how other people deal with this.

Some background. I'm writing code for my own 6502 board, and it's actually a 65C02, so my code has some 65C02-specific instructions here and there. I've written unit tests that I run with the sim65 emulator that's part of the cc65 package. But sometimes (usually?) the tests just crash the simulator when they don't work, and it's hard for me to figure out what's going on.

I tried using VICE, but apparently it doesn't support the 65C02. In general, tools that are intended for C64 and Atari development tend to have this problem.

I'm kind of wondering why sim65 doesn't support debugging. It is obviously emulating the CPU and the cc65 package includes a disassembler, so seems like it would be straightforward to put the pieces together.

If you have a solution that works for you, please let me know.

For development of vbcc (debugging and automated tests), I use a modified version of an emulator written by Frank Wille a long time ago. It is written in portable C and provides the option to write plugins for GUIs and peripherals. I added a simple text-based user-interface (the original contained a GUI for the Amiga) with debug-features like single-step, go-to-next, go-to-address, disassemble or set-breakpoint.

Originally, it only supported the 6502, but I added some support for 65c02 (at least those instructions generated by vbcc).

There is not much documentation and I think Frank probably never released this tool, but if there is some demand I can ask him about that.


Top
 Profile  
Reply with quote  
PostPosted: Mon Nov 29, 2021 1:55 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 690
Location: North Tejas
I do my debugging in my own homegrown simulator/debugger. It is patterned after DEBUG or SYMDEB and supports stepping and breakpoints.

It counts the clock cycles used by instructions so I use it to compare snippets of code for efficiency. It also has what I call a "clock breakpoint" so that if code runs away, I can have the debugger stop after N cycles. Not as useful in general as instruction trace logging, but it does not take added time or storage.

Potential enhancements in the future may include memory read or write breakpoints, symbolic debugging or some kind of GUI/CUI interface.


Top
 Profile  
Reply with quote  
PostPosted: Mon Nov 29, 2021 8:20 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8177
Location: Midwestern USA
I do it the old-fashioned way: with a machine language monitor, breaks in the code at the areas where there is, or might be trouble, and a good understanding of what the program is supposed to do.

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


Last edited by BigDumbDinosaur on Tue Nov 30, 2021 8:09 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Mon Nov 29, 2021 9:51 pm 
Offline

Joined: Thu Oct 05, 2017 2:04 am
Posts: 62
One option could be to add some printf's to both my emulator code and yours to output an opcode sequence number, the PC and opcode, and the state of the registers. Both of our emulators should execute addresses and opcodes in lockstep so you could use the traces to see where our emulators begin to diverge.

https://github.com/MicroCoreLabs/Projects/blob/master/MCL65%2B/SourceCode/Generic_6502/MCL65.ino

I was recently considering posting the command-line version of my code which replaces the 6502 bus interface with a generic ram_array for the RAM/ROM, along with the version of Klaus's opcode tests. This is the method I used to develop my emulator where subtle differences caused a divergence which allowed me to quickly focus on the error.


Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 30, 2021 12:19 am 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
Everyone has posted good options for debugging, and I'll add what I use. My emulator works in JavaScript so you can run it in your browser. Here's an example on my website. If you click on "System Information" you can see all the registers and single step the processor. It shows several panes of memory and highlights the instruction executed and any memory accessed which has come in really handy. It can load a listing from CA65 and highlight each line of source when you single step. You can also see the entire memory contents and log all registers on each cycle. It supports bank switching and has 32k of RAM mapped one byte per pixel to a 128x64 screen. I've been able to get EhBASIC and TaliForth 2 running on it.

You can download the source from github and run it locally. I have a line in my script that copies the binary and listing to the emulator folder every time I run CA65. I'm happy to help if you want to get it running.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 28 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 15 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: