Detokenising in 6502 machine code

From BeebWiki
Jump to: navigation, search

BBC BASIC programs are tokenised, that is, BASIC keywords are stored as one-byte values This results in programs which execute faster and are more compact. BASIC has code to detokenise program code when listing, but it is unwise to try to call it directly as it is in different locations in different versions, and also depends on workspace locations containing values that BASIC expects which will not be the case if trying to use the routines when BASIC is no the current language.

The following code, which must run in the I/O processor, will search for the token table in any version of BBC BASIC - even in non-6502 BASIC ROMs.

   \ Detokenise BASIC tokens
   \ =======================
   \ needs, eg tbase=&70:tptr=&72 if calling from BASIC
   \        eg tbase=&A8:tptr=&AA if calling as a *command
   \ ----------------------------------
   \ TokenInit - Find BASIC token table
   \ ----------------------------------
   \ On entry, BASIC ROM must be paged in
   \ On exit,  tbase=>Start of token table
   \           A,Y,tptr corrupted, X preserved
   LDY #0:STY tptr:LDA #&80:STA tptr+1    :\ tptr=>ROM start
   LDA #1:CLC:ADC tptr:STA tptr           :\ Inc. tptr
   LDA #0:TAY:ADC tptr+1:STA tptr+1
   LDA (tptr),Y:CMP #&80:BEQ TokInit2:DEY :\ Found &80
   INY:LDA (tptr),Y:CMP #ASC"A":BNE TokInitLp :\ Not "A"
   INY:LDA (tptr),Y:CMP #ASC"N":BNE TokInitLp :\ Not "AN"
   INY:LDA (tptr),Y:CMP #ASC"D":BNE TokInitLp :\ Not "AND"
   LDA tptr:STA tbase:LDA tptr+1:STA tbase+1
   \ -----------------------------
   \ PrToken - Print a BASIC token
   \ -----------------------------
   \ On entry, A=token byte
   \           BASIC ROM must be paged in
   \           tbase=>Start of token table, set by TokenInit
   \ On exit,  A,Y,tptr corrupted, X preserved
   PHA:LDA tbase:STA tptr           :\ Point to start token table
   LDA tbase+1:STA tptr+1
   LDY #&FF
   INY:LDA (tptr),Y:BPL TokPrLp2    :\ Loop until token byte found
   PLA:CMP (tptr),Y:BEQ TokPrFound  :\ Found matching token
   PHA:TYA:BNE TokPrStep            :\ Step to next token
   INY:LDA (tptr),Y:BPL TokPrLp3    :\ Find next token byte
   INY:TYA:SEC:ADC tptr:STA tptr    :\ Step past this token string
   LDA #0:ADC tptr+1:STA tptr+1
   BNE TokPrLp1                     :\ Loop to keep searching
   TYA:BEQ TokPrNxt:LDY #0          :\ Skip past leading token
   LDA (tptr),Y:BMI TokPrEnd        :\ Token byte, end
   CMP #32:BCC TokPrEnd:JSR OSWRCH  :\ Flag byte, end
   INY:BNE TokPrLp3                 :\ Loop back for next character

You can test the code with the following:

   CALL TokenInit
   FOR A%=&80 TO 255:PRINT ;A%;": ";:CALL TokenPrint:PRINT:NEXT

Note that the code requires the BASIC ROM to be paged in, and also needs to run in the I/O processor - where the ROMs are. This would normally be done in a *command utility with code such as the following:

   LDA &F4:PHA                      :\ Save current ROM
   LDA &24B:CMP #&FF:BEQ errNoBASIC :\ Get BASIC ROM, error if no BASIC
   AND #&127:JSR SelectROM          :\ Page in BASIC ROM
   JSR TokenInit
   JSR TokenPrint
   PLA                              :\ Restore previous ROM
   STA &F4:STA &FE30:RTS            :\ Page in ROM

This code has been tested with 6502 BASIC 1.00-4.00, 4.32, 4.40, 4.86, Z80 BASIC and PDP-11 BASIC.

See also

Jgharston 03:09, 22 November 2010 (UTC)