BASIC INTEGER INTERPRETER AND COMPILER
written by Malcolm ? / SUC/UK
Source: SUC-magazine December 1982, Volume 2, Number 3, pp. 42 - 46
|
BASIC INTEGER INTERPRETER AND COMPILER occupies 1200 - 33FF
/ 9800 - BB00
Cold Start 1200 and warm start 1202 ( or M:B from Internal Monitor )
Work space 3400 - 3FFF: text area from 4000, although this can be varied.

The Compiler can be loaded at the same time from 9800 if there is
no risk of overwriting memory. This product, whose source is completely
unknown but presumed to be Japanese, is less than perfect and could
have been abandoned through lack of interest. Yet it contains interesting
features and, given a certain amount of care and patience, its compiler
is capable of worthwhile savings, as will be shown below in a few short
examples. It remains for someone to attempt a little more ambitious
programming, say a text editor or a "VISICALC" which can be
loaded as a machine code program from 1200. Full details are given below.
Note that generous use of brackets to enclose expressions, and spaces
to separate words which must to converted to tokens is recommended:
otherwise text may not be interpreted correctly and the only way of
checking this is to use the monitor M:D memory dump.
Commands: |
RUN ( 20 ) |
LIST |
DELETE |
VLIST |
undef. |
NEW |
LOAD |
SAVE |
|
VERIFY |
APPEND |
SYSTEM |
LIMIT |
TEXT |
CLR |
undef. |
undef. |
Sharpmz's comment: These tokens start with RUN = $20, LIST = $21... and
all tokens are preceded by $80.
|
1. TOKENS 30 - 8F
|
|
30 |
40 |
50 |
60 |
70 |
80 |
-0
|
IF |
MON |
- |
- |
GET |
<= |
-1
|
THEN |
BYE (*) |
SPOKE |
- |
INKEY |
=< |
-2
|
FOR |
CALL |
CURH |
- |
MOD( |
>= |
-3
|
NEXT |
PUSH |
CURV |
- |
ABS( |
=> |
-4
|
REPEAT |
POP |
PLOT |
- |
SGN( |
= |
-5
|
UNTIL |
OUT |
LINE |
- |
RND( |
<> |
-6
|
ON |
CURSOR |
PUT@ |
- |
INP( |
< |
-7
|
GOTO |
POKE |
GET@ |
- |
ADRS( |
> |
-8
|
GOSUB |
STA$( |
PRMODE |
SPEEK( |
PEEK( |
OR |
-9
|
RETURN |
LINPUT |
BELL |
TIME |
INC( |
+ |
-A
|
REM |
- |
MUSIC |
- |
DEC( |
- |
-B
|
PRINT |
- |
TEMPO |
- |
USR( |
* |
-C
|
INPUT |
- |
SOUND |
- |
- |
/ |
-D
|
- |
- |
TIME= |
SEARCH$( |
- |
AND |
-E
|
STOP |
TO |
- |
CP$( |
- |
XOR |
-F
|
END |
STEP |
- |
CPI( |
- |
- |
Sharpmz's comments:
(*) COM in the downloadable file
All tokens are preceded by $80.
View the complete token list and the related
addresses of entry points.
|
2. General Points
|
( a ) no tokens for DATA or READ
( b ) must use IF ... GOTO line number and IF ...THEN expression
( c ) variable names can be one or two characters
( d ) Repeat key facility is normally operative
( e ) use $ to precede hex numbers
( f ) Integers only
|
3. Storage of Text from $4000
|
e.g.
1 A = 10 : B = 100 : C = 1234
2 PRINT A
4000
|
|
00
|
|
01
|
|
16
|
|
41
A
|
|
80
|
|
84
|
|
31
1
|
|
30
0
|
|
3A
|
|
42
B
|
|
80
|
|
84
|
|
31
1
|
|
30
0
|
|
30
0
|
|
3A
|
|
|
1
|
|
|
|
=
|
:
|
=
|
:
|
 |
4010
|
|
43
C
|
|
80
|
|
84
|
|
31
1
|
|
32
2
|
|
33
3
|
|
34
4
|
|
0D
|
|
00
|
|
02
|
|
05
|
|
80
|
|
3B
|
|
41
A
|
|
0D
|
|
FF
|
=
|
|
|
|
2
|
|
PRINT
|
|
|
Start of line: |
1st byte = 0, 2nd byte = line number, 3rd byte = number of bytes |
|
from the 1st up to 0D which marks end of Line. |
|
sharpmz's comment: The 1st & 2nd byte represent the line number
in the order low / high byte. |
End of text: |
marked by FF. |
This was observed by using Club Monitor ( CALL $CC00): return via G1202
|
4. INTERPRETER Commands Statements Functions
|
Normal |
|
|
|
|
|
|
RUN
|
NEW |
LOAD |
VERIFY |
SAVE |
LIST |
BYE |
APPEND |
MUSIC |
TEMPO |
IF..THEN |
IF..GOTO |
FOR..NEXT..STEP |
INPUT |
ON..GOTO |
ON..GOSUB |
RETURN |
REM |
POKE |
CALL |
ABS(X) |
SGN(X) |
PEEK(X) |
INP(X) |
STOP |
END |
USR(X) |
OUT X, Y |
CURSOR X, Y |
LIMIT |
REPEAT.......UNTIL |
AND OR XOR |
Different |
|
GET |
eg. A = GET awaits keypress, obtains ASCII code of
key |
INKEY |
eg. A = INKEY as GET but does not wait ( A = 0 ) |
RND(X) |
integer random number between 0 and X |
INC(A) |
eg. A = INC(A) |
does A = A + 1 but faster |
DEC(A)
|
|
does A = A - 1 |
ADRS(A)
|
eg. B = ADRS(A) gives decimal address of A in memory |
TIME
|
instead of TI$ |
MOD(X, Y)
|
eg. A = MOD(X, Y) gives X - Y * ( X / Y ) integer
division! |
PUSH X
|
put X on stack |
POP X
|
remove X from stack |
SOUND X
|
high note 255 < X < 32767 low note |
BELL
|
approximately 440 Hz tone |
PRMODE X
|
where X = 0, 1 or 2 for screen, printer or both |
LIST X,Y
|
from X to Y |
DELETE X, Y
|
from X to Y or DELETE Y |
VLIST
|
Lists variables and values |
TEXT nnnn
|
determines where source code is put: default $4000 |
CLR
|
initializes all variables |
MON
|
jumps to internal monitor |
CURH X
|
move cursor horizontally eg. CURH 20 : PRINT A |
CURV Y |
move cursor vertically |
STA$(address,string) |
|
10 STA$ ( $C000, "AABCDEFG“ )
20 POKE $C008, $0D
30 PRINT !$C001, ///
40 A = $C009 : STA$ ( A, "HIJKL" )
50 POKE A + 5, $0D : PRINT !A + 1, / |
Thus DATA and string arrays may be stored ( see PRINT
! below ) |
SPOKE X, Y, Z |
eg. # at top left of screen SPOKE 0, 0, 99
direct poke to screen using coordinates X, Y: display code Z
|
PLOT X, Y, Z
|
same as SET X, Y when Z = 1; RESET X, Y when Z = 0
does an "inverse“ point when Z = 2
|
LINE X1, Y1, X2, Y2, Z
|
line from ( X1, Y1 ) to ( X2, Y2 )
draws when Z = 1, deletes when Z = 0, inverts when Z = 2
Most effective for vertical and horizontal lines.
|
PUT@X1, Y1, X2, Y2, Z
|
where Z is a hexadecimal address.
Defines on the screen a rectangular block with top left vertex (
X1, Y1 ) and bottom
right vertex ( X2, Y2 ) which is filled with the characters stored
at addr Z onwards.
NB. Display codes!
|
GET@X1, Y1, X2, Y2, Z
|
opposite of PUT@
|
LINPUT A |
puts whole line of input from keyboard into memory starting at
A.
10 A = $8000 : D = $10 : CR = $0D : SP = $20
15 FOR I = A TO A + $A0 : POKE I, SP : NEXT
20 PRINT “INPUT 10 STRINGS“ / : FOR I = 1 TO 10
30 PRINT %3 I, “. " / : LINPUT A
40 A = A + D : POKE A - 1, CR : PRINT / : NEXT
|
SPEEK X, Y
|
looks at screen coordinates ( X, Y ): screen peek.
|
CP$(address 1, address 2, ch)
|
where ch is a character.
eg. X = CP$( $8000, $8100, "A") searches for character
A
if found, X = 1, otherwise X = 0
|
CPI( ) |
no details discovered how to use this.
Sharpmz's comment: See the next article
for more details. |
PRINT
|
prints number / string without carriage return. |
/
|
use / for a carriage return, // for two.
to separate numbers PRINT A, /, B, / or PRINT /A, /B, /
to separate strings PRINT “ABCD" / "EFGH" / |
%
|
%n creates a field of n digits for all numbers: to be effective
n must
be greater than the number of digits in the number to be printed.
eg. PRINT %6 A, %8 B, C, %2 D
use PRINT %0 to cancel previous setting. |
#
|
conversion to hexadecimal. eg. if A = 1200
PRINT #2 A gives B0 ( least significant byte only ).
PRINT #4 A gives 04B0 |
&
|
used instead of CHR$( ). eg. PRINT &102 where 102 is
decimal
or PRINT &$70 where $70 is the same hex value. |
! |
for printing stored strings / messages / data.
eg. PRINT ! $C000 where the data which starts at $C000 must
be terminated by $0D |
SYSTEM |
a command to lookup TEXT START, TEXT END, END MEMORY. |
MON calls Monitor mode. |
M:E
|
Editor ( not available? ), all CR return to M:
Sharpmz's comment: See the next article
for more details. |
M:S
|
saves machine code object code generated by compiler.
FILENAME: ?
START: ?
END: ?
AUTO: ? then RECORD / PLAY |
M:Dxxxx
|
( default 1200 ) displays contents of memory, 8 addresses per
line, with
ASCII characters: very fast ( Mach V on 4 MHz ) until interrupted
by SHIFT BREAK. |
M:B
|
return to interpreter ( program not destroyed i.e. J1202 ) |
M:Jxxxx |
eg. JC000 for machine code program at C000 |
|
5. Normal Usage LOAD Interpreter from Sharp Monitor.
|
|
BYE exit
LOAD compiler from Sharp Monitor
Carriage return as Compiler not needed yet.
M:B return to Interpreter. READY. |
e.g. 1 |
|
10 A = $8000 : D = $10 : CR = $0D : SP = $20
15 FOR I = A TO A + $A0 : POKE I, SP : NEXT
20 PRINT “INPUT 10 STRINGS"/
30 FOR I = 1 TO 10
40 PRINT %3I, ". " : J = 0
50 REPEAT
60 K = GET
65 IF K <> 102 THEN PRINT &K : POKE A + J, J - INC(J)
70 UNTIL K = 102
80 A = A + D : POKE A - 1, CR : PRINT /
90 NEXT : END
|
Arrays: the DIM statement does not exist: the user
must arrange storage of arrays. |
e.g. 2 |
Single dimension arrays DIM A(10)
10 A = $BB00 : REM your choice of address
20 FOR I = 0 T0 10
30 PRINT %3I, "? " : INPUT X
40 A(I) = X : NEXT
50 FOR I = 0 TO 10 : PRINT %8 A(I), / : NEXT
|
e.g. 3 |
DIM A(2, 2)
10 A = $BB00 : FOR I = 0 TO 2 : FOR J = 0 TO 2
20 PRINT “A(“ : PRINT %0 I, “,“, J, “)
= ?"
30 INPUT X : K = 3 * I + J : A(K) = X : NEXT : NEXT
40 FOR I = 0 T0 2 : PRINT / : FOR J = 0 TO 2
50 K = 3 * I + J : PRINT %6 A(K) : NEXT : NEXT
60 PRINT / : END
|
e.g. 4 |
Strings must have a fixed length, say 16: best stored using LINPUT
: DIM A$(/,)
10 A = $BB00 : L = 16 : N = 4 : P = A
20 PRINT “INPUT 5 STRINGS“/
30 FOR I = 0 TO N : LINPUT P : P = P + L : NEXT
40 PRINT “WHICH STRING (1 - 5)? “ : INPUT X
50 P = A + 16 * (X - 1) : PRINT ! P, / : END |
N.B. A(X) requires 2 bytes per character, this is
not suitable. |
|
6. BASIC INTEGER COMPILER 9800 - BB00
|
The compiler makes a transformation of a BASIC program into a machine
code program, which, depending on the original program, could run 25 times
faster. When the compiler has been loaded from the Sharp Monitor ( LOAD
), it becomes accessible:
|
(a) J9800 from the MONITOR ( see above )
(b) CALL $9800 from the Interpreter.
|
Exercise 1 Write a program to discover numbers between
1000 and 9999 equal to the sum of the fourth powers of the digits. |
|
10 FOR I = 1 TO 9 : FOR J = 0 TO 9 : FOR K = 0 TO 9 : FOR L =
0 TO 9
15 M = 1000 * I + 100 * J + 10 * K + L
20 N= I * I * I * I + J * J * J * J + K * K * K * K + L * L * L
* L
30 IF M = N THEN PRINT/N
40 NEXT : NEXT : NEXT : NEXT : END
|
RUN produces 1634, 8208 and 9474 in 1 min.
24 secs.
SYSTEM 4000 - 40AF
CALL $9800 call the compiler. |
SOURCE ADR: |
$4000 |
must use $ else assumed decimal. |
OBJECT ADR: |
$8000
|
|
WORKING AREA: |
$3400 |
then Pass 1 and Pass 2 at lightning speed! |
Compiles in 3 secs approx. Object size 301 ( $8000 - $812C )
Lists line number and addresses of code. Also variables $812D - $813F
Returns to Monitor M:
J8000 to test machine code version: takes 12 seconds !!
Then automatic return to compiler.
N.B. Source should compile to same size, irrespective of number of line
numbers ( eg. if no multiple statements ).
To save final version, return to compiler: J9800
SOURCE ADR:
|
$4000 |
|
OBJECT ADR:
|
$1E00 |
|
WORKING AREA: |
$3400 |
Object code 1E00 - 1F2C |
M:S
|
Filename: |
Test 1 |
|
|
Start:
|
1200 |
|
|
End:
|
1F41 |
or 1F2C |
|
Auto:
|
1200 |
saves on tape and returns to M: |
N.B. should include CALL 0 at end of your BASIC program?
Sharpmz's comment: See the next article
for more details. |
Exercise 2 Write a program to discover all perfect
numbers ( those equal to the sum of their factors ) up to 1000 (
or higher? ). |
|
10 FOR I = 4 TO 1000 : N = 1 : K = I / 2
20 FOR J = 2 TO K
30 IF MOD(I, J) = 0 THEN N = N + J
40 NEXT : IF N = I THEN PRINT /I
50 NEXT : A = GET : CALL 0 : END
|
RUN produces 6, 28, 496 in 7 min. 28 secs.
Compiled version: 139 bytes ( $8000 - $808A ) takes 1 min. 38 secs.
Alternative program: |
|
10 FOR I = 4 TO 1000 : N = 1: K= I / 2 : J = 2
20 REPEAT
30 IF MOD(I, J) = 0 THEN N = N + J
40 J = INC(J)
50 UNTIL J > K
60 IF N = I THEN PRINT /I
70 NEXT : A = GET : CALL 0 |
Exercise 3 Write a program to discover prime Pythagorean triples. |
|
10 S = $8000 : S(1) = 12 : I = 3 : J = 4 : K = 5 : N = 1
15 IF K > 8 * I GOTO 110
20 X = I * I - (K + J) * (K - J)
30 IF X > 0 THEN K = K + 1 : GOTO 15
40 IF X < 0 THEN J = J + 1 : GOTO 20
50 P = I + J + K : L = 1: FL = 1
60 REPEAT
70 IF MOD(P, S(L)) = 0 THEN FL = 0
80 L = L + 1
90 UNTIL (FL < 1) OR (L > N)
100 IF FL > 0 THEN N = N + 1 : S(N) = P : PRINT%8I, J, K, P,
/
110 I = I + 1 : J = I + 1 : K = J + 1 : GOTO 20 |
Object size 358 ( $C000 - $C165) |
|