115-138
The address range 115–138 (or $73–$8A in hexadecimal) holds a machine language subroutine that plays a central role for the BASIC interpreter built into the C-64: It reads either the current or the next character or token in the BASIC program, skips any excess spaces, and sets or clears the carry flag depending on whether the character read is a numerical digit ("0" thru "9") or not. It also sets or clears the zero flag depending on whether the end of statement (either a colon or the end of line) has been reached:
Address | Machine code |
Assembler | Comments | ||
Dec | Hex | Labels | Code | ||
115 | 73 | E6 7A | CHRGET | INC TXTPTR | Increase the two-byte pointer at label TXTPTR (122–123/$7A–$7B) by one. |
117 | 75 | D0 02 | BNE CHRGOT | ||
119 | 77 | E6 7B | INC TXTPTR+1 | ||
121 | 79 | AD ... | CHRGOT | LDA ... | LDA in absolute mode, with the argument given below |
122 | 7A | 60 EA | TXTPTR | .WORD 60000 | Pointer to current character in the BASIC text |
124 | 7C | C9 3A | CMP #":" | Leave the routine through label QUIT with the carry set, if the PETSCII code read equals or exceeds 58 (the code for "colon", following the codes for "9") | |
126 | 7E | B0 0A | BCS QUIT | ||
128 | 80 | C9 20 | CMP #" " | If the character read was a space then skip it and go back and read the next character | |
130 | 82 | B0 0A | BEQ CHRGET | ||
132 | 84 | 38 | SEC | Together these two subtractions leave the character held in the accumulator unchanged, while the last of them sets the carry if the character's PETSCII code is less than that of the digit "0" | |
133 | 85 | E9 30 | SBC #"0" | ||
135 | 87 | 38 | SEC | ||
136 | 88 | E9 D0 | SBC #256-"0" | ||
138 | 8A | 60 | QUIT | RTS | Return from this subroutine |
Being a fundamental example of self-modifying code, this routine needs to be in RAM which can be modified, as opposed to ROM: Inside this routine is a pointer (at 122–123/$7A–$7B) which is made part of the LDA absolute instruction which reads a character from the BASIC text – in effect implementing the non-existant "LDA indirect".
ROM details[edit | edit source]
During cold start, i.e. after power-up or a reset, the system runs through a short loop at 58336–58345/$E3E0–$E3E9, which copies the routine above (along with the initial "seed" value for the RND BASIC function) from a ROM image held at 58274–58297/$E3A2–$E3BE. In this ROM image, the two bytes that end up in the pointer at 122–123 point to the "arbitrary" address of 60000/$EA60, although this address will always refer to the KERNAL in any situation where the BASIC is banked in.