![]() 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 | ||||||||||||||||||||
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] Some more information on Basic commands:-
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 |
||||||||||||||||||||
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 PRINTs. |