Saturday, July 20, 2024

ALPP 01-08 -- Simple Lists on the 6800, 6801, 6809, and 68000

Simple Lists on the 6800, 6801, 6809, and 68000

(Title Page/Index)

 

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.


(Title Page/Index)

 

No comments:

Post a Comment