105. GOTO/GOSUB line tokens
~~~~~~~~~~~~~~~~~~~~~~
If you examine the structure of a BASIC program listing in memory, you will
see that the line numbers are stored as two bytes; low followed by high. The
low byte is given by linenumber MOD 256, and the high byte is given by
linenumber DIV 256. However, the line numbers following a GOSUB, GOTO, or
implied GOTO, (ie IF A=5 THEN 550), are tokenised in a weird way. They are
stored as 4 bytes; the first byte always being &8D to indicate that a line
number follows in the next three bytes, which I shall call b1, b2 and b3.
To decode this, you must shift b1 up 2 bits, (the same as multiplying by 4 in
BASIC, or doing two ASL's in machine code), mask off the bottom 6 bits, (same
as ANDing it with &C0), then EOR it with b2, and this gives you the low byte
of the line number. Now shift the original b1 up 4 bits, mask off the bottom
6 bits, and EOR it with b3, which gives you the high byte.
Try running the program below, from line 200, (ie type GOTO200 rather than
RUN), enter A4,68,43 (separate with commas; no need to prefix with '&'), and
you should get "line 1000". Note how the Hex numbers are entered as strings,
and turned into numeric variables with EVAL; you can't do it directly.
Encoding the line numbers is a bit more hairy; the first part of the program
below demonstrates this, and you can enter the results into the second part,
to confirm that the encoding works OK.
100 REM Encode tokenised line numbers.
110 INPUT"Enter Decimal Line No.... "line%
120 lobyt%=line%MOD256:hibyt%=line%DIV256
130 b2%=&40+(lobyt%AND&3F):b3%=&40+(hibyt%AND&3F)
140 lobyt%=(lobyt%AND&C0)DIV4:b1%=(&80+lobyt%)EOR&10
150 hibyt%=(hibyt%AND&C0)DIV16:b1%=(b1%+hibyt%)EOR4
160 PRINT~&8D,~b1%,~b2%,~b3%
170 :
200 REM Decode tokenised line numbers.
210 INPUT"Enter three Hex bytes.... 8D,"b1$,b2$,b3$
220 b1%=EVAL("&"+b1$):b2%=EVAL("&"+b2$):b3%=EVAL("&"+b3$)
230 lobyt%=((b1%*4)AND&C0)EORb2%:hibyt%=((b1%*16)AND&C0)EORb3%
240 PRINT"Line Number = ";hibyt%*256+lobyt%