Applesoft BASIC programs start at location $0801 in memory (usually). If you put a nonzero value at address $0800, though, you get an error when you try to run the program:
?SYNTAX ERROR IN 65124
Why does this happen?
Applesoft BASIC programs start at location $0801 in memory (usually). If you put a nonzero value at address $0800, though, you get an error when you try to run the program:
?SYNTAX ERROR IN 65124
Why does this happen?
The Applesoft RUN command ($d912) begins by calling SETPTRS ($d665), which calls STXTPT ($d697) to initialize TXTPTR ($b8-b9) to the value in TXTTAB ($67-68) minus one. In simple terms, parsing of the program actually starts at $0800 when the program is loaded at $0801.
When the RUN command finishes, Applesoft falls back into its command execution loop NEWSTT ($d7d2), which had just finished calling EXECUTE_STATEMENT from $d820. When it jumps back to the top of the loop, it pulls the next byte from memory and evaluates it.
Normally, at the start of the program, it will read a zero, which causes it to behave as if it had reached the end of a line, and it will start processing the line. If it doesn't see a zero, it acts like it's in the middle of processing a line, and looks for a colon (':'). If it doesn't see that, it reports a syntax error (jump from SYNERR_1 at $d846), because statements must be separated by a colon or line break.
Setting $0800 to $3a (':') doesn't generally work, because Applesoft will think it's mid-line, but the next things it finds in memory at $0801 are a 16-bit next-line address followed by a 16-bit line number. These are unlikely to form a valid Applesoft statement.
The syntax error message uses the contents of CURLIN ($75-76), which was partially initialized: CURLIN+1 ($76) is set to $ff in "command" mode, and RUN decrements it to $fe to indicate that we're in "run" mode. The line number reported will thus be somewhere in the range $fe00-feff (65024-65279).
See also the Applesoft disassembly.
TXTTAB points to the start of the program code, which is technically $0801, since the $00 is an end-of-line indicator, not a start-of-line indicator. This situation is an artifact of keeping the interpreter design simple: when it finishes with the RUN command it wants to find a statement separator, and relies on the coldstart code to have put one there (see $f1b0). No need to waste space for that byte on tape/disk since it's supposed to have been taken care of already. (DOS/ProDOS LOAD really ought to zero it out though.)
– fadden
Jun 21 '21 at 18:56
nextline: LDX ,X / BEQ notfound / search: CMP A,2,X / BNE nextline / CMP B,3,X / BNE nextline / .... (I don't know if this is exactly how they did it, but you get the idea.)
– cjs
Jun 06 '22 at 07:25
LDA line_msb/ bra testH / lp1: ldb ,x / beq oops / abx / testH: cmpa 2,X / bne lp1 / lda line_lsb / bra testL/ lp2: ldb ,x / beq oops / abx / testL: cmp 1,x / bne lp2 which I think would work out pretty well.
– supercat
Jun 06 '22 at 15:16
abx instruction. That's not the 6800. :-)
– cjs
Jun 10 '22 at 05:31
ld e,(hl)/inc e/dec hl/cmp (hl)/add hl,de/jp c,loop. Then code would need to see if (hl) is one greater than A, exit if not, and otherwise search for the LSB with a similar loop, and then recheck the MSB once it was done. I think that's faster than any approach using two-byte line links.
– supercat
Jun 10 '22 at 15:33
LDX ,X instruction of the 6800, but emulating that is only a few instructions long: MOV D,M; INX H; MOV C,M; XCHG.
– cjs
Jun 10 '22 at 15:51
ld e,(hl) / inc (or dec) E / add hl,de.
– supercat
Jun 10 '22 at 16:09