Monday, October 14, 2024

ALPP 01-13 -- Hello, Bugs! Debugging Example, 6800 and 6809

Hello, Bugs!
Debugging Example
6800 and 6809

(Title Page/Index)

 

We've got simple text output using the monitor ROM routines under EXORsim, with the 6800, 6801, and 6809. And we have the same on the 68000, using the Atari BIOS under Hatari.

I've talked a little about debugging, and we used some debugging techniques getting EXORsim6801 to offer us something stable to look at.

But I need to make sure I give you a chance to figure out how to deal with problems, because assembler level code tends to be very sensitive to programmer error.

I may have gone over the top on this one. If so, forgive me.

Our theoretical target for this debugging exercise is to get all of the following strings of characters to display on the terminal: 

  • "To the beach!"
  • "Hello Bugs Bunny!" 
  • "I am a muggle."
  • "Are we there yet?"

Now let's try that on the 6800. 

(The same code can be used on the 6801, but you'll need to add the kickstarter code.)

Here's some code with a couple of common bugs:

XPDAT1	EQU	$F027	; string output, terminated by EOT
EOT	EQU	$04	; $04 is decimal 4
LF	EQU	$0A	; line feed
CR	EQU	$0D	; carriage return
*
NATWID	EQU	2	; 2 bytes in the CPU's natural integer
*
ENTRY	JMP	START
* (EXORsim apparently doesn't want to calculate RMB arguments.)
*	RMB	16*NATWID-1
	RMB	31	; 16 levels of call minus any saved registers, max
STKBAS	RMB	1	; 6800 is post-dec (post-store-decrement) push
SAVES	RMB	2	; a place to keep S so we can be clean
STR1	FCB	CR,LF	; Put message at beginning of line
	FCB	"To the beach!"	; Whatever the user wants here.
	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
STR1	FCB	CR,LF	; Put message at beginning of line
	FCB	"Hello Bugs Bunny!"	; Whatever the user wants here.
	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
STR1	FCB	CR,LF	; Put message at beginning of line
	FCB	"I am a muggle."	; Whatever the user wants here.
	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
STR1	FCB	CR,LF	; Put message at beginning of line
	FCB	"Are we there yet?"	; Whatever the user wants here.
	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
*
START	STS	SAVES	; Save what the monitor gives us.
	LDS	#STKBAS	; Move to our own stack
	LDX	#STR1	; point to the string
	JSR	XPDAT1	; output it
	LDX	#STR1	; point to the string
	JSR	XPDAT1	; output it
	LDX	#STR1	; point to the string
	JSR	XPDAT1	; output it
	LDX	#STR1	; point to the string
	JSR	XPDAT1	; output it
DONE	LDS	SAVES	; restore the stack pointer
	NOP
	NOP		; landing pad
"
"" 
""
""

Don't bother looking for the bugs yet, just copy and paste it into the assemble command of a running EXORsim 6800 session and watch the output:

(Assemble at $2000.)

$ ./exor --mon
Load facts file 'facts'
'exbug.bin' loaded.
  EXBUG-1.1 detected
'mdos.dsk' opened for drive 0 (double sided)

OSLOAD...

Hit Ctrl-C for simulator command line.  Starting simulation...

>         0 A=00 B=00 X=0000 SP=00FF ------          0020: B6 E8 00 LDA E800                 

6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% a 2000
2000: XPDAT1	EQU	$F027	; string output, terminated by EOT
2000: EOT	EQU	$04	; $04 is decimal 4
2000: LF	EQU	$0A	; line feed
2000: CR	EQU	$0D	; carriage return
2000: *
2000: NATWID	EQU	2	; 2 bytes in the CPU's natural integer
2000: *
2000: ENTRY	JMP	START
2003: * (EXORsim apparently doesn't want to calculate RMB arguments.)
2003: *	RMB	16*NATWID-1
2003: 	RMB	31	; 16 levels of call minus any saved registers, max
2022: STKBAS	RMB	1	; 6800 is post-dec (post-store-decrement) push
2023: SAVES	RMB	2	; a place to keep S so we can be clean
2025: STR1	FCB	CR,LF	; Put message at beginning of line
2027: 	FCB	"To the beach!"	; Whatever the user wants here.
2034: 	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
2037: STR1	FCB	CR,LF	; Put message at beginning of line
Symbol 'STR1' already defined to 2025
2039: 	FCB	"Hello Bugs Bunny!"	; Whatever the user wants here.
204a: 	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
204d: STR1	FCB	CR,LF	; Put message at beginning of line
Symbol 'STR1' already defined to 2025
204f: 	FCB	"I am a muggle."	; Whatever the user wants here.
205d: 	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
2060: STR1	FCB	CR,LF	; Put message at beginning of line
Symbol 'STR1' already defined to 2025
2062: 	FCB	"Are we there yet?"	; Whatever the user wants here.
2073: 	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
2076: *
2076: START	STS	SAVES	; Save what the monitor gives us.
Address at 2001 set to 2076
2079: 	LDS	#STKBAS	; Move to our own stack
207c: 	LDX	#STR1	; point to the string
207f: 	JSR	XPDAT1	; output it
2082: 	LDX	#STR1	; point to the string
2085: 	JSR	XPDAT1	; output it
2088: 	LDX	#STR1	; point to the string
208b: 	JSR	XPDAT1	; output it
208e: 	LDX	#STR1	; point to the string
2091: 	JSR	XPDAT1	; output it
2094: DONE	LDS	SAVES	; restore the stack pointer
2097: 	NOP
2098: 	NOP		; landing pad
2099: "
2099: "" 
2099: ""
Symbol '""' already defined to 2099
2099: ""
Symbol '""' already defined to 2099
2099: 
% 

Woops.

Symbol '""' already defined to 2099

The interactive assembler is telling us we have trash at the end, left over from my copying and pasting the strings in. Those could cause problems, but won't in this case..

(If you've already found the real bugs, bear with us.)

(u)nassemble from $2000:

% u 2000
2000: 7E 20 76            JMP $2076
2003: 00                  ???
...

 (Lots of question marks after that.) 

Then from $2076:

% u 2076
2076: BF 20 23            STS $2023
2079: 8E 20 22            LDS #$2022
207C: CE 20 25            LDX #$2025
207F: BD F0 27            JSR $F027 [PDATA1 Print string]
2082: CE 20 25            LDX #$2025
2085: BD F0 27            JSR $F027 [PDATA1 Print string]
2088: CE 20 25            LDX #$2025
208B: BD F0 27            JSR $F027 [PDATA1 Print string]
208E: CE 20 25            LDX #$2025
2091: BD F0 27            JSR $F027 [PDATA1 Print string]
2094: BE 20 23            LDS $2023
2097: 01                  NOP
2098: 01                  NOP
2099: 00                  ???
...

 Set a breakpoint at $2097 and just (c)ontinue from $2000:

% b 2097
Breakpoint set at 2097
% c 2000


Breakpoint!

To the beach!

To the beach!

To the beach!

To the beach!
       1211 A=04 B=00 X=2036 SP=2022 ---Z-- DONE     2094: BE 20 23 LDS 2023  EA=2023(SAVES) D=00FF 
>      1212 A=04 B=00 X=2036 SP=00FF ------          2097: 01       NOP                      

6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% 

Yeah, yeah, you had already seen that and you were expecting it. In fact, you were raising your hand to say,

Hey, there's other already defined label messages up there!

And you're right. Starting at address $2037, it says STR1 is already defined to $2025.

So, let's go in where you have that in your text editor ...

What, you just copied from here into EXORsim? Silly you. 

Silly me for not warning you you'd need to paste it into a text editor so you could fix it. 8-* 

(And if you're ahead of me on that, good for you.)

... and fix the 2nd through 4th STRs to STR2, STR3, and STR4.

Will that fix it?

You're saying, of course not. We have to load the addresses of the latter three STRNs into X in their turn, or it just repeats the same output.

Okay, go fix the LDX lines, too. And clear out those trailing quotation marks, while you're at it.

Go ahead, paste it in and get it running.

You need to go ahead and play with EXORsim and Hatari like this a bit, to get used to the noise it makes and figuring out what it means and when it's useful.

I'm going to skip the 6801. Trying to run 6801 code on the 6800 would be more interesting, but let's not do that, either. Not yet.

Let's try a little more subtle puzzle on the 6809. 

Remember to start the session with 

$ ./exor09 --mon

And (a)ssemble it at $2000. 

Here's some code:

* 6809 very special version
XPDAT1	EQU	$F026	; string output, terminated by EOT
EOT	EQU	$00	; $04 is decimal 4
LF	EQU	$0A	; line feed
CR	EQU	$0D	; carriage return
*
NATWID	EQU	2	; 2 bytes in the CPU's natural integer
*
ENTRY	BRA	START	; Close enough for the short branch.
	RMB	32	; 16 levels of call minus any saved registers, max
SAVES	RMB	2	; a place to keep S so we can return cleanly
STKBAS	EQU	SAVES 	; 6809 is pre-dec (pre-store-decrement) push

STR1	FCB	CR,LF	; Put message at beginning of line
	FCB	"To the beach!"	; Whatever the user wants here.
	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
STR2	FCB	CR,LF	; Put message at beginning of line
	FCB	"Hello Bugs Bunny!"	; Whatever the user wants here.
	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
STR3	FCB	CR,LF	; Put message at beginning of line
	FCB	"I am a muggle."	; Whatever the user wants here.
	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
STR4	FCB	CR,LF	; Put message at beginning of line
	FCB	"Are we there yet?"	; Whatever the user wants here.
	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
*
START	STS	SAVES,PCR	; Save what the monitor gives us.
	LEAS	STKBAS,PCR	; Move to our own stack
	LEAX	HELLO,PCR	; point to the string
	BSR	XPDAT1		; output it
	LEAS	STKBAS,PCR	; Move to our own stack
	LEAX	HELLO,PCR	; point to the string
	BSR	XPDAT2		; output it
	LEAS	STKBAS,PCR	; Move to our own stack
	LEAX	HELLO,PCR	; point to the string
	BSR	XPDAT3		; output it
	LEAS	STKBAS,PCR	; Move to our own stack
	LEAX	HELLO,PCR	; point to the string
	BSR	XPDAT4		; output it
DONE	LDS	SAVES,PCR	; restore the stack pointer
	NOP
	NOP		; landing pad

Again, you might see the bugs already. Let's see what they do.

$ ./exor09 --mon
Load facts file 'facts09'
'exbug09.bin' loaded.
  EXBUG09-2.1 detected
'mdos09.dsk' opened for drive 0 (double sided)

OSLOAD...

Hit Ctrl-C for simulator command line.  Starting simulation...

>         0 A=00 B=00 X=0000 Y=0000 U=0000 S=00FF P=00 --------            0020: 86 10        LDA #$10                   

6809 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% a 2000
2000: * 6809 very special version
2000: XPDAT1	EQU	$F026	; string output, terminated by EOT
2000: EOT	EQU	$00	; $04 is decimal 4
2000: LF	EQU	$0A	; line feed
2000: CR	EQU	$0D	; carriage return
2000: *
2000: NATWID	EQU	2	; 2 bytes in the CPU's natural integer
2000: *
2000: ENTRY	BRA	START	; Close enough for the short branch.
later = 2001
2002: 	RMB	32	; 16 levels of call minus any saved registers, max
2022: SAVES	RMB	2	; a place to keep S so we can return cleanly
2024: STKBAS	EQU	SAVES 	; 6809 is pre-dec (pre-store-decrement) push
2024: 
% STR1	FCB	CR,LF	; Put message at beginning of line
Huh?
% 	FCB	"To the beach!"	; Whatever the user wants here.
Huh?
% 	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
Huh?
...

What is that 

Huh?

thing? It starts after STKBAS is declared. If we look back up there, all we see is a blank line.

Ah. Oh, yeah. The interactive assembler thinks a blank line is meant to terminate the (a)ssemble command, and then it tries to interpret STR1 as a command and tells us it doesn't understand. 

(Cheeky assembler. ;-)

Okay, so let's put an asterisk in on that line so it's a comment and doesn't terminate the assembly job. And paste it in, (u)nassemble it from $2000 and then $2077 to see how it looks, set a (b)reakpoint at $20A1 where the NOP landing pad is, and (c)ontinue at $2000:

$ ./exor09 --mon
Load facts file 'facts09'
'exbug09.bin' loaded.
  EXBUG09-2.1 detected
'mdos09.dsk' opened for drive 0 (double sided)

OSLOAD...

Hit Ctrl-C for simulator command line.  Starting simulation...

>         0 A=00 B=00 X=0000 Y=0000 U=0000 S=00FF P=00 --------            0020: 86 10        LDA #$10                   

6809 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% a 2000
2000: * 6809 very special version
2000: XPDAT1	EQU	$F026	; string output, terminated by EOT
2000: EOT	EQU	$00	; $04 is decimal 4
2000: LF	EQU	$0A	; line feed
2000: CR	EQU	$0D	; carriage return
2000: *
2000: NATWID	EQU	2	; 2 bytes in the CPU's natural integer
2000: *
2000: ENTRY	BRA	START	; Close enough for the short branch.
later = 2001
2002: 	RMB	32	; 16 levels of call minus any saved registers, max
2022: SAVES	RMB	2	; a place to keep S so we can return cleanly
2024: STKBAS	EQU	SAVES 	; 6809 is pre-dec (pre-store-decrement) push
2024: *
2024: STR1	FCB	CR,LF	; Put message at beginning of line
2026: 	FCB	"To the beach!"	; Whatever the user wants here.
2033: 	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
2036: STR2	FCB	CR,LF	; Put message at beginning of line
2038: 	FCB	"Hello Bugs Bunny!"	; Whatever the user wants here.
2049: 	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
204c: STR3	FCB	CR,LF	; Put message at beginning of line
204e: 	FCB	"I am a muggle."	; Whatever the user wants here.
205c: 	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
205f: STR4	FCB	CR,LF	; Put message at beginning of line
2061: 	FCB	"Are we there yet?"	; Whatever the user wants here.
2072: 	FCB	CR,LF,EOT	; Put the debugger's output on a new line.
2075: *
2075: 	NEG	$00
2077: START	STS	SAVES,PCR	; Save what the monitor gives us.
Offset at 2001 set to 75
207b: 	LEAS	STKBAS,PCR	; Move to our own stack
207e: 	LEAX	HELLO,PCR	; point to the string
later = 2080
2082: 	BSR	XPDAT1		; output it
Error: Offset for 2083 out of range.  It was 53154 but must be -128 to 127
2082: 	LEAS	STKBAS,PCR	; Move to our own stack
2085: 	LEAX	HELLO,PCR	; point to the string
later = 2087
2089: 	BSR	XPDAT2		; output it
later = 208a
208b: 	LEAS	STKBAS,PCR	; Move to our own stack
208e: 	LEAX	HELLO,PCR	; point to the string
later = 2090
2092: 	BSR	XPDAT3		; output it
later = 2093
2094: 	LEAS	STKBAS,PCR	; Move to our own stack
2097: 	LEAX	HELLO,PCR	; point to the string
later = 2099
209b: 	BSR	XPDAT4		; output it
later = 209c
209d: DONE	LDS	SAVES,PCR	; restore the stack pointer
20a1: 	NOP
20a2: 	NOP		; landing pad
20a3: 
% u 2000
2000: 20 75               BRA $2077
2002: 00 00               NEG $00
...
% u 2077
2077: 10EF 8C A7           STS $2022,PCR
207B: 32 8C A4            LEAS $2022,PCR
207E: 30 8D 0000           LEAX $2082,PCR
2082: 32 8C 9D            LEAS $2022,PCR
2085: 30 8D 0000           LEAX $2089,PCR
2089: 8D 00               BSR $208b
208B: 32 8C 94            LEAS $2022,PCR
208E: 30 8D 0000           LEAX $2092,PCR
2092: 8D 00               BSR $2094
2094: 32 8C 8B            LEAS $2022,PCR
2097: 30 8D 0000           LEAX $209b,PCR
209B: 8D 00               BSR $209d
209D: 10EE 8C 81           LDS $2022,PCR
20A1: 12                  NOP 
20A2: 12                  NOP 
20A3: 00 00               NEG $00
...
% b 20a1
Breakpoint set at 20A1
% c 2000


Breakpoint!
         13 A=00 B=00 X=209B Y=0000 U=0000 S=2020 P=00 -------- DONE       209D: 10EE 8C 81   LDS $2022,PCR EA=2022(STKBAS) D=00FF 
>        14 A=00 B=00 X=209B Y=0000 U=0000 S=00FF P=00 --------            20A1: 12           NOP                        

6809 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% 

Erk. 

Nothing.

Why?

Look back at the output as it assembles, and you should see an error message. Offset out of range for branching to subroutine to XPDAT1.

Well, yeah. XPDAT1. It's way up there at 53154, which needs a long branch. 

But XPDAT2 and XPDAT3 don't seem to cause problems?

(u)nassemble again from $2077.

% u 2077
2077: 10EF 8C A7           STS $2022,PCR
207B: 32 8C A4            LEAS $2022,PCR
207E: 30 8D 0000           LEAX $2082,PCR
2082: 32 8C 9D            LEAS $2022,PCR
2085: 30 8D 0000           LEAX $2089,PCR
2089: 8D 00               BSR $208b
208B: 32 8C 94            LEAS $2022,PCR
208E: 30 8D 0000           LEAX $2092,PCR
2092: 8D 00               BSR $2094
2094: 32 8C 8B            LEAS $2022,PCR
2097: 30 8D 0000           LEAX $209b,PCR
209B: 8D 00               BSR $209d
209D: 10EE 8C 81           LDS $2022,PCR
20A1: 12                  NOP 
20A2: 12                  NOP 
20A3: 00 00               NEG $00

Well, the branch offsets seem to be set to 00. And HELLO? The offsets to HELLO are ...

HELLO?

There's no HELLO in there any more. Not supposed to be.

Ah! Not defined. What did I do?

Gack. Somehow I seem to have thought I was pasting in STR1, STR2, etc. and I was changing the XPDAT1 output string target to XPDAT2 and ..., which is why those are undefined. There is no XPDAT2, etc. Okay, so get those labels fixed, and don't forget the long branches:

START	STS	SAVES,PCR	; Save what the monitor gives us.
	LEAS	STKBAS,PCR	; Move to our own stack
	LEAX	STR1,PCR	; point to the string
	LBSR	XPDAT1		; output it
	LEAS	STKBAS,PCR	; Move to our own stack
	LEAX	STR2,PCR	; point to the string
	LBSR	XPDAT1		; output it
	LEAS	STKBAS,PCR	; Move to our own stack
	LEAX	STR3,PCR	; point to the string
	LBSR	XPDAT1		; output it
	LEAS	STKBAS,PCR	; Move to our own stack
	LEAX	STR4,PCR	; point to the string
	LBSR	XPDAT1		; output it

Okay, paste the whole thing (not just the fixed part) into a fresh EXORsim 6809 session and (u)nassemble from $2077 again, and the offsets look reasonable now. And no error messages. (c)ontinue it from $2000.

Well, that's interesting. Looks like it's looping or something. I'm going to have to break out with a Ctrl-C.

% c 2000


To the beach!

Hello Bugs Bunny!

I am a muggle.

Are we there yet?
2020202~ODjF K3 4
Hello Bugs Bunny!

I am a muggle.

Are we there yet?
2020202~ODjF K3 4
I am a muggle.

Are we there yet?
2020202~ODjF K3 4
Are we there yet?
2020202~Interrupt!
    5152051 A=00 B=00 X=3D53 Y=0000 U=0000 S=2019 P=00 -----Z-C            F1D9: F6 FCF4      LDB $fcf4   EA=FCF4(ACIA0) D=02 
>   5152052 A=00 B=02 X=3D53 Y=0000 U=0000 S=2019 P=00 -------C            F1DC: C5 02        BITB #$02                  

6809 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% 

Let's try single stepping. Fresh session, freshly assembled, (s)tep from$2000.

% s 2000

          0 A=00 B=00 X=0000 Y=0000 U=0000 S=00FF P=00 -------- ENTRY      2000: 20 75        BRA $2077                  
>         1 A=00 B=00 X=0000 Y=0000 U=0000 S=00FF P=00 -------- START      2077: 10EF 8C A7   STS $2022,PCR                

6809 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s

          1 A=00 B=00 X=0000 Y=0000 U=0000 S=00FF P=00 -------- START      2077: 10EF 8C A7   STS $2022,PCR EA=2022(STKBAS) D=00FF 
>         2 A=00 B=00 X=0000 Y=0000 U=0000 S=00FF P=00 --------            207B: 32 8C A4     LEAS $2022,PCR                

6809 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s

          2 A=00 B=00 X=0000 Y=0000 U=0000 S=00FF P=00 --------            207B: 32 8C A4     LEAS $2022,PCR                
>         3 A=00 B=00 X=0000 Y=0000 U=0000 S=2022 P=00 --------            207E: 30 8C A3     LEAX $2024,PCR                

6809 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
% s

          3 A=00 B=00 X=0000 Y=0000 U=0000 S=2022 P=00 --------            207E: 30 8C A3     LEAX $2024,PCR                
>         4 A=00 B=00 X=2024 Y=0000 U=0000 S=2022 P=00 --------            2081: 17 CFA2      LBSR $f026                 

6809 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
%     

Long branch to subroutine to $F026. Hmm. Just in case, let's go look at the 6809 code we've used before.

$F027!!!

How'd I do that?

(Really, these kinds of things do happen. I promise.)

Okay, fix that line. Very first line. Well, first line of non-comment code:

XPDAT1	EQU	$F027	; string output, terminated by EOT

Fresh session, freshly assembled, run it and, ... it's doing the same thing? Leave it.Maybe it will stop by itself.

Output four times, with a long pause between each. And trash after. Hmm.

Look back up at that first line of code. Idly look at the second line of code.

* 6809 very special version
XPDAT1	EQU	$F027	; string output, terminated by EOT
EOT	EQU	$00	; $04 is decimal 4
LF	EQU	$0A	; line feed
CR	EQU	$0D	; carriage return

EOT EQUated to $00?

O O
<
()

The comment is right. How'd that happen?

:-/

Well, yeah, this kind of thing happens, too. 

Go ahead and fix it and assemble and run it. This time it should behave itself.

Do you want to do a debug session like this with Hatari? Hmm. Gotta think about that.

Until I figure that out, you can go ahead and walk through the examples using the single character output functions to write your own string output functions.


(Title Page/Index)

 

No comments:

Post a Comment