The disassembled code here is from
Commodore 64 ROM.
The comments and intermediate labels
are mine.
Together they are useful.
Placing this here as is for reference.
I found this exercise necessary when
implementing my hires extensions for C64
including a patch of this routine.
; C64 crunch is A57C-A612
; C64 tokens are A09E-A19D
crunch ; from C64 ROM
; INPUT: PETASCII of entered line is at buffer $0200, ending with #$00 null character
; OUTPUT: tokenizes in place entire line, ending line with #$00 null character
; HINT: because of tokens, result is smaller than original so can modify in place
LDX $7A ; source buffer index
LDY #$04 ; storage index starts at 4 (4+$1FB+1 = $200)
STY $0F ; set not DATA flag (4=NOT, 0=DATA)
.go LDA $0200,X ; retrieve next character from input buffer
BPL .lowch ; branch if 00-7F
CMP #$FF ; PI?
BEQ .store ; branch if PI, already tokenized
INX ; advance source index
BNE .go ; always skip initial character 80-FE, as X shouldn't ever wrap to 0
.lowch CMP #$20 ; compare to ASCII space
BEQ .store ; branch if space, store literal
STA $08 ; no, store character, non-zero = not REMark
CMP #$22 ; compare to ASCII quote
BEQ .literal ; branch if string, store literal characters instead of matchng tokens
BIT $0F ; test if in DATA statement
BVS .store ; branch if in DATA statement, store literal characters instead of matching tokens
CMP #$3F ; compare to ASCII question mark
BNE .chkzero ; no, skip next part
LDA #$99 ; replace question mark with token PRINT
BNE .store ; unconditional branch, store token
.chkzero CMP #$30 ; compare to ASCII zero digit
BCC .scantbl ; branch if less
CMP #$3C ; compare to ASCII less than
BCC .store ; branch if less, so branch if numeric or colon or semi-colon, store literal character
.scantbl STY $71 ; save storage offset index
LDY #$00 ; initialize token table byte index to zero
STY $0B ; initialize token number to zero
DEY ; cancel out the next increment for loop beginning with decrement
STX $7A ; save source index
DEX ; cancel out the next increment for loop beginning with decrement
.advance INY ; advance token table index
INX ; advance source index
.scanch LDA $0200,X ; retrieve character from buffer
SEC ; prepare for subtraction
SBC $A09E,Y ; compare to Commodore token table
BEQ .advance ; branch if character match, look for more matches
CMP #$80 ; end of token?
BNE .scannxt ; branch if not end of token, mismatch, so get ready to check next token
ORA $0B ; match! combine zero based token number with $80 high bit set for storage
.storaty LDY $71 ; retrive storage offset index
.store INX ; advance input index
INY ; advance output index
STA $01FB,Y ; store token or character
LDA $01FB,Y ; set Z flag if end of line
BEQ .endline ; branch if end of line, finish up
SEC ; prepare for subtraction
SBC #$3A ; subtract ASCII colon
BEQ .setf ; branch if colon
CMP #$49 ; DATA?
BNE .skipset ; skip setting flag if not DATA
.setf STA $0F ; $49 if DATA, or $00 if colon
.skipset SEC ; prepare for subtraction
SBC #$55 ; REM?
BNE .go ; branch if not REM to get next character
STA $08 ; store flag zero = REM
.litloop LDA $0200,X ; retrieve next character from input
BEQ .store ; branch if end of line
CMP $08 ; compare to token that got us in this loop (e.g. 0x22 quote), or 0x00 (REM)
BEQ .store ; branch if REMark end of line
.literal INY ; advance destination index
STA $01FB,Y ; store in buffer
INX ; advance source index
BNE .litloop ; repeat getting next character
.scannxt LDX $7A ; retrieve source index
INC $0B ; advance token number
.endtok INY ; advance destination index
LDA $A09D,Y ; retrieve character from token table
BPL .endtok ; loop until find end of token
LDA $A09E,Y ; retrieve next character from token table
BNE .scanch ; branch if not end of token table
LDA $0200,X ; re-retrieve character from input buffer
BPL .storaty ; branch if character 00-7F, should be if got here, no token match
.endline STA $01FD,Y ; store end of line nul character $00
DEC $7B ; update TXTPTR
LDA #$FF ; to point to
STA $7A ; $01FF
crunch_finish:
RTS ; done
This article is informative, well-written, and easy to follow, offering valuable insights for students managing academic deadlines. I appreciate its clear explanations and practical guidance. Students facing tight schedules may find Urgent Assignment Help useful for organizing their workload, understanding challenging topics, and improving their academic writing skills effectively.
ReplyDelete