When you power up a Commodore 64 you are greeted with a friendly message telling the user it has
38911 BASIC bytes free. 38,911 is one byte shy of a 38 KiB (1,024 * 38 = 38,912).
What was the reason for this "missing" byte?
Well, it's a 'trick' to simplify the editor as well as the BASIC editor. After Reset (or
NEW) three bytes of Zero are placed at the beginning of the basic RAM. They make it look to the basic interpreter as this looks like the tokenisation of a single, empty BASIC line. Consisting of
00as line end marker and
00as pointer to the next BASIC line - zero means end of program
(For more details check here)
To display the amount of free memory the startup code then uses the FRE function (*1), which in turn walks through BASIC memory ($0800..$9FFF) to see what's unused. Its logic counts the byte at $0800 as part of the current program, as it's the last byte of the line stored here (*2).
So basically a Commodore with no program holds a NULL-program :))
As weird as this seems, it saved the addition (and management) of another zero page pointer, thus simplifying the Interpreter (*3) by allowing all parts to assume that there's always a valid program loaded.
*1 - The displayed value is also corrected for values greater than 32767 which would seem negative.
*2 - Now, why the two bytes Zero aren't counted as well is weird, as they are always present as well. The whole issue can as well be seen as the usual +/-1 Error programs often show.
*3 - At least when intending to keep the advantage of not having to manage the various variable pointers (
STREND) during edit (they just get reset by
Plus the side effect to be able to reserve space between the program end and variables for additional machine code, allowing tricks to load it from tape in one turn.
The begin of the basic area is set in the addresses 43/44, the default value is 01 and 08, which means a start address of $0801 = 2049. The end of the basic area is in addresses 55/56, default values are 160 and 0, meaning $A000 = 40960. 40960 minus 2049 is 38911, the value that is also reported at the startup screen.
The byte before the basic area must contain a value of 0 so that the BASIC program can be run, that is why 2048 is used for that and BASIC starts at 2049 (2047 could not be used as the zero-holder, since it is already in use as a sprite costume pointer). Entering RUN when the byte before the BASIC area is not zero results in a SYNTAX ERROR message, because the RUN command sets the current character pointer (addresses 122/123) to the start of the BASIC area minus one. The basic interpreter then sees a zero, which tells it that a new line starts here.