Sharp logo
BASIC COMPILER REVIEW 
written by Alan Rowley, David Loverseed, Maurice Hawes / SUC/UK
Source: SUC-magazine June 1983, Volume 3, Number 2, pp. 18 - 19 
Interpreter


Begins at 1200H with a table of vectors, up to 12A1H. From 1254H onwards the vectors are set to C3 00 00, which indicates the unfinished nature of the interpreter, but has the advantage that it represents a lot of spare room! 12A2H is the “PRMODE“ buffer. The monitor routine is at 1695H, and the user handler is at 1850H.

A cold start ( 1200H ) is vectored straight to 13DBH, where it zeroes the PRMODE flag, sets the TWO stack pointers ( 10F0H and 1DFEH ), and then jumps to 1E00H. The cold start at $1E00 is a vector to $253D, which is where the second half of the COLD START routine begins. It prints out the Message and then sets TEXT ( at $198C ) to $4000, and LIMIT ( at $1996 ) to $C000. Obviously these are the default values; TEXT is already documented in the Dec ‘82 Magazine, but LIMIT at $C000 is not, and gives me the impression that the writer intended that message strings should be stored here. This approach certainly helps when preparing a program for compilation, as it leaves the space between the top of the program and $9800 unbroken and therefore available for testing.

1DFEH is the top of the “BASIC“ stack and is used for the Basic PUSH and POP commands. 1203H is the warm start address, and 1206H takes you to the monitor.

The whole of the code from 1200H to 1DFFH is a run-time package for compiled programs. Thus, the final tested version of any program is meant to be compiled at 1E00H, saved from 1200H, and executed there; and it will contain the monitor program. There is no need to put CALL 0 nor anything else at the end of a Basic program ( not even an END statement ); the compiler puts a final C3 06 12 at the end of every program and that takes you back to the WICS monitor.

The PRMODE flag, once set, is picked up not only by Basic, but also by the WICS monitor and by the compiler, if present. This is very useful when compiling; if you go into the compiler in PRMODE2 you get a complete printout of the 1st and 2nd passes. It could also be useful with the “D“ command of the monitor, but as it stands the printer routine passes control codes from ASCII equivalents and this causes odd line feeds etc. If you want to use this facility you should rewrite the printer routine to suppress codes below 20H.

The Monitor E command works as follows:-

M:E[CR]
$XXXX ( to write new code from $XXXX ) [CR]
Spaces are inserted automatically, [CR] allows correction, and “;“ returns you to M:
Use cursor keys to edit previously listed code, with [CR] on each line modified.

Some more information on Basic commands:-

LIST X, Y either X or Y may be omitted; LIST, for continuous listing. Listing of program and the monitor dump can be stopped by holding down the SPACE key. Release to restart.
DELETE requires that the start and end lines are both specified. DELETE100, is not allowed.
LINPUT stores input as a line of either 41 or 81 characters INCLUDING A FINAL 0DH. Unused spaces are filled up with 0D‘s. If more than 80 characters are typed in, the first 80 are lost.
INKEY this repeats.
GET gives a flashing cursor but does not echo the input; does not repeat
LIMIT the value of the LIMIT must be specified. LIMIT MAX sets the top of memory to zero.
STEP negative STEP causes a data error on the interpreter - is accepted at compile time, but on execution of the object code only one cycle through the loop occurs.
X = CP$($XXXX, $YYYY, "A")   COMPARES the two strings beginning at $XXXX and $YYYY up to the character "A" in the first string. X = 1 ( equal ), X = 0 ( not )
X = CPI($XXXX, “ABCDE“) looks for the string “ABCDE“ at $XXXX. X = 1 if there, X = 0 if not.
X = SEARCH$($XXXX, “A“) looks for the character "A" from $XXXX upwards and puts X = the address of the first occurrence in decimal. The character specified in CP$( and SEARCH$( may be in HEX form without the inverted commas, eg. X = CP$($7500, $8000, $41) or X = SEARCH$($7500, $0D). The code for SEARCH$( includes an unwanted INC HL. A “00“ poked in 17FD will put this right.

PRINTER ERROR in an object program returns control into the nether regions usually resulting in a crash. POKE $1A22, $82 : POKE $1A23, $00 before compiling, and the printer error returns to the SP1002 warm start.

There seems to be a spare byte to insert the ‘E‘ missing from ‘VRIFYING‘. POKE the following ( all hex ) into locations $231E to $2327: 56, 45, 52, 49, 46, 59, 49, 4E, 47, 20.

There is no overflow checking on number sizes so anything bigger than 2 bytes gets corrupted and the carry is lost without any error message being sent. This also applies to line numbers if you are clumsy enough to exceed the limit.

PRINT!, ADRS(, and SEARCH$( will not compile. I have therefore written a substitute for PRINT! at $1254 which works as follows:-

R = $XXXX : PUSH R : CALL $1254 : POP R

will print out the string at $XXXX up to the first 0DH.

TIME returns time in seconds but it must be initialized, eg. by TIME = 0 before it is read, otherwise an attempt to read it results in a crash. Also, if TIME overflows, the two byte integer limit produces the negative complement value and consequent rubbish.

There is also something weird about variable names; not sure what precise problem is but I used ULP as a name and it gave a crash on the interpreter; also problems if there are keywords in variable names, eg. ORG gets tokenized and produces syntax error at run time. In fact the interpreter seems to be eager to tokenize anything even REM contents.

Compiler


There do not seem to be any snags with the COMPILER except for the fact that it won‘t compile PRINT! ( I suspect that ADRS( and SEARCH$( were not meant to be compilable - the compiler prints out all the addresses of the variables anyway, and the programmer needs to keep a record of where strings are stored in any case ).

After finishing a successful compilation, it leaves PRINT% set to PRINT%5. Therefore, if you run a compiled program immediately after compilation, PRINT%5 will be in force until the program decrees otherwise. A saved version of the program will not be affected, but the easy way round this one is to get in the habit of including PRINT%0 as part of your standard initializing routine for all programs.

Code produced will sometimes not run on the MZ80A, depending on which routines are called. To overcome this, POKE $50 into locations $18D6 and $1952 immediately before calling M:S to save. This will freeze the cursor on the MZ80K; POKE $8F back to restore afterwards. Again, if writing code for the MZ80A, ensure that variables are defined as zero before use, otherwise they could start off as 255.

If the object generated for location at $1E00 overwrites the text, this is shown up by the compiler producing spurious ‘UNDEFINED LINE NO‘ errors. The answer of course is simply to relocate the text higher up by changing TEXT before reloading but it is alarming at first. Also a bit of a juggling act to avoid overwriting compiler. Major problem is not surprisingly with programs with lots of PRINT‘s.


Go to the top of this page      Back to page part I      Get next page - part III      Home     

last updated September 24, 2003
SUC / UK: Alan Rowley, David Loverseed, Maurice Hawes