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:


Why does this happen?


1 Answer 1


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.

  • I wonder why TXTTAB is set to point to the byte following the zero byte, rather than pointing at the zero byte itself? Does that allow other parts of the code to be simplified?
    – supercat
    Jun 21, 2021 at 18:00
  • 1
    @supercat 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, 2021 at 18:56
  • Saved BASIC programs have quite a bit of redundant information, such as line links (which, on the 6502 could have been reduced to one byte if they'd specified the length of input lines. Actually, if program lines and strings had been stored in reverse order, that would have made a lot of things more efficient on the 6502, since code to iterate through a string could simply output (stringPtr),y and decrement y until it hits zero, rather than having to check each index against the string length.
    – supercat
    Jun 21, 2021 at 19:25
  • @supercat Regarding re-use of 8080 and 6800 techniques in 6502 MS-BASIC, see this question and answer(s), which I created in part to give a place for further comments about this. (I keep seeing comments like yours scattered throughout RCSE.) Many of the design decisions that were poor on the 6502 worked very well on the 8080 and 6800, which had 16-bit index registers.
    – cjs
    Jun 6, 2022 at 7:21
  • The line links work especially well on the 6800; consider searching for a line number you have in the A and B registers, with X pointing to the start of a line. This is a very simple and efficient sequence along the lines of 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 6, 2022 at 7:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .