Hello, Bugs!
Debugging Example
6800 and 6809
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 might be interested in things to consider if you want to use this tutorial as a guide to studying other processors.
Or you can go ahead and walk through my examples using single character output functions to write your own character and string output functions.
No comments:
Post a Comment