Sharp logo
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.

BASIC INTEGER INTERPRETER AND COMPILER

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


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)


Go to the top of this page      Get next page - part II      Home     

last updated September 24, 2003
SUC / UK: Malcolm ?