summaryrefslogtreecommitdiff
path: root/programs/subasm.s
diff options
context:
space:
mode:
Diffstat (limited to 'programs/subasm.s')
-rw-r--r--programs/subasm.s1019
1 files changed, 457 insertions, 562 deletions
diff --git a/programs/subasm.s b/programs/subasm.s
index 50f2e8d..350e105 100644
--- a/programs/subasm.s
+++ b/programs/subasm.s
@@ -3,576 +3,471 @@
;
; by mr b0nk 500 <b0nk@b0nk.xyz>
-; Variables
-.org $1000
-prg_name:
+MAX_SYM = $800 ; Max symbol size.
+
+.org incl
+; String Constants.
+asm_name:
.byte "SuBAsm"
-ver_txt:
- .byte ", version "
-ver_num:
+asm_ver:
.byte "0.1"
; Directives.
dir:
- .byte "org"
+ .byte "org",
.byte "byte"
.byte "word"
.byte "dword"
.byte "qword"
+ .byte "include"
+
+; Short form Commands.
+sh_cmds:
+ .byte "vlahirs"
+
+; Commands.
+cmds:
+ .byte "viewmem"
+ .byte "list"
+ .byte "asm"
+ .byte "help"
+ .byte "inst"
+ .byte "run"
+ .byte "set"
+
+; Instruction mnemonics, and opcodes.
+
+; Legend.
+; mne = Mnemonic.
+; imm = Immediate data.
+; zm = Zero Matrix.
+; zmx = Zero Matrix, indexed with X.
+; zmy = Zero Matrix, indexed with Y.
+; ind = Indirect.
+; idx = Indexed Indirect.
+; idy = Indirect Indexed.
+; abs = Absolute.
+; imp = Implied.
-; Instruction mnemonics.
mne:
- .byte "CPS"
- .byte "ADC"
- .byte "AAB"
- .byte "PHB"
- .byte "PHP"
- .byte "PHA"
- .byte "PHY"
- .byte "TAY"
- .byte "PHX"
- .byte "TAX"
- .byte "TYX"
- .byte "JMP"
- .byte "SBC"
- .byte "SAB"
- .byte "PLB"
- .byte "PLP"
- .byte "PLA"
- .byte "PLY"
- .byte "TYA"
- .byte "PLX"
- .byte "TXA"
- .byte "TXY"
- .byte "JSR"
- .byte "AND"
- .byte "ABA"
- .byte "STT"
- .byte "TAB"
- .byte "TSX"
- .byte "BPO"
- .byte "ORA"
- .byte "OAB"
- .byte "TBA"
- .byte "SEI"
- .byte "TXS"
- .byte "BNG"
- .byte "XOR"
- .byte "XAB"
- .byte "CLI"
- .byte "BCS"
- .byte "LSL"
- .byte "LLB"
- .byte "STB"
- .byte "SEC"
- .byte "STA"
- .byte "STY"
- .byte "STX"
- .byte "BCC"
- .byte "LSR"
- .byte "LRB"
- .byte "LDB"
- .byte "CLC"
- .byte "LDA"
- .byte "LDY"
- .byte "LDX"
- .byte "BEQ"
- .byte "ROL"
- .byte "RLB"
- .byte "SSP"
- .byte "BNE"
- .byte "ROR"
- .byte "RRB"
- .byte "CSP"
- .byte "BVS"
- .byte "MUL"
- .byte "MAB"
- .byte "SEV"
- .byte "BVC"
- .byte "DIV"
- .byte "DAB"
- .byte "CLV"
- .byte "RTS"
- .byte "CMP"
- .byte "CAB"
- .byte "CPY"
- .byte "CPX"
- .byte "CPB"
- .byte "ENT"
- .byte "RTI"
- .byte "INC"
- .byte "IAB"
- .byte "INY"
- .byte "INX"
- .byte "DEC"
- .byte "DBA"
- .byte "DEY"
- .byte "DEX"
- .byte "WAI"
- .byte "JSL"
- .byte "ASR"
- .byte "ARB"
- .byte "NOP"
- .byte "RTL"
- .byte "BRK"
-
-
-scr_row:
- .byte $0
-scr_col:
- .byte $0
-a:
- .word $0
-b:
- .word $0
-c:
- .word $0
-d:
- .word $0
-
-str_buf:
-
-; Input buffer.
-.org $2000
-buf:
-
-.org $2400
-ptr1:
- .qword $2500
-
-ptr2:
- .qword $2900
-
-; Control Register.
-.org $C000
-ctrl_reg:
-
-; Screen.
-.org $C001
-scr:
-
-; Keyboard.
-.org $C002
-kbd:
-
-; Main program.
-.org $0
-reset:
- cps
- ldx.w #$FFFF
- txs
- ldy #0
- jsr clr_buf
- ldx.w #0 ; Reset x.
- ldy #0 ; Reset y.
- jmp print_title
-
-read:
- lda ctrl_reg ; Is the keyboard ready?
- beq read ; Loop until the keyboard is ready.
- lda #0 ; Start resetting the control register.
- sta ctrl_reg ; Reset the control register.
- jmp getchar ; We got a key.
-
-rset_x:
-
- ldx #0 ; Reset x.
- stx.w x
- rts
-
-print_title:
- lda prg_name, x
- beq print_ver ; Did we find a null terminator?
- sta ; Print character.
- inx ; Increment offset.
- inc x
- jmp print_title ; Keep printing more characters.
-
-print_ver
- jsr rset_x
- lda ver_txt, x
- beq print_num ; Did we find a null terminator?
- sta scr ; Print character.
- inx ; Increment offset.
- jmp print_ver ; Keep printing more characters.
-
-print_num:
- lda ver_num, x
- beq getline ; Did we find a null terminator?
- sta scr ; Print character.
- inx ; Increment offset.
- jmp print_num ; Keep printing more characters.
-getline:
- lda #$A
- sta scr ; Print newline
- inc scr_row
- lda #0
- sta scr_col
- inc y
- jsr rset_x
- jmp read
-
-getchar:
- lda kbd ; Get typed character.
- cmp #$1B ; Did the user type an escape?
- beq esc ; Yes, so start getting the escape code.
- cmp #$A ; Did the user type a newline?
- beq nl ; Yes, so start parsing the input.
- cmp #8 ; Did the user type a backspace?
- beq bs ; Yes, so start checking the buffer.
- jsr echo ; Print character to screen.
-
-store_char:
- sta buf, y ; Store typed character into the input buffer.
- iny ; Increment buffer offset.
- jmp read ; Get another character.
-
-esc:
- lda ctrl_reg ; Skip the '['.
- lda ctrl_reg ; Get the next character.
- beq read ; We have an error, so discard it, and go back to getting user input.
- lda kbd ; Get the escape code.
- sta c ; Store the escape code, until we need it.
- jsr isup ; Check if the user pressed up.
- lda d
- cmp #0
- bne esc_end
- jsr isdown ; Check if the user pressed down.
- lda d
- cmp #0
- bne esc_end
- lda #0
- jsr isleft ; Check if the user pressed left.
- lda d
- cmp #0
- bne esc_end
- jsr isright ; Check if the user pressed right.
-esc_end:
- lda #$0
- sta d
- jmp rset_a ; Go back to getting user input.
-
-isup:
- lda scr_row ; Is the cursor at the top of the screen?
- beq isup_done ; Yes, so return.
- lda c ; No, so load the escape code back into the accumulator.
- cmp #$41 ; Did the user press the up arrow key?
- beq up ; Yes, so move the cursor up.
-isup_done:
- rts ; End of isup.
-
-isdown:
- lda scr_row ; Start checking the y coordinate of the cursor.
- cmp #$17 ; Is the cursor at the bottom of the screen?
- beq isdown_done ; Yes, so return.
- lda c ; No, so load the escape code back into the accumulator.
- cmp #$42 ; Did the user press the down arrow key?
- beq down ; Yes, so move the cursor down.
-isdown_done:
- rts ; End of isdown.
-
-isright:
- lda scr_col ; Start checking the x coordinate of the cursor.
- cmp #$4F ; Is the cursor at the far right of the screen?
- beq isright_end ; Yes, so return.
- lda c ; No, so load the escape code back into the accumulator.
- cmp #$43 ; Did the user press the right arrow key?
- beq right ; Yes, so move the cursor right.
-isright_end:
- rts ; End of isright.
-
-isleft:
- lda scr_col ; Is the cursor at the far left of the screen?
- beq isleft_done ; Yes, so return.
- lda c ; No, so load the escape code back into the accumulator.
- cmp #$44 ; Did the user press the left arrow key?
- beq left ; Yes, so move the cursor left.
-isleft_done:
- rts ; End of isleft.
-
-up:
- dec scr_row
- jsr update_pos
- lda #1
- sta d
- jmp isup_done
-down:
- inc scr_row
- jsr update_pos
- lda #1
- sta d
- jmp isdown_done
-right:
- inc scr_col
- jsr update_pos
- jmp isright_end
-left:
- dec scr_col
- jsr update_pos
- lda #1
- sta d
- jmp isleft_done
-
-update_pos:
- lda #$1B ; Print an escape character
- sta scr ; to the screen.
- lda #$5B ; Print '['
- sta scr ; to the screen, and start the escape sequence.
- jsr getrow ; Start printing the row number to the screen.
- jsr getcol ; Start printing the column number to the screen.
- lda #$48 ; Print 'H'
- sta scr ; to the screen.
- rts ; End of update_pos.
-getrow:
- lda scr_row ; Get the cursor's y coordinate.
- div #$A ; Divide A by 10.
- adc #$30 ; Convert it to ascii, and
- sta scr ; print to the screen.
- tba ; Get the remainder.
- adc #$30 ; Convert it to ascii, and
- sta scr ; print to the screen.
- rts ; End of getrow.
-getcol:
- lda #$3B ; Print ';'
- sta scr ; to the screen.
- lda scr_col ; Get the cursor's x coordinate.
- div #$A ; Divide A by 10.
- adc #$30 ; Convert it to ascii, and
- sta scr ; print to the screen.
- tba ; Get the remainder.
- adc #$30 ; Convert it to ascii, and
- sta scr ; print to the screen.
- rts ; End of getrow.
-
-
-
-nl:
- sta scr ; Print newline.
- inc scr_row ; Move the cursor down one line.
- lda #0 ; Put a null terminator, in place of the newline.
- sta scr_col ; Move the cursor back to column 0.
- sta buf, y ; Place it into the input buffer.
- ldy.w #0 ; Reset y, to parse the input.
- jsr parse ; Start parsing input.
-
-back:
- sta scr ; Print backspace.
- lda #0 ; Put a null terminator, in place of the backspace.
- sta buf, y ; Place it into the input buffer.
- dey ; Decrement buffer offset.
- dec scr_col
- jmp read ; Get next character.
-
-bs:
- cpy #0 ; Are we at the start of the buffer?
- beq read ; We are, so do not store the backspace into the buffer.
- jmp back ; We are not, so add the backspace to the buffer.
-
-parse:
- jsr getdir
- jsr
- rts
-
-getdir:
- iny ; Increment offset.
- lda buf, y
- jsr iswhite
- bcs getdir ; Reset y, if we hit the null terminator.
- cmp #$2E ; Is this character a '.'?
- bne getdir_exit ; No, so return.
- jsr clr_ptr
-
-getdir_end:
- iny ; Increment offset.
- lda buf, y
- jsr iswhite
- bcs getdir_cmp
- ora #%00100000 ; Make character lower case.
- sta (ptr1), y
- jmp getdir_end
-gettok:
- ply #1
- iny
-gettok2:
- lda buf, y
- jsr istoken
- bcs gettok3
- jmp gettok2
-gettok3:
- cmp #$
- cmp #$24 ; Is this character, a '$'?
- beq getaddr ; Yes, so start getting the address.
-
-
-
-getdir_cmp:
- phy #1
- ldy.w #0
- tyx
-getdir_cpl:
- ldb dir, x ; Start checking if the directive we're using, is "org".
- stb (ptr2), y
- beq getdir_scmp
- inx
- iny
- jmp getdir_cpl
-getdir_scmp:
- ldy #0
- jsr strcmp
- cpx #0
- beq getdir_tok
-getdir_exit:
- rts ; End of getdir.
-
-
-istoken:
- cmp #$20 ; Is this character a space?
- beq istoken_f ; Yes, so return false.
- cmp #$09 ; Is this character a tab?
- beq istoken_f ; Yes, so return false.
- cmp #$A ; Is this character a newline?
- beq istoken_f ; Yes, so return false.
- cmp #$3B ; Is this character a ';'?
- beq istoken_f ; Yes, so return false.
- cmp #0 ; Is this character a null terminator?
- beq istoken_f ; Yes, so return false.
- sec ; Return true.
- rts ; End of istoken.
-istoken_f
- clc ; Return false.
- rts ; End of istoken_f.
-
-iswhite:
- cmp #$20 ; Is this character a space?
- beq iswhite_t ; Yes, so return true.
- cmp #9 ; Is this character a tab?
- beq iswhite_t ; Yes, so return true.
- clc ; No, so return false.
- rts ; End of iswhite.
-iswhite_t:
- sec ; Return true.
- rts ; End of iswhite_t.
-
-rset_y:
- ldy.w #0
- jmp print_buf ; Print the input buffer.
-
-print_buf:
- lda buf, y ; Get a character from the input buffer.
- beq fin ; Are we done with printing the buffer?
- sta scr ; Print said character.
- iny
- jmp print_buf ; Keep printing the buffer.
-
-spin:
- nop
- nop
- nop
- jmp spin
-
-clr_buf:
- lda #0
- cpy.w #$3FF
- beq clr_end
- sta buf, y
- iny
- jmp clr_buf
-clr_sbuf:
- lda #0
- cpy.w #$1FF
- beq clr_end
- sta str_buf, y
- iny
- jmp clr_sbuf
-
-clr_end:
- rts
-
-echo:
- tab
- ldx scr_col
- cpx #$4F
- bne echo_print
- cmp #$A
- beq linewrap
-linewrap:
- inc scr_row
- ldx #0
- stx scr_col
- jsr update_pos
-echo_print:
- tba
- sta scr ; Echo typed character.
- inc scr_col ; Increment the cursor's x coordinate.
- sta buf, y ; Store typed character into the input buffer.
- iny ; Increment the buffer offset.
- rts ; Return.
-
-clr_ptr:
- lda #0
- cpy.w #$3FF
- beq ptr_end
- sta (ptr1), y
- sta (ptr2), y
- iny
- jmp clr_ptr
-ptr_end:
- rts
-
-strcmp:
- lda (ptr1), y
- cmp (ptr2), y
- bne strcmp_l1
- tax
- beq strcmp_l3
- iny
- bne strcmp
- jmp strcmp
-
-
-strcmp_l1:
- bcs strcmp_l2
- ldx #0
- dex
- rts
-
-strcmp_l2:
- ldx #1
-strcmp_l3:
- rts
-
-
-.org $FFC0
-.qword reset
-
-.org $FF50
-.qword spin
-.qword spin
-.qword spin
-.qword spin
-.qword spin
-.qword spin
-.qword spin
-
-.org $FFA0
-.qword irq_routine
-.org $0
-v
-.org $100
-v
-.org $200
-v
-.org $300
-v
-.org $1000
-v
-.org $1100
-v
-.org $1200
-v
-.org $1300
-v
-.org $1400
-v
-q
-
+; mne imm, zm, zmx, zmy, ind, idx, idy, abs, imp
+ .byte "CPS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $00
+ .byte "ADC", $01, $06, $FF, $FF, $FF, $FF, $FF, $04, $FF
+ .byte "AAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $02
+ .byte "PHP", $08, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "CPB", $09, $2D, $FF, $FF, $55, $AD, $AC, $2C, $FF
+ .byte "PHB", $0A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "DEC", $FF, $0D, $FF, $FF, $FF, $FF, $FF, $0C, $E5
+ .byte "JMP", $FF, $0E, $FF, $FF, $CE, $FF, $FF, $10, $FF
+ .byte "SBC", $11, $16, $FF, $FF, $FF, $FF, $FF, $14, $FF
+ .byte "SAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $12
+ .byte "ENT", $18, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "CPY", $19, $3D, $FF, $FF, $85, $FF, $FF, $4C, $FF
+ .byte "PLB", $1A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "INC", $FF, $1D, $FF, $FF, $FF, $FF, $FF, $1C, $F5
+ .byte "JSR", $FF, $1E, $FF, $FF, $BE, $FF, $FF, $FF, $FF
+ .byte "JSL", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $20, $FF
+ .byte "AND", $21, $26, $FF, $FF, $FF, $FF, $FF, $24, $FF
+ .byte "ABA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $22
+ .byte "PLP", $28, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "CPX", $29, $4D, $FF, $FF, $B5, $FF, $FF, $3C, $FF
+ .byte "PHY", $2A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "BPO", $FF, $2E, $FF, $FF, $FF, $FF, $FF, $30, $FF
+ .byte "ORA", $31, $36, $FF, $FF, $FF, $FF, $FF, $34, $FF
+ .byte "OAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $32
+ .byte "STT", $38, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "PLY", $3A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "BNG", $FF, $3E, $FF, $FF, $FF, $FF, $FF, $40, $FF
+ .byte "XOR", $41, $46, $FF, $FF, $FF, $FF, $FF, $44, $FF
+ .byte "XAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $42
+ .byte "PHA", $48, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "PHX", $4A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "BCS", $FF, $4E, $FF, $FF, $FF, $FF, $FF, $50, $FF
+ .byte "LSL", $51, $56, $FF, $FF, $FF, $FF, $FF, $54, $FF
+ .byte "LLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $52
+ .byte "CLC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $58
+ .byte "PLX", $5A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "BCC", $FF, $5E, $FF, $FF, $FF, $FF, $FF, $60, $FF
+ .byte "LSR", $61, $66, $FF, $FF, $FF, $FF, $FF, $64, $FF
+ .byte "LRB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $62
+ .byte "PLA", $68, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "TAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $6A
+ .byte "BEQ", $FF, $6E, $FF, $FF, $FF, $FF, $FF, $70, $FF
+ .byte "ROL", $71, $76, $FF, $FF, $FF, $FF, $FF, $74, $FF
+ .byte "RLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $72
+ .byte "SEC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $78
+ .byte "TBA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $7A
+ .byte "BNE", $FF, $7E, $FF, $FF, $FF, $FF, $FF, $80, $FF
+ .byte "ROR", $81, $86, $FF, $FF, $FF, $FF, $FF, $84, $FF
+ .byte "RRB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $82
+ .byte "DEY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $88
+ .byte "TAY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $8A
+ .byte "BVS", $FF, $8E, $FF, $FF, $FF, $FF, $FF, $90, $FF
+ .byte "MUL", $91, $96, $FF, $FF, $FF, $FF, $FF, $94, $FF
+ .byte "MAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $92
+ .byte "CLI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $98
+ .byte "TYA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $9A
+ .byte "BVC", $FF, $9E, $FF, $FF, $FF, $FF, $FF, $A0, $FF
+ .byte "DIV", $A1, $A6, $FF, $FF, $FF, $FF, $FF, $A4, $FF
+ .byte "DAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A2
+ .byte "INY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A8
+ .byte "TAX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $AA
+ .byte "RTS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $AE
+ .byte "RTL", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B0
+ .byte "CMP", $B1, $B6, $FF, $FF, $25, $7D, $7C, $B4, $FF
+ .byte "CAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B2
+ .byte "SEI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B8
+ .byte "LDX", $B9, $BD, $FF, $C9, $95, $FF, $FF, $BC, $FF
+ .byte "TXA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $BA
+ .byte "RTI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C0
+ .byte "LDA", $C1, $C6, $79, $39, $05, $5D, $5C, $C4, $FF
+ .byte "DEX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C5
+ .byte "CLV", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C8
+ .byte "TYX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $CA
+ .byte "STA", $FF, $CD, $89, $49, $15, $6D, $6C, $CC, $FF
+ .byte "TSX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D0
+ .byte "LDB", $D1, $D6, $99, $59, $35, $8D, $8C, $D4, $FF
+ .byte "INX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D5
+ .byte "WAI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D8
+ .byte "TXY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $DA
+ .byte "STB", $FF, $DD, $A9, $69, $45, $9D, $9C, $DC, $FF
+ .byte "TXS", $E0, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "LDY", $E1, $E6, $E9, $FF, $65, $FF, $FF, $E4, $FF
+ .byte "BRK", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $E8
+ .byte "NOP", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $EA
+ .byte "STY", $FF, $ED, $F9, $FF, $75, $FF, $FF, $EC, $FF
+ .byte "DEB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $EE
+ .byte "ASR", $F1, $F6, $FF, $FF, $FF, $FF, $FF, $F4, $FF
+ .byte "ARB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $F2
+ .byte "STX", $FF, $FD, $FF, $D9, $A5, $FF, $FF, $FC, $FF
+ .byte "INB" $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FE
+
+; Command subroutine table.
+cmd_srt:
+ .word viewmem
+ .word list
+ .word asm
+ .word help
+ .word inst
+ .word run
+ .word set
+
+; Hex character table.
+hex_char:
+ .byte "0123456789ABCDEF"
+
+
+; Token table.
+.org $20000
+tokline:
+
+.org cmd_buf+$400
+; Program Counter.
+prg_cnt:
+ .qword 0
+; Hex digit string buffer.
+hex_str:
+ .qword 0, 0
+; String buffer.
+strbuf:
+
+.org strbuf+$80
+; Subroutine pointer.
+sub_ptr:
+ .word 0
+
+; Indecies.
+idx0:
+ .qword 0
+idx1:
+ .qword 0
+idx2:
+ .qword 0
+idx3:
+ .qword 0
+
+; Lexeme string.
+lexeme:
+
+; Symbol tables.
+.org lexeme+$100
+sym_val:
+.org sym_val+$4000
+sym_id:
+.org sym_id+$1000
+sym_def:
+.org sym_def+$100
+sym_name:
+
+; Fixup table.
+; Fixups are unresolved symbols.
+.org sym_name+$1000
+fix_sym:
+.org fix_sym+$1000
+fix_ln:
+.org fix_ln+$1000
+fix_val:
+
+
+; Start of program code.
+.org parser
+subasm:
+ ldb #0 ; Set the first pointer
+ lda.d #cmd_buf ; to the command buffer.
+ jsl set_ptr ;
+ tba ; Reset A.
+ tax ; Reset X.
+ jsl chk_shcmd ; Did we get a shortend command?
+ bne parse_cmd ; Yes, so skip everything else.
+ jmp subasm_end ;
+ jsl chk_cmd ; No, but did we get a full command?
+ bne parse_cmd ; Yes, so skip everything else.
+ jsl lexer ; No, so start lexing this line.
+subasm_end:
+ rtl ; End of subasm.
+
+parse_cmd:
+ ldb #1 ; Set the second pointer
+ lda.d #cmd_srt ; to the command subroutine table.
+ jsl set_ptr ;
+ deb ; Reset B.
+ tba ; Reset A.
+ lda f ; Get the command ID.
+ cmp #8 ; Is the command ID greater than the command count?
+ bcs subasm_end ; Yes, so we're done.
+ lsl #1 ; No, so multiply the command ID by two.
+ phy #2 ; Preserve the screen buffer position.
+ tay ; Set the index to the offset that we just calculated.
+ lda.w (ptr2), y ; Get the command subroutine, from the command subroutine table.
+ ply #2 ; Get back the screen buffer position.
+ ldb #2 ; Save it in the third pointer.
+ jsl set_ptr ;
+ ldb #0 ; Reset B.
+ jsr (ptr3) ; Run the command's subroutine.
+ jmp subasm_end ; We are done.
+
+chk_shcmd:
+ tba ; Reset A.
+ inb ; Set the second pointer
+ lda.w #sh_cmds ; to the shortend command table.
+ jsl set_ptr ;
+ deb ; Reset B.
+ tba ; Reset A.
+ phy #2 ; Preserve the screen buffer position.
+ txy ; Set our index to zero.
+ lda (ptr), y ; Is there nothing in the command buffer?
+ beq shcmd_fail ; Yes, so return that we failed.
+ cmp #' ' ; No, but is this character, a space?
+ beq shcmd_fail ; Yes, so return that we failed.
+shcmd_loop:
+ ldb (ptr2), y ; Are we at the end of the table?
+ beq shcmd_fail ; Yes, so return that we failed.
+ cab ; No, so did the character match?
+ beq shcmd_fnd ; Yes, so check if there are any arguments.
+ iny ; No, so check the next command.
+ jmp shcmd_loop ; Keep looping.
+shcmd_fnd:
+ sty f ; Save the command ID.
+ ldy #1 ; Check the next character in the command buffer.
+ lda (ptr), y ; Is this the end of the buffer?
+ beq shcmd_true ; Yes, so return that we succeded.
+ cmp #' ' ; No, but is this a space?
+ beq shcmd_true ; Yes, so return that we succeded.
+ jmp shcmd_fail ; No, so return that we failed.
+shcmd_true:
+ lda #1 ; Return true.
+ jmp shcmd_end ; We are done.
+shcmd_fail:
+ ldb #0 ; Reset B.
+ tba ; Return false.
+ tax ; Reset X.
+shcmd_end:
+ ply #2 ; Get back the screen buffer position.
+ rtl ; End of chk_shcmd.
+
+print_hex:
+ pha #8 ; Preserve the hex value.
+ and #0 ; Reset A.
+ ldb #1 ; Set the second pointer
+ lda.w #hex_char ; to the start of hex character table.
+ jsl set_ptr ;
+ inb ; Set the third pointer
+ lda.d #hex_str ; to the end of hex string buffer.
+ clc ; Do a non carrying add.
+ adc #$10 ;
+ jsl set_ptr ;
+ ldb #0 ; Reset B.
+ pla #8 ; Get the hex value back.
+pnthex_lp:
+ pha #8 ; Preserve the hex value.
+ and #$F ; Mask the lowest nibble.
+ phy #2 ; Preserve the screen buffer position.
+ tay ; Get the index for the hex digit.
+ lda (ptr2), y ; Get the hex digit.
+ dec ptr3 ; Decrement the string pointer.
+ sta (ptr3) ; Save the hex digit character in the string.
+ ply #2 ; Get back the screen buffer position.
+ pla #8 ; Get the hex value back.
+pnthex_lp1:
+ cpx #1 ; Is the digit count less than one?
+ bcc pnthex_lp2 ; Yes, so don't decrement the digit count.
+ dex ; No, but was the digit count zero, when decremented?
+ beq pnthex_end ; Yes, so we're done.
+ jmp pnthex_lp3 ; No, so get the next nibble.
+pnthex_lp2:
+ ldb #1 ; Enable auto digit count.
+pnthex_lp3:
+ lsr #4 ; No, but is the next nibble, a zero?
+ beq pnthex_lp4 ; Yes, so check if auto digit count is enabled.
+ jmp pnthex_lp ; No, so print the next digit.
+pnthex_lp4:
+ cpb #1 ; Is auto digit count enabled?
+ beq pnthex_end ; Yes, so we're done.
+ jmp pnthex_lp ; No, so keep printing more digits.
+pnthex_end:
+ rtl ; End of print_hex.
+
+charcpy:
+ ldx idx3 ; Get the string index.
+ sta strbuf, x ; Save it in the string buffer.
+ inc idx3 ; Increment the string index.
+ rtl ; End of charcpy.
+
+print_hi:
+ and #0 ; Reset A.
+ sta idx3 ; Clear the string index.
+ lda #'$' ; Print the hex delimiter.
+ jsl charcpy ;
+ lda.q idx0 ; Get the masked address.
+ ldx #$10 ; Set digit count to 16.
+ jsl print_hex ; Print the address.
+ lda.q hex_str ; Get the lower half of the string.
+ sta.q strbuf+1 ; Save it in the string buffer.
+ lda.q hex_str+8 ; Get the upper half of the string.
+ sta.q strbuf+9 ; Save it in the string buffer.
+ ldx #$11 ; Add 16 to the index.
+ stx idx3 ;
+ lda #':' ; Print a colon.
+ jsl charcpy ;
+ lda # ' ' ; Print a space.
+ jsl charcpy ;
+ rtl ; End of print_hi.
+
+print_lo:
+ lda #0 ; Reset A.
+ sta idx3 ; Clear the string index.
+pntlo_lp:
+ ldx #2 ; Set digit count to 2.
+ pha #1 ; Preserve the nibble offset.
+ jsl print_hex ; Print the low nibble offset.
+ lda.w (ptr3) ; Get the two digits.
+ jsl charcpy ; Copy the first digit.
+ lsr #8 ; Copy the next digit.
+ jsl charcpy ;
+ pla #1 ; Get the nibble offset back.
+ inc ; Increment the offset.
+ cmp #$10 ; Are we at the last offset?
+ bcs pntlo_end ; Yes, so we're done.
+pntlo_lp1:
+ pha #1 ; No, so preserve the nibble offset.
+ lda #' ' ; Add a space to the string buffer.
+ jsl charcpy ;
+ pla #1 ; Get the nibble offset back.
+ jmp pntlo_lp ; Keep looping.
+pntlo_end:
+ inx ; Increment the index by one.
+ lda #0 ; Null terminate the string buffer.
+ sta strbuf, x ;
+ tax ; Reset X.
+ lda.d #strbuf ; Print the string buffer.
+ jsl print_str ;
+ rtl ; End of print_lo.
+
+print_chunk:
+ ldx #0 ; Reset X.
+ phy #2 ; Preserve the screen buffer index.
+ txy ; Copy the byte index to it.
+pntchnk_lp:
+ and #0 ; Reset A.
+ ldx #2 ; Set the digit count to 2.
+ lda (idx0), y ; Get the byte at that address.
+ jsl print_hex ; Print the byte.
+ lda.w (ptr3) ; Get the two digits.
+ jsl charcpy ; Copy the first digit.
+ lsr #8 ; Copy the next digit.
+ jsl charcpy ;
+ iny ; Increment the byte index.
+ cpy #$10 ; Have we read 16 bytes?
+ beq pntchnk_end ; Yes, so we're done.
+ lda #' ' ; No, so add a soace to the string buffer.
+ jsl charcpy ;
+ jmp pntchnk_lp ; Keep looping.
+pntchnk_end:
+ ply #2 ; Get the screen buffer index back.
+ inx ; Increment the index by one.
+ and #0 ; Null terminate the string.
+ sta strbuf, x ;
+ tax ; Reset X.
+ sta idx3 ; Clear the string index.
+ rtl ; End of print_chunk.
+
+viewmem:
+ lda.q prg_cnt ; Get the program counter.
+ sta.q idx0 ; Save the address in the first index.
+ and #$F0 ; Clear the first four bits of the address.
+ sta idx0 ; Overwrite the first byte, with the masked byte.
+ lda #19 ; Move the cursor to the right, by 19 columns.
+ sta scr_col ;
+ jsl update_pos ;
+ jsl print_lo ; Print the low nibble offsets.
+ ldx #0 ; Reset X.
+ ldb #0 ; Reset B.
+ stb idx1 ; Reset the byte count.
+vmem_lp0:
+ lda #'\n' ; Print a newline.
+ jsl print_char ;
+ jsl print_hi ; Place the address in the string buffer.
+ jsl print_chunk ; Place the next 16 bytes in the string buffer.
+ lda.d #strbuf ; Print the string buffer.
+ jsl print_str ;
+ inc idx1 ; Increment the chunk count.
+ ldb idx1 ; Get the chunk count.
+ cpb #$10 ; Did we print 16 chunks?
+ beq vmem_end ; Yes, so we're done.
+ lda.q idx0 ; No, so get the address index.
+ clc ; Prepare for a non carrying add.
+ adc #$10 ; Add 16 to the address.
+ sta.q idx0 ; Put it back into the address.
+ and #0 ; Reset A.
+ jmp vmem_lp0 ; Keep looping.
+vmem_end:
+ lda #'\n' ; Print a newline.
+ jsl print_char ;
+ and #0 ; Reset A.
+ rts ; End of viewmem.
+
+
+list:
+ nop ;
+list_end:
+ rts ; End of list.
+asm:
+ nop ;
+asm_end:
+ rts ; End of asm.
+help:
+ nop ;
+help_end:
+ rts ; End of help.
+inst:
+ nop ;
+inst_end:
+ rts ; End of inst.
+run:
+ nop ;
+run_end:
+ rts ; End of run.
+set:
+ nop ;
+set_end:
+ rts ; End of set.