The Poor Man's Linker experiment has gone well. The conversion of the run-time library to the new approach is done. In the foreseeable future, my Python library (currently 6502 only) will be converted in the same way; it really needs it.

The following program, the skeleton of a monitor or a debugger, compiles into a 6800 binary image a little under 2K bytes in size; it uses quite a bit but not all of the library code.

Code:

10 PRINT '? ';
20 INPUT LINE A$
30 GOSUB 1000:REM Strip leading spaces from A$
40 B$=LEFT$(A$,1):A$=MID$(A$,2):GOSUB 1000:GOSUB 1100
50 IF B$ = 'D' THEN 10000
60 IF B$ = 'U' THEN 12000
90 IF B$ = 'Q' THEN END
95 PRINT 'Unrecognized command.':GOTO 10
1000 REM Strip leading spaces from A$
1010 IF ASC(' ') = ASC(A$) THEN A$=MID$(A$,2) ELSE RETURN
1020 GOTO 1010
1100 REM Convert B$ to upper case
1110 IF ASC('a') <= ASC(B$) AND ASC('z') >= ASC(B$) THEN B$=CHR$(ASC(B$)-32)
1120 RETURN
10000 REM DUMP
10001 print "DUMP ";a$:goto 10
12000 REM UNASSEMBLE
12001 print "UNASSEMBLE ";a$:goto 10

You may have noticed the ordering of "IF ASC(' ') = ASC(A$)" as a bit unusual. A single-pass compiler which generates code as it parses the source can do a better job if simple expressions which can be completely evaluated at compile time are on the left while things which must wait until run time are postponed as long as possible. The opposite "IF ASC(A$) = ASC(' ')" gets the first character from the string, puts it into a temporary variable, then does the comparison because without lookahead, the compiler does not know that a constant follows.

Since what I thought was source code for the FLEX BASIC interpreter turned out to be something else, SWTPC BASIC instead of TSC BASIC, I will be building a version of this compiler to generate 6502 code for TSC BASIC programs. I am just starting to reverse engineer the FLEX BASIC and Extended BASIC interpreters and thus cannot commit to doing anything with them at this time.

For comparison, here is some code from the two compilers...

The 6502 code generated by the compiler:

Code:

00108 ; 120 C = A * (B + 1)
0B26 00109 L00120:
00110 ifdef __TRACE
00111 ldx #<120
00112 lda #>120
00113 jsr Trace
00114 endif
00115 ifdef __ATLIN
00116 ldx #<L00120
00117 stx ResLn_
00118 ldx #>L00120
00119 stx ResLn_+1
00120 endif
00121
0B26 18 [2] 00122 clc
0B27 AD 0F39 [4] 00123 lda B_
0B2A 69 01 [2] 00124 adc #<1
0B2C AA [2] 00125 tax
0B2D AD 0F3A [4] 00126 lda B_+1
0B30 69 00 [2] 00127 adc #>1
0B32 AC 0F37 [4] 00128 ldy A_
0B35 84 14 [3] 00129 sty Int0
0B37 AC 0F38 [4] 00130 ldy A_+1
0B3A 84 15 [3] 00131 sty Int0+1
0B3C 20 0D30 [6] 00132 jsr IMul
0B3F 8E 0F3B [4] 00133 stx C_
0B42 8D 0F3C [4] 00134 sta C_+1

The 6800 code generated by the compiler:

Code:

00083 * 120 C = A * (B + 1)
0119 00084 L00120
00085 ifdef __TRACE
00086 ldx #120
00087 jsr Trace
00088 endif
00089 ifdef __ATLIN
00090 ldx #L00120
00091 stx ResLn_
00092 endif
00093
0119 C6 01 [2] 00094 ldab #1
011B 4F [2] 00095 clra
011C FB 0435 [4] 00096 addb B_+1
011F B9 0434 [4] 00097 adca B_
0122 FE 0432 [5] 00098 ldx A_
0125 BD 0297 [9] 00099 jsr IMul
0128 F7 0437 [5] 00100 stab C_+1
012B B7 0436 [5] 00101 staa C_

The 6502 multiply subroutine:

Code:

. 00730 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
. 00731 ;
. 00732 ; IMul - Multiply integers
. 00733 ;
. 00734 ; Input:
. 00735 ; A:X = one number
. 00736 ; Int0 = the other number
. 00737 ;
. 00738 ; Output:
. 00739 ; A:X = the product
. 00740 ;
. 00741
.0D2C 00742 IMulB rmb 2 ; Operand
.0D2E 00743 IMulC rmb 1 ; Bits left
.0D2F 00744 IMulS rmb 1 ; Sign of the product
. 00745
.0D30 00746 IMul:
.0D30 A0 00 [2] 00747 ldy #0 ; Clear sign of product
.0D32 8C 0D2F [4] 00748 sty IMulS
. 00749
.0D35 C9 00 [2] 00750 cmp #0 ; Is first number negative?
.0D37 10 10 (0D49) [2/3] 00751 bpl IMul1 ; No
. 00752
.0D39 EE 0D2F [6] 00753 inc IMulS ; Update sign of product
. 00754
.0D3C 49 FF [2] 00755 eor #$FF ; Negate the number
.0D3E A8 [2] 00756 tay
.0D3F 8A [2] 00757 txa
.0D40 49 FF [2] 00758 eor #$FF
.0D42 18 [2] 00759 clc
.0D43 69 01 [2] 00760 adc #1
.0D45 AA [2] 00761 tax
.0D46 98 [2] 00762 tya
.0D47 69 00 [2] 00763 adc #0
. 00764
.0D49 00765 IMul1:
.0D49 8E 0D2C [4] 00766 stx IMulB ; Save the number
.0D4C 8D 0D2D [4] 00767 sta IMulB+1
. 00768
.0D4F A5 15 [3] 00769 lda Int0+1 ; Is the other number negative?
.0D51 10 10 (0D63) [2/3] 00770 bpl IMul2 ; No
. 00771
.0D53 EE 0D2F [6] 00772 inc IMulS ; Update sign of product
. 00773
.0D56 A9 00 [2] 00774 lda #0 ; Negate the other number
.0D58 38 [2] 00775 sec
.0D59 E5 14 [3] 00776 sbc Int0
.0D5B 85 14 [3] 00777 sta Int0
.0D5D A9 00 [2] 00778 lda #0
.0D5F E5 15 [3] 00779 sbc Int0+1
.0D61 85 15 [3] 00780 sta Int0+1
. 00781
.0D63 00782 IMul2:
.0D63 A9 10 [2] 00783 lda #16 ; 16 bits to multiply
.0D65 8D 0D2E [4] 00784 sta IMulC
. 00785
.0D68 A9 00 [2] 00786 lda #0 ; Clear product
.0D6A A8 [2] 00787 tay
. 00788
.0D6B 00789 IMul3:
.0D6B 4E 0D2D [6] 00790 lsr IMulB+1 ; Shift number right
.0D6E 6E 0D2C [6] 00791 ror IMulB
.0D71 90 09 (0D7C) [2/3] 00792 bcc IMul4 ; Skip add if low bit was clear
. 00793
.0D73 18 [2] 00794 clc ; Add number to product
.0D74 65 14 [3] 00795 adc Int0
.0D76 AA [2] 00796 tax
.0D77 98 [2] 00797 tya
.0D78 65 15 [3] 00798 adc Int0+1
.0D7A A8 [2] 00799 tay
.0D7B 8A [2] 00800 txa
. 00801
.0D7C 00802 IMul4:
.0D7C 06 14 [5] 00803 asl Int0 ; Shift the other number left
.0D7E 26 15 [5] 00804 rol Int0+1
. 00805
.0D80 CE 0D2E [6] 00806 dec IMulC ; One fewer bit to do
.0D83 D0 E6 (0D6B) [2/3] 00807 bne IMul3 ; More?
. 00808
.0D85 4E 0D2F [6] 00809 lsr IMulS ; Is product negative?
.0D88 90 0E (0D98) [2/3] 00810 bcc IMul5 ; No
. 00811
.0D8A 49 FF [2] 00812 eor #$FF ; Negate the product
.0D8C 18 [2] 00813 clc
.0D8D 69 01 [2] 00814 adc #1
.0D8F AA [2] 00815 tax
.0D90 98 [2] 00816 tya
.0D91 49 FF [2] 00817 eor #$FF
.0D93 69 00 [2] 00818 adc #0
. 00819
.0D95 4C 0D9A [3] 00820 jmp IMul6
. 00821
.0D98 00822 IMul5:
.0D98 AA [2] 00823 tax ; Product goes in A:X
.0D99 98 [2] 00824 tya
. 00825
.0D9A 00826 IMul6:
.0D9A 60 [6] 00827 rts

The 6800 multiply subroutine:

Code:

. 00560 ******************************************************************************
. 00561 *
. 00562 * IMul - Multiply integers
. 00563 *
. 00564 * Input:
. 00565 * A:B = one number
. 00566 * X = the other number
. 00567 *
. 00568 * Output:
. 00569 * A:B = the product
. 00570 *
.0293 00571 IMulB rmb 2 ; Operand
.0295 00572 IMulC rmb 1 ; Bits left
.0296 00573 IMulS rmb 1 ; Sign of the product
. 00574
.0297 00575 IMul
.0297 7F 0296 [6] 00576 clr IMulS ; Clear sign of product
. 00577
.029A DF 02 [5] 00578 stx Int0 ; Save second number
. 00579
.029C 4D [2] 00580 tsta ; Is first number negative
.029D 2A 07 (02A6) [4] 00581 bpl IMul1 ; No
. 00582
.029F 7C 0296 [6] 00583 inc IMulS ; Update sign of product
. 00584
.02A2 40 [2] 00585 nega ; Negate the number
.02A3 50 [2] 00586 negb
.02A4 82 00 [2] 00587 sbca #0
. 00588
.02A6 00589 IMul1
.02A6 B7 0293 [5] 00590 staa IMulB ; Save the number
.02A9 F7 0294 [5] 00591 stab IMulB+1
. 00592
.02AC 96 02 [3] 00593 ldaa Int0 ; Is the other number negative?
.02AE 2A 0E (02BE) [4] 00594 bpl IMul2 ; No
. 00595
.02B0 7C 0296 [6] 00596 inc IMulS ; Update sign of product
. 00597
.02B3 73 0002 [6] 00598 com Int0 ; Negate the other number
.02B6 70 0003 [6] 00599 neg Int0+1
.02B9 25 03 (02BE) [4] 00600 bcs IMul2
.02BB 7A 0002 [6] 00601 dec Int0
. 00602
.02BE 00603 IMul2
.02BE 86 10 [2] 00604 ldaa #16 ; 16 bits to multiply
.02C0 B7 0295 [5] 00605 staa IMulC
. 00606
.02C3 4F [2] 00607 clra ; Clear product
.02C4 5F [2] 00608 clrb
. 00609
.02C5 00610 IMul3
.02C5 74 0293 [6] 00611 lsr IMulB ; Shift number right
.02C8 76 0294 [6] 00612 ror IMulB+1
.02CB 24 04 (02D1) [4] 00613 bcc IMul4 ; Skip add if low bit was clear
. 00614
.02CD DB 03 [3] 00615 addb Int0+1 ; Add number to product
.02CF 99 02 [3] 00616 adca Int0
. 00617
.02D1 00618 IMul4
.02D1 78 0003 [6] 00619 asl Int0+1 ; Shift the other number left
.02D4 79 0002 [6] 00620 rol Int0
. 00621
.02D7 7A 0295 [6] 00622 dec IMulC ; One fewer bit to do
.02DA 26 E9 (02C5) [4] 00623 bne IMul3 ; More?
. 00624
.02DC 74 0296 [6] 00625 lsr IMulS ; Is the product negative?
.02DF 24 04 (02E5) [4] 00626 bcc IMul5 ; No
. 00627
.02E1 40 [2] 00628 nega ; Negate the product
.02E2 50 [2] 00629 negb
.02E3 82 00 [2] 00630 sbca #0
. 00631
.02E5 00632 IMul5
.02E5 39 [5] 00633 rts

## Bookmarks