Simple Lists on the 6800, 6801, 6809, and 68000
I'm going to keep working with that list of small integers for at least one more, to
make it easier to focus on the topic, in this case, a way to treat a list like a list.
But now that you
know some tools to help you with the binary and hexadecimal math, you can make your own list(s) if you want. It's not a bad idea, I think.
Just keep the total under 128 while we are working on byte math. It'll keep
things more sane.
What we want to do now is treat the list as a single entity.
Let's take another look at the disassembly of the most recent example. We'll start another exorsim session and assemble it
again:
$ ./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 1000
1000: ENTRY JMP START
1003: *
1003: BYTE8 FCB 8
1004: BYTE5 FCB 5
1005: BYTE2 FCB 2
1006: BYTE7 FCB 7
1007: BYTE4 FCB 4
1008: *
1008: START LDAB BYTE8
Address at 1001 set to 1008
100b: ADDB BYTE5
100e: ADDB BYTE2
1011: ADDB BYTE7
1014: ADDB BYTE4
1017: NOP
1018: DONE NOP
1019:
% u 1000
1000: 7E 10 08 JMP $1008
1003: 08 INX
1004: 05 ???
1005: 02 ???
1006: 07 TPA
1007: 04 ???
1008: F6 10 03 LDB $1003
100B: FB 10 04 ADDB $1004
100E: FB 10 05 ADDB $1005
1011: FB 10 06 ADDB $1006
1014: FB 10 07 ADDB $1007
1017: 01 NOP
1018: 01 NOP
1019: 00 ???
101A: 00 ???
If we type help, we'll notice a command called "sy":
% help
help Show this help text
h Show this help text
q Exit simulator
...
clr Clear symbol table
sy Show symbol table
u hhhh Unassemble
...
%
Let's try that:
% sy
1018 DONE
1007 BYTE4
1006 BYTE7
1005 BYTE2
1004 BYTE5
1003 BYTE8
1008 START
1000 ENTRY
%
if we think about it,
- BYTE5 is BYTE8 plus 1.
- BYTE2 is BYTE8 plus 2.
- BYTE7 is BYTE8 plus 3.
- And BYTE4 is BYTE8 plus 4.
So we could write the code like this:
ENTRY JMP START
*
BYTTBL FCB 8
FCB 5
FCB 2
FCB 7
FCB 4
*
START LDAB BYTTBL+0
ADDB BYTTBL+1
ADDB BYTTBL+2
ADDB BYTTBL+3
ADDB BYTTBL+4
NOP
DONE NOP
and the object code would look exactly as in the last example, as long as we start the assembly at $1000 like before ("%a 1000").
Give it a try, with all four CPUs. The 6801 code is exactly the same. The 6809 source code is only different where LDAB becomes LDB. The 68000 code only changes in the declaration of BYTTBL instead of BYTE8, etc., and in the use of BYTTBL+0, etc., instead of BYTE8, etc.
Done that? That was easy, right?
If re-reading the last chapter doesn't solve whatever problems, leave a message below and I'll try to get back to you.
What's next?
We've just looked at one way to use offsets. Let's see if there's another:
ENTRY JMP START
*
BYTTBL FCB 8
FCB 5
FCB 2
FCB 7
FCB 4
*
START LDX #BYTTBL
LDAB 0,X
ADDB 1,X
ADDB 2,X
ADDB 3,X
ADDB 4,X
NOP
DONE NOP
What is this LDX and the ",X" all over the place?
X is what is called an index register. On the 6800 and the 6801, it's the only one. An index register is a place to keep addresses, mostly.
So we LoaD X with the address of BYTTBL. Note the immediate "#". If we used the extended (absolute) mode instead of the immediate mode,
LDX BYTTBL
without the immediate mode hash in there, the assembled code would make the CPU go out to BYTTBL and load the first two bytes in it into X, which would result in $805 being loaded into the index register.
I wonder, what's at address $805?
Anyway, in the next instruction,
LDAB 0,X
the B accumulator will now be loaded from the address which is in X, plus the
constant offset 0. That's what the "0," means.
In the 6800 and 6801, offsets to the index register are always constant.
So, you add the 0 to the address of BYTTBL in X, and that's the address of the first byte, the 8. Add 1 to it in the next instruction, and that's the address of the second byte, the 5. Where does that address go? Once it is used by the indexed mode instruction, it's gone.
Then add 2 to the (unchaged) base of the BYTTBL array to get the address of the third byte, the 2. And so forth. So we're doing the same thing as before, but a different way. We are using X to tell us where the list is, and we are using offsets to the index register X to find each entry.
Some people would say this is actually an array, not a list. It's a reasonable distinction to make, but it isn't always meaningful. More to talk about later, I guess. We'll make it to the beach soon, I promise.
Let's watch the code run:
% a 1000
1000: ENTRY JMP START
1003: *
1003: BYTTBL FCB 8
1004: FCB 5
1005: FCB 2
1006: FCB 7
1007: FCB 4
1008: *
1008: START LDX #BYTTBL
Address at 1001 set to 1008
100b: LDAB 0,X
100d: ADDB 1,X
100f: ADDB 2,X
1011: ADDB 3,X
1013: ADDB 4,X
1015: NOP
1016: DONE NOP
1017:
% u 1000
1000: 7E 10 08 JMP $1008
1003: 08 INX
1004: 05 ???
1005: 02 ???
1006: 07 TPA
1007: 04 ???
1008: CE 10 03 LDX #$1003
100B: E6 00 LDB $00,X
100D: EB 01 ADDB $01,X
100F: EB 02 ADDB $02,X
1011: EB 03 ADDB $03,X
1013: EB 04 ADDB $04,X
1015: 01 NOP
1016: 01 NOP
1017: 00 ???
1018: 00 ???
...
% b 1015
Breakpoint set at 1015
% t on
% c 1000
0 A=00 B=00 X=0000 SP=00FF ------ ENTRY 1000: 7E 10 08 JMP 1008 EA=1008(START)
1 A=00 B=00 X=0000 SP=00FF ------ START 1008: CE 10 03 LDX #$1003 EA=1009 D=1003
2 A=00 B=00 X=1003 SP=00FF ------ 100B: E6 00 LDB 00,X EA=1003(BYTTBL) D=08
3 A=00 B=08 X=1003 SP=00FF ------ 100D: EB 01 ADDB 01,X EA=1004 D=05
4 A=00 B=0D X=1003 SP=00FF ------ 100F: EB 02 ADDB 02,X EA=1005 D=02
5 A=00 B=0F X=1003 SP=00FF ------ 1011: EB 03 ADDB 03,X EA=1006 D=07
6 A=00 B=16 X=1003 SP=00FF H----- 1013: EB 04 ADDB 04,X EA=1007 D=04
Breakpoint!
> 7 A=00 B=1A X=1003 SP=00FF ------ 1015: 01 NOP
6800 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
%
If you look carefully at the right edge of the trace listing, you'll see the effective address (EA) and the data (D) at that address being reported by the debugger. But once the instruction is done with the address and the data, the CPU does not remember either any more. Only the effect remains in the CPU, where the data is being added up in the B accumulator.
Out in memory, of course, the data is still there at the address it was at, waiting in case we decide to look at it again.
Again, when we run this in the 6801, it will do exactly the same thing again.
Go ahead and try it, changing to that directory and running it there. Remember
to use the --6801 option:
$ ./exor --6801 --mon
Load facts file 'facts'
'exbug.bin' loaded.
'mdos.dsk' opened for drive 0 (single sided)
Hit Ctrl-C for simulator command line. Starting simulation...
> 0 A=00 B=00 X=0000 SP=FF8A ------ OSLOAD E800: 8E FF 8A LDS #$FF8A Load OS
Type 'help'
%
% a 1000
1000: ENTRY JMP START
1003: *
1003: BYTTBL FCB 8
1004: FCB 5
1005: FCB 2
1006: FCB 7
1007: FCB 4
1008: *
1008: START LDX #BYTTBL
Address at 1001 set to 1008
100b: LDAB 0,X
100d: ADDB 1,X
100f: ADDB 2,X
1011: ADDB 3,X
1013: ADDB 4,X
1015: NOP
1016: DONE NOP
1017:
% u 1000
1000: 7E 10 08 JMP $1008
1003: 08 INX
1004: 05 LSLD
1005: 02 ???
1006: 07 TPA
1007: 04 LSRD
1008: CE 10 03 LDX #$1003
100B: E6 00 LDB $00,X
100D: EB 01 ADDB $01,X
100F: EB 02 ADDB $02,X
1011: EB 03 ADDB $03,X
1013: EB 04 ADDB $04,X
1015: 01 NOP
1016: 01 NOP
1017: 00 ???
1018: 00 ???
...
% b 1015
Breakpoint set at 1015
% t on
% c 1000
0 A=00 B=00 X=0000 SP=FF8A ------ ENTRY 1000: 7E 10 08 JMP 1008 EA=1008(START)
1 A=00 B=00 X=0000 SP=FF8A ------ START 1008: CE 10 03 LDX #$1003 EA=1009 D=1003
2 A=00 B=00 X=1003 SP=FF8A ------ 100B: E6 00 LDB 00,X EA=1003(BYTTBL) D=08
3 A=00 B=08 X=1003 SP=FF8A ------ 100D: EB 01 ADDB 01,X EA=1004 D=05
4 A=00 B=0D X=1003 SP=FF8A ------ 100F: EB 02 ADDB 02,X EA=1005 D=02
5 A=00 B=0F X=1003 SP=FF8A ------ 1011: EB 03 ADDB 03,X EA=1006 D=07
6 A=00 B=16 X=1003 SP=FF8A H----- 1013: EB 04 ADDB 04,X EA=1007 D=04
Breakpoint!
> 7 A=00 B=1A X=1003 SP=FF8A ------ 1015: 01 NOP
Type 'help'
%
Change back to the directory where you can run exor09 and try it on the 6809. Remember to use LDB instead of LDAB:
$ ./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 1000
1000: ENTRY JMP START
later = 1001
1003: *
1003: BYTTBL FCB 8
1004: FCB 5
1005: FCB 2
1006: FCB 7
1007: FCB 4
1008: *
1008: START LDX #BYTTBL
Address at 1001 set to 1008
100b: LDB 0,X
100d: ADDB 1,X
100f: ADDB 2,X
1011: ADDB 3,X
1013: ADDB 4,X
1015: NOP
1016: DONE NOP
1017:
% u 1000
1000: 7E 1008 JMP $1008
1003: 08 05 ASL $05
1005: 02 07 ??? $07
1007: 04 8E LSR $8e
1009: 1003 E6 COM $e6
100C: 00 EB NEG $eb
100E: 01 EB ??? $eb
1010: 02 EB ??? $eb
1012: 03 EB COM $eb
1014: 04 12 LSR $12
1016: 12 NOP
1017: 00 00 NEG $00
1019: 00 00 NEG $00
...
% u 1008
1008: 8E 1003 LDX #$1003
100B: E6 00 LDB 0,X
100D: EB 01 ADDB 1,X
100F: EB 02 ADDB 2,X
1011: EB 03 ADDB 3,X
1013: EB 04 ADDB 4,X
1015: 12 NOP
1016: 12 NOP
1017: 00 00 NEG $00
1019: 00 00 NEG $00
...
% b 1015
Breakpoint set at 1015
% t on
% c 1000
0 A=00 B=00 X=0000 Y=0000 U=0000 S=00FF P=00 -------- ENTRY 1000: 7E 1008 JMP $1008
1 A=00 B=00 X=0000 Y=0000 U=0000 S=00FF P=00 -------- START 1008: 8E 1003 LDX #$1003
2 A=00 B=00 X=1003 Y=0000 U=0000 S=00FF P=00 -------- 100B: E6 00 LDB 0,X EA=1003(BYTTBL) D=08
3 A=00 B=08 X=1003 Y=0000 U=0000 S=00FF P=00 -------- 100D: EB 01 ADDB 1,X EA=1004 D=05
4 A=00 B=0D X=1003 Y=0000 U=0000 S=00FF P=00 -------- 100F: EB 02 ADDB 2,X EA=1005 D=02
5 A=00 B=0F X=1003 Y=0000 U=0000 S=00FF P=00 -------- 1011: EB 03 ADDB 3,X EA=1006 D=07
6 A=00 B=16 X=1003 Y=0000 U=0000 S=00FF P=00 --H----- 1013: EB 04 ADDB 4,X EA=1007 D=04
Breakpoint!
> 7 A=00 B=1A X=1003 Y=0000 U=0000 S=00FF P=00 -------- 1015: 12 NOP
6809 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
%
And we see that the code does the same thing, there are just more indexable registers to report nothing happening in. And op-codes are a little different.
Hmm. What about PC-relative? Should we try it? How is that going to work? Is there a way to load an immediate address in PC-relative or something? Let's have a look.
There is a Load Effective Address (LEA) instruction for the 6809 that can do
what we want. The assembler will calculate the offset and assemble it, and
when the CPU runs the instruction, it will add the offset to the PC and grab
the effective address before it disappears, loading the calculated addres into
the specified index register:
LEAX BYTTBL,PCR
We'll use this instruction instead of the "LDX #BYTTBL" instruction.
Hit Ctrl-C or type "quit" to end the session, start a new one, and paste the code in:
% a 1000
1000: ENTRY JMP START
later = 1001
1003: *
1003: BYTTBL FCB 8
1004: FCB 5
1005: FCB 2
1006: FCB 7
1007: FCB 4
1008: *
1008: START LEAX BYTTBL,PCR
Address at 1001 set to 1008
100b: LDB 0,X
100d: ADDB 1,X
100f: ADDB 2,X
1011: ADDB 3,X
1013: ADDB 4,X
1015: NOP
1016: DONE NOP
1017:
% u 1000
1000: 7E 1008 JMP $1008
1003: 08 05 ASL $05
1005: 02 07 ??? $07
1007: 04 30 LSR $30
1009: 8C F8E6 CMPX #$f8e6
100C: 00 EB NEG $eb
100E: 01 EB ??? $eb
1010: 02 EB ??? $eb
1012: 03 EB COM $eb
1014: 04 12 LSR $12
1016: 12 NOP
1017: 00 00 NEG $00
1019: 00 00 NEG $00
...
% u 1008
1008: 30 8C F8 LEAX $1003,PCR
100B: E6 00 LDB 0,X
100D: EB 01 ADDB 1,X
100F: EB 02 ADDB 2,X
1011: EB 03 ADDB 3,X
1013: EB 04 ADDB 4,X
1015: 12 NOP
1016: 12 NOP
1017: 00 00 NEG $00
1019: 00 00 NEG $00
...
% b 1015
Breakpoint set at 1015
% t on
% c 1000
0 A=00 B=00 X=0000 Y=0000 U=0000 S=00FF P=00 -------- ENTRY 1000: 7E 1008 JMP $1008
1 A=00 B=00 X=0000 Y=0000 U=0000 S=00FF P=00 -------- START 1008: 30 8C F8 LEAX $1003,PCR
2 A=00 B=00 X=1003 Y=0000 U=0000 S=00FF P=00 -------- 100B: E6 00 LDB 0,X EA=1003(BYTTBL) D=08
3 A=00 B=08 X=1003 Y=0000 U=0000 S=00FF P=00 -------- 100D: EB 01 ADDB 1,X EA=1004 D=05
4 A=00 B=0D X=1003 Y=0000 U=0000 S=00FF P=00 -------- 100F: EB 02 ADDB 2,X EA=1005 D=02
5 A=00 B=0F X=1003 Y=0000 U=0000 S=00FF P=00 -------- 1011: EB 03 ADDB 3,X EA=1006 D=07
6 A=00 B=16 X=1003 Y=0000 U=0000 S=00FF P=00 --H----- 1013: EB 04 ADDB 4,X EA=1007 D=04
Breakpoint!
> 7 A=00 B=1A X=1003 Y=0000 U=0000 S=00FF P=00 -------- 1015: 12 NOP
6809 Monitor: Ctrl-C to exit, 'c' to continue, or type 'help'
%
Now we can begin to see some of the usefulness of index registers.
Let's try this on the 68000. Getting the base address of BYTTBL by absolute
address mode first:
OPT LIST,SYMTAB ; Options we want for the stand-alone assembler.
MACHINE MC68000 ; because there are a lot the assembler can do.
OPT DEBUG ; We want labels for debugging.
OUTPUT
***********************************************************************
EVEN
ENTRY JMP START
*
BYTTBL DC.B 8 ; byte data doesn't have to be aligned.
DC.B 5
DC.B 2
DC.B 7
DC.B 4
*
EVEN ; But 68K code does have to be even aligned.
START MOVE.L #BYTTBL,A0
MOVE.B 0(A0),D1
ADD.B 1(A0),D1
ADD.B 2(A0),D1
ADD.B 3(A0),D1
ADD.B 4(A0),D1
NOP
DONE NOP
* One way to return to the OS or other calling program
clr.w -(sp) ; there should be enough room on the caller's stack
trap #1 ; quick exit
Save that with a new name, maybe sumconx.s , in your working directory under the Hatari C: drive emulation directory. According to the example I've been using, that would be as
~/asmwork/share/hatari/C/primer/sumconx.s
Change to that directory in your host OS shell and assemble it with vasm. Then get a Hatari session running:
$ cd ~/asmwork/share/hatari/C/primer/
$ vasmm68k_mot -Ftos -no-opt -o SUMCONX.PRG -L sumconx.lst sumconx.s
$ hatari
Use Ctrl-Z to drop out of the GUI into the EmuTOS CPM shell, then change to the working directory:
C:\>CD PRIMER
C:\primer>
HIt Alt-PAUSE to break out of the CPM shell into the debugger, and use the mouse to bring up the host OS's parent window where the debugger is running .
Set the debugger to (b)reak on entry to the TEXT segment of the next program loaded; and then (c)ontinue, to return to the CPM shell:
> b pc = TEXT :once
CPU condition breakpoint 1 with 1 condition(s) added:
pc = TEXT
-> Break only once, and delete breakpoint afterwards.
> c
Returning to emulation...
Run the code in the CPM shell:
C:\primer>SUMCONX
Go back to the debugger in the host's parent window and (d)isassemble code to
make sure it's what you think it is:
1. CPU breakpoint condition(s) matched 1 times.
pc = TEXT :once
Removed CPU breakpoint 1:
pc = TEXT :once
Reading symbols from program '/home/nova/usr/share/hatari/C:/primer/SUMCONX.PRG' symbol table...
TOS executable, DRI / GST symbol table, reloc=0, program flags: PRIVATE (0x0)
Program section sizes:
text: 0x2e, data: 0x0, bss: 0x0, symtab: 0x38
Trying to load DRI symbol table at offset 0x4a...
Offsetting BSS/DATA symbols from TEXT section.
Skipping duplicate address & symbol name checks when autoload is enabled.
Loaded 4 symbols (4 TEXT) from '/home/nova/usr/share/hatari/C:/primer/SUMCONX.PRG'.
CPU=$13d10, VBL=2649, FrameCycles=235056, HBL=231, LineCycles=360, DSP=N/A
00013d10 4ef9 0001 3d1c jmp $00013d1c
> d
(PC)
ENTRY:
00013d10 4ef9 0001 3d1c jmp $00013d1c
BYTTBL:
00013d16 0805 0207 btst.l #$0207,d5
00013d1a 0400 207c sub.b #$7c,d0
00013d1e 0001 3d16 or.b #$16,d1
00013d22 1228 0000 move.b (a0,$0000) == $00000000 [60],d1
00013d26 d228 0001 add.b (a0,$0001) == $00000001 [2e],d1
00013d2a d228 0002 add.b (a0,$0002) == $00000002 [02],d1
00013d2e d228 0003 add.b (a0,$0003) == $00000003 [06],d1
00013d32 d228 0004 add.b (a0,$0004) == $00000004 [00],d1
00013d36 4e71 nop
DONE:
00013d38 4e71 nop
00013d3a 4267 clr.w -(a7) [0000]
00013d3c 4e41 trap #$01
00013d3e 0000 0000 or.b #$00,d0
00013d42 0000 0000 or.b #$00,d0
...
>
Check the target of the jump address so you can disassemble the code after the
table where it will make sense, and (d)isassamble again, from the jump target
address:
> d $13d1c
START:
00013d1c 207c 0001 3d16 movea.l #$00013d16,a0
00013d22 1228 0000 move.b (a0,$0000) == $00000000 [60],d1
00013d26 d228 0001 add.b (a0,$0001) == $00000001 [2e],d1
00013d2a d228 0002 add.b (a0,$0002) == $00000002 [02],d1
00013d2e d228 0003 add.b (a0,$0003) == $00000003 [06],d1
00013d32 d228 0004 add.b (a0,$0004) == $00000004 [00],d1
00013d36 4e71 nop
DONE:
00013d38 4e71 nop
00013d3a 4267 clr.w -(a7) [0000]
00013d3c 4e41 trap #$01
00013d3e 0000 0000 or.b #$00,d0
00013d42 0000 0000 or.b #$00,d0
...
>
Check the (r)egisters and (s)tep, repeating until the NOP comes up, and
looking for the sum to accumulate in D1:
> r
D0 00000000 D1 00000000 D2 00000000 D3 00000000
D4 00000000 D5 00000000 D6 00000000 D7 00000000
A0 00000000 A1 00000000 A2 00000000 A3 00000000
A4 00013D3E A5 00013D3E A6 00077FC6 A7 00077FF8
USP 00077FF8 ISP 00007E64
T=00 S=0 M=0 X=0 N=0 Z=0 V=0 C=0 IMASK=3 STP=0
Prefetch 4ef9 (JMP) 0001 (OR) Chip latch 00000000
00013d10 4ef9 0001 3d1c jmp $00013d1c
Next PC: 00013d16
> s
CPU=$13d1c, VBL=2649, FrameCycles=235068, HBL=231, LineCycles=372, DSP=N/A
00013d1c 207c 0001 3d16 movea.l #$00013d16,a0
> r
D0 00000000 D1 00000000 D2 00000000 D3 00000000
D4 00000000 D5 00000000 D6 00000000 D7 00000000
A0 00000000 A1 00000000 A2 00000000 A3 00000000
A4 00013D3E A5 00013D3E A6 00077FC6 A7 00077FF8
USP 00077FF8 ISP 00007E64
T=00 S=0 M=0 X=0 N=0 Z=0 V=0 C=0 IMASK=3 STP=0
Prefetch 207c (MOVEA) 0001 (OR) Chip latch 00000000
00013d1c 207c 0001 3d16 movea.l #$00013d16,a0
Next PC: 00013d22
> s
CPU=$13d22, VBL=2649, FrameCycles=235080, HBL=231, LineCycles=384, DSP=N/A
00013d22 1228 0000 move.b (a0,$0000) == $00013d16 [08],d1
> r
D0 00000000 D1 00000000 D2 00000000 D3 00000000
D4 00000000 D5 00000000 D6 00000000 D7 00000000
A0 00013D16 A1 00000000 A2 00000000 A3 00000000
A4 00013D3E A5 00013D3E A6 00077FC6 A7 00077FF8
USP 00077FF8 ISP 00007E64
T=00 S=0 M=0 X=0 N=0 Z=0 V=0 C=0 IMASK=3 STP=0
Prefetch 1228 (MOVE) 0000 (OR) Chip latch 00000000
00013d22 1228 0000 move.b (a0,$0000) == $00013d16 [08],d1
Next PC: 00013d26
> s
CPU=$13d26, VBL=2649, FrameCycles=235092, HBL=231, LineCycles=396, DSP=N/A
00013d26 d228 0001 add.b (a0,$0001) == $00013d17 [05],d1
> r
D0 00000000 D1 00000008 D2 00000000 D3 00000000
D4 00000000 D5 00000000 D6 00000000 D7 00000000
A0 00013D16 A1 00000000 A2 00000000 A3 00000000
A4 00013D3E A5 00013D3E A6 00077FC6 A7 00077FF8
USP 00077FF8 ISP 00007E64
T=00 S=0 M=0 X=0 N=0 Z=0 V=0 C=0 IMASK=3 STP=0
Prefetch d228 (ADD) 0001 (OR) Chip latch 00000000
00013d26 d228 0001 add.b (a0,$0001) == $00013d17 [05],d1
Next PC: 00013d2a
> s
CPU=$13d2a, VBL=2649, FrameCycles=235104, HBL=231, LineCycles=408, DSP=N/A
00013d2a d228 0002 add.b (a0,$0002) == $00013d18 [02],d1
> r
D0 00000000 D1 0000000D D2 00000000 D3 00000000
D4 00000000 D5 00000000 D6 00000000 D7 00000000
A0 00013D16 A1 00000000 A2 00000000 A3 00000000
A4 00013D3E A5 00013D3E A6 00077FC6 A7 00077FF8
USP 00077FF8 ISP 00007E64
T=00 S=0 M=0 X=0 N=0 Z=0 V=0 C=0 IMASK=3 STP=0
Prefetch d228 (ADD) 0002 (OR) Chip latch 00000000
00013d2a d228 0002 add.b (a0,$0002) == $00013d18 [02],d1
Next PC: 00013d2e
> s
CPU=$13d2e, VBL=2649, FrameCycles=235116, HBL=231, LineCycles=420, DSP=N/A
00013d2e d228 0003 add.b (a0,$0003) == $00013d19 [07],d1
> r
D0 00000000 D1 0000000F D2 00000000 D3 00000000
D4 00000000 D5 00000000 D6 00000000 D7 00000000
A0 00013D16 A1 00000000 A2 00000000 A3 00000000
A4 00013D3E A5 00013D3E A6 00077FC6 A7 00077FF8
USP 00077FF8 ISP 00007E64
T=00 S=0 M=0 X=0 N=0 Z=0 V=0 C=0 IMASK=3 STP=0
Prefetch d228 (ADD) 0003 (OR) Chip latch 00000000
00013d2e d228 0003 add.b (a0,$0003) == $00013d19 [07],d1
Next PC: 00013d32
> s
CPU=$13d32, VBL=2649, FrameCycles=235128, HBL=231, LineCycles=432, DSP=N/A
00013d32 d228 0004 add.b (a0,$0004) == $00013d1a [04],d1
> r
D0 00000000 D1 00000016 D2 00000000 D3 00000000
D4 00000000 D5 00000000 D6 00000000 D7 00000000
A0 00013D16 A1 00000000 A2 00000000 A3 00000000
A4 00013D3E A5 00013D3E A6 00077FC6 A7 00077FF8
USP 00077FF8 ISP 00007E64
T=00 S=0 M=0 X=0 N=0 Z=0 V=0 C=0 IMASK=3 STP=0
Prefetch d228 (ADD) 0004 (OR) Chip latch 00000000
00013d32 d228 0004 add.b (a0,$0004) == $00013d1a [04],d1
Next PC: 00013d36
> s
CPU=$13d36, VBL=2649, FrameCycles=235140, HBL=231, LineCycles=444, DSP=N/A
00013d36 4e71 nop
> r
D0 00000000 D1 0000001A D2 00000000 D3 00000000
D4 00000000 D5 00000000 D6 00000000 D7 00000000
A0 00013D16 A1 00000000 A2 00000000 A3 00000000
A4 00013D3E A5 00013D3E A6 00077FC6 A7 00077FF8
USP 00077FF8 ISP 00007E64
T=00 S=0 M=0 X=0 N=0 Z=0 V=0 C=0 IMASK=3 STP=0
Prefetch 4e71 (NOP) 4e71 (NOP) Chip latch 00000000
00013d36 4e71 nop
Next PC: 00013d38
> s
CPU=$13d38, VBL=2649, FrameCycles=235144, HBL=231, LineCycles=448, DSP=N/A
00013d38 4e71 nop
> r
D0 00000000 D1 0000001A D2 00000000 D3 00000000
D4 00000000 D5 00000000 D6 00000000 D7 00000000
A0 00013D16 A1 00000000 A2 00000000 A3 00000000
A4 00013D3E A5 00013D3E A6 00077FC6 A7 00077FF8
USP 00077FF8 ISP 00007E64
T=00 S=0 M=0 X=0 N=0 Z=0 V=0 C=0 IMASK=3 STP=0
Prefetch 4e71 (NOP) 4267 (CLR) Chip latch 00000000
00013d38 4e71 nop
Next PC: 00013d3a
>
You can see that the address of BYTTBL got loaded into A0, and the bytes in the table got accumulated in D1 as we expected. You'll also notice that A4 to A7 have some sort of values in them that looks like they might be addresses. And you'll notice the USP and the ISP, and you'll wonder what those are. We'll talk about all this stuff later on.
(c)ontinue, to return to the CPM shell:
> c
Returning to emulation...
Program exit, removing its symbols.
The 68000 also has a LEA instruction. Let's try using that in PC-relative
mode. Change the move immediate
START MOVE.L #BYTTBL,A0
at the START label to load effective address, PC relative:
START LEA BYTTBL(PCR),A0
Save the file under a different name, say sumconxpc.s .
Uhm, no. Too many file names with most of the part that's significant to CPM the same, and now we would have two that have all that is significant to CPM the same. I shouldn't be getting you in the habit of doing that. Shame on me. Don't do that, okay? :-/
Sigh. Save it as something different that you'll hopefully remember what it is later -- maybe sumcnxrpc.s . Short file names can get a little crazy.
End the Hatari session and use vasm to assemble the new file:
$ vasmm68k_mot -Ftos -no-opt -o SUMCNXR.PRG -L sumcnxrpc.lst sumcnxrpc.s
Go through the process in the EmuTOS CPM shell and the Hatari debugger to set the TEXT segment to break on program entry, and step through the code watching the registers change, convincing yourself that it works as I advertise it. In particular, check that the LEA instruction does what I say it does.
No. Really. Save the file, assemble it, walk it through. Make sure you can use the Hatari debugger to do this.
This approach to a list is usually referred to as an array, by the way. As you see, we access it by a base address and an index, or offset into the array. It is our method of accessing it that is array-like. But array access is usually a little more complicated. We'll get to that, too.
Next, let's see if we can put some of this together to put out a message, and hopefully this will begin to make sense.
No, I guess we aren't quite ready for that. I think we need to first take a little look at accessing the elements of a list in an orderly sequence. That should help us get in the mood to work with strings. Then we can put out a simple message.
No comments:
Post a Comment