[net.micro.cbm] ABACUS Basic Compiler

rwh@aesat.UUCP (Russ Herman) (09/25/85)

                       Abacus BASIC 64 (BASIC Compiler)

                       Russell Herman (utzoo!aesat!rwh)
                                   (c) 1985

_I_n_t_r_o_d_u_c_t_i_o_n

I'd been considering getting a BASIC compiler for awhile. When Abacus came
through with a $10 off coupon after reducing the compiler's price to $39.95,
that was sufficient to toggle my 'purchase' line.

_I_n_i_t_i_a_l _I_m_p_r_e_s_s_i_o_n_s

As usual (I've bought by mail from them before), Abacus ships promptly, and
doesn't rip off Canadians by charging "foreign" postal rates. The package
consists of the usual Abacus binder and diskette. Checking over the
registration card and seeing the $10 fee for a backup copy (a bit high for a
$29.95 net product), I grab my trusty nibble copier and make my own. Uh-oh,
won't load. This one belongs in the "heavily protected" category.

Glancing at the title page, I notice that the copyright is held by Data Becker
GMBH. They're the German outfit that supplies the _Anatomy of ..._ books (and
others) that Abacus distributes in N.  America.

So the next thing to do is to boot up the program, and give it a try on one of
the simple programs I've written, an _I CHING_ tosser, which "tosses the coins"
and displays the two resulting hexagrams. Up comes the menu with a choice of
compiler 1, compiler 2, adv. devel. system, and overlay generator. Leafing
through the documentation, I see that the difference between compiler 1 and
compiler 2 is that the latter is, in effect, an integer BASIC for higher
efficiency. Well, that's just what I want. So I pump the program through the
compiler and ...
                               TYPE MISMATCH ...
Try to stop the thing when the error message pops up, but no, grind, grind,
grind, through all of pass 1 and pass 2. Finally I get back to a menu, and, NO
WAY to LIST the program. Sigh. Reset the machine. Look at the offending lines
                    FOR I=somethingTOsomethingSTEPsomething
nothing wrong with that.  Back to the manual. Aha! Here it is, mentioned in
passing. To improve efficiency in the integer compiler, STEP is disallowed. If
you need it, do the increment-and-test yourself. Oh, well. There goes the one
bit of structuredness that BASIC has. So after rewriting the two lines, reload
the compiler (another two minutes staring at the threat screen), turn on the ML
output toggle this time. Reset the machine, load the program (now 42 blocks
instead of 12), and voila!  an observable, but unmeasurable, speed improvement.
Whereas the BASIC version took a few hundred milliseconds to fill the screen,
now it appears to be blinking the entire screenful up instantaneously.  Thus
heartened, now off to read the manual.

_F_u_r_t_h_e_r _T_e_s_t_i_n_g

The manual is terse, but appears complete. It describes options of the advanced
development screen, and some REM@ toggles that allow setting some of the same
compiler features. You can raise the bottom and lower the top of your program,
declare variables as float for the integer BASIC compiler, access features of
some BASIC extensions (most of SIMON's, some of MASTER-64).  What they call
"overlays" is little more than one program loading another, although only
string variables get clobbered. The requirement that the first-loaded program
be the largest still carries on. You can move the location of the symbol table
(normally in the casette buffer). You can turn on the line-number/machine
address listing option, needed since runtime errors give a machine address
instead of a BASIC line number.  Symbol tables can be saved and reloaded for
use with the overlay feature, which gives the feature of separate compilation
units for each program.  A clever feature is the ability to force a symbol to
be an address so you can access the SID and VIC chips (or any location in
memory above 368) just by accessing a named variable.

I'm not going to use any of this interesting stuff just yet, though.  Going to
work on a REAL program this time: a disk T/S editor published by RUN Magazine
and slightly hacked to do a better job of handling disk errors and disk-chain
following.  Each sector is displayed in 2 128-byte screens that you just cursor
over to and change, and dumping out each screen takes 22 seconds, which seems
like forever. So make a few changes to get rid of some unnecessary INT calls,
compile and run, and now, *6* seconds per screen. Very nice.

One more to try, a version of a PD disassembler that has been adapted to take
code from disk or core, and write assembler input, source listing, or both.
This one has lots of INT statements for generating lo-byte, hi-byte address,
and an opcode table that is stored in an index*100+optype format. Make
appropriate changes, including generating a temp for inline INTs, compile, and
                               RUNTIME ERROR ...
How to debug this thing now. Well, there's no way to look around at anything of
compiled code once you're back in the interpreter. So it's insert PRINT
statements, recompile, insert more PRINT statements, more recompiling ... this
is pretty tedious. Finally I discover that a subroutine is being called with a
negative value that is being used as an index into MID$. But how is that value
being generated??? Only thing I can think of doing is coming up with a version
of the program where the BASIC source can be run directly, as well as compiled.
This means that whereas I was relying on the integer nature of the compiler,
now I've got to modify the program to use % variables. So I do this (a BASIC
xref program comes in REALLY handy here), verify under the interpreter, run a
compiled version, and NO MORE PROBLEM. So, somewhere, lurking in the compiler,
is at least one bug. Performance, by the way, is 30 seconds for a disassembly
that requires nearly 2 minutes in the interpreted version.

Now for the hairiest test of them all - a primitive terminal program.

Set up the menu parameters specified in the manual for RS-232 programs,
compile, and try it out at 300 baud.  Program hangs. Finally trace it down to
within the GET# reading the port. Well, here I'm stuck. No way to determine
what's going on inside.  In desperation, I give Abacus a call; they DO
advertise customer support for this product, and am quickly connected to
someone who see the info on a certain manual page. I do, and unfortunately, it
conflicts with the information on another manual page, but I'll try it anyway.
Finally, after trying a number of combinatorials of changing the compiler's top
of program, as well as FRETOP, MEMSIZ, and MEMTOP, it runs. No 1200 baud modem
to *really* test it with, though.

_C_o_n_c_l_u_s_i_o_n_s

Not perfect, but certainly a winner. For complex programs accessing disk and
doing extensive string manipulation, expect around 4X performance improvement.
This is, of course, for the integer-BASIC compiled version. What the gains
would be for programs making heavy use of floating point, trig functions, etc.
I don't know, but since the native BASIC ROM routines are invoked, I wouldn't
expect too much.

You'd better thoroughly debug an interpreted BASIC version of the program
before you compile it, or you're going to have a devil of a time trying to
figure out what went wrong with only the machine address equivalent of the
offending line as debugging info (table converting this to line number
optionally available from the compilation phase).  Documentation leaves
something to be desired, but what else is new.

The paranoia about protecting the compiler is annoying, as you have to reset
the machine to get out of it. Compiled code can't be CONTed after STOPping
either. On examination, the compiled code isn't very compiled: it's entirely a
string of parameter setups and calls to the (3K) runtime package. Reminds me a
mainframe COBOL I used to know. But the main thing is the achievement of very
significant performance gains from running compiled versions.
-- 
  ______			Russ Herman
 /      \			{allegra,ihnp4,linus,decvax}!utzoo!aesat!rwh
@( ?  ? )@			
 (  ||  )			The opinions above are strictly personal, and 
 ( \__/ )			do not reflect those of my employer (or even
  \____/			possibly myself an hour from now.)