Last Update: 16 January 1997
(Minor modifications to URLs etc by Rowan Crowe)
MoonRock is a BASIC-like language with several extensions. Produces small and tight executables. Includes compiler, ArrowSoft assembler, documentation and sample programs. Continuing development by the author - Rowan Crowe rowanWEB@sensation.net.au
-- This version is FREEWARE --
[MoonRock Docs] [Example code] [Downloads] [Credits]
I originally began work on MoonRock because I was dissatisfied with the bloated executables that QuickBASIC and other MicroSoft BASICs produce. Before I moved to the PC world in 1992, I had been coding in 6502 ASM on a machine with typically less than 32k RAM, so I could certainly appreciate the need for tight code. My only other language was BASIC. This particular machine (BBC Model B 6502 2MHz 32K RAM) had an assembler embedded into the BASIC interpreter, which allowed me to freely mix both languages.
As I gradually moved over to 80x86 assembly I became interested in how compilers converted high level source into low level ASM or machine code. I thought I would give it a try myself. When I originally started MoonRock, I had little experience: I had never written or designed a compiler, and did not know many fundamental techniques. I had plenty of ideas. I made several mistakes along the way, some that affect the direction the compiler has taken, but I've certainly learnt a lot, too.
MoonRock has now been in development for over 15 months (the oldest archive I have is dated 1st-Nov-1994). Over that time it has grown significantly, both in power and internal complexity.
Currently there is only a single person (myself) involved in the development of MoonRock, and it is done in my spare time.
Now for some more detail about MoonRock: the compiler translates a BASIC-like source file into assembler source (ASM). This is then assembled with an assembler such as MASM, TASM, A86, or ArrowSoft, then finally linked to produce an executable (either COM or EXE). Each ASM produced by MoonRock is entirely standalone and does not need to be linked with external libraries: one of the oddities of the compiler is that the library functions are *included* in the output ASM file. This is not as silly as it sounds, because it means that the code for the library functions can change dynamically from compile to compile, depending on which switches or directives are used. For example, if 386+ code generation is specified, then several of the string handling libraries use MOVSD (move doubleword, 386+) instead of MOVSW.
MoonRock's code generation is of average to good quality. It uses register based parameter passing to most internal functions and procedures. Simple functions (such as ABS) are performed "inline" so as not to add the overhead of calling a function. The compiler provides simple optimisations such as not saving a register to a memory address and then reloading it straight back (MicroSoft BASICs are guilty of not doing this blatantly obvious optimisation).
The library functions themselves are, in their "release" form, as tight as possible. When the debug switch is specified with the compiler, extra hand-holding code is included into the functions to catch potential errors. Thus, for debugging one can include the necessary hand-holding, but a release compile will be free of the extra size and loss of speed. The included ASM library contains 5,000+ lines of ASM.
Startup code is small. A program to print "Hello World" is 220 bytes (compiled with MRC v0.15.b4 with switch "/-C"). The startup and cleanup code also changes dynamically depending on commandline switches.
Generally MoonRock executables will be compiled for smallest size.
Briefly, these are the features and limits of MoonRock:
print "Hello world\n\n"
print "Hello world" + chr$(13) + chr$(10) + chr$(13) + chr$(10)
a% = ((c% - 2) * d%) + 5
The evaluation must be done separately thus:
temp1% = c% - 2 temp2% = temp1% * d% a% = temp2% + 5
So much for the current version. A newer version is being developed, this time in "native" MoonRock. It is far more powerful, for example you can throw it this expression:
a% = c% * (5 + 3) - ((2 - d% + (e% * 3) * 5) + (c% * 2) + (e% - 2) - 3)
... and it evaluates the brackets in the correct order.
It supports FUNCTIONs.
It has generally better code creation, and a post-optimiser which makes use of available registers, to speed evaluation in the compiled executable.
It is more reliable at catching compile-time (source code) errors.
It is much a much faster compiler, and is smaller (due to it being compiled by MoonRock).
Basically (no pun intended), the newer version blows the old one out of the water, and makes it look rather primitive. There are some minor changes to the language elements, but I'll be including a convertor. Some of the changes are already present in the current version of MoonRock (for example, in the current version you can use either END SUB or RETURN to mark the end of a subroutine block; in the newer version RETURN will be used for something else).
The newer version is still under development, and will not be released for several months, although Beta versions will be released before then.
Finally, here is a simple MoonRock program which shows a listing of the specified files. I have modified it slightly to make it more readable.
Write to Rowan or visit his web site and tell him to hurry up with this new version.
' FF.MOO by Rowan Crowe ' Demonstrates FINDFIRST/FINDNEXT functions. ' Displays a simple directory listing. ' Last modified 05-Jan-1996 BEGIN DEF #INCLUDE ffblk.h STRSEGSIZE 5k ' We only need a small string seg for this. BEGIN CODE cmd$ = CMDLINE ' get commandline cmd$ = LTRIM(cmd$) ' trim leading spaces cmd$ = UCASE(cmd$) ' convert to uppercase IF cmd$ <> "" THEN PRINT " Filespec = '" + cmd$ + "'\n\n" b$ = FINDFIRST (cmd$, 7) WHILE b$ <> "" fcount% = fcount% + 1 b$ = LCASE(b$) + SPACE(12) PRINT LEFT(b$, 12) + " " b$ = FINDNEXT WEND IF fcount% > 0 THEN PRINT "\n\n" PRINT " " + fcount% + " file" IF fcount% <> 1 THEN PRINT "s" PRINT " found.\n" ELSE PRINT "Specify filespec in commandline.\n" ENDIF END
[Back to Example Code][TOP]
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ''' ''' ''' BOUNCE.MOO *** released to the public domain *** ''' ''' ''' ''' Originally by Rowan Crowe, Wednesday, 03-Jan-1996 ''' ''' 3:635/727.1@fidonet ''' ''' email@example.com.DIALix.oz.au ''' ''' ''' ''' Fairly cute but useless demonstration program bounces several ''' ''' independent "balls" around the screen area. ''' ''' ''' ''' %BallCount may be modified. Limits are 1 to about 8000 (!) balls. ''' ''' ''' ''' Requires MoonRock compiler: ''' ''' MRC bounce/-m/-c ''' ''' ''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' begin DEF %BallCount = 25 ' number of balls on screen dim x%[%BallCount] ' current ball x position dim y%[%BallCount] ' current ball y position dim dx%[%BallCount] ' direction to travel: -1, 0, 1 dim dy%[%BallCount] ' " " " " begin CODE $outstream _tty_str_direct randomize(0) colour ?,0 cls @mov ah, 01h @mov cx, 2000h @int 10h ' disable cursor. for i% = 0 to %BallCount x%[i%] = rand(7900) \ 100 ' scale 0-79 (nb: '\' = integer division) y%[i%] = rand(2300) \ 100 ' scale 0-23 dx%[i%] = 0 while dx%[i%] = 0 t% = rand(32000) - 16000 dx%[i%] = sgn(t%) ' -1, 0, +1 wend dy%[i%] = 0 while dy%[i%] = 0 t% = rand(32000) - 16000 dy%[i%] = sgn(t%) ' -1, 0, +1 wend next k% = -1 while k% = -1 c% = 7 for i% = 0 to %BallCount mcursor x%[i%],y%[i%] print " " ' clear last position x%[i%] = x%[i%] + dx%[i%] y%[i%] = y%[i%] + dy%[i%] mcursor x%[i%],y%[i%] colour c% c% = c% + 1 if c% = 8 then c% = 0 print "\h04" ' diamond "ball" if x%[i%] > 77 then t% = rand(5000) - 4000 if t% < 0 then dx%[i%] = 0 else dx%[i%] = -1 endif endif if x%[i%] < 1 then t% = rand(5000) - 4000 if t% < 0 then dx%[i%] = 0 else dx%[i%] = 1 endif endif if y%[i%] > 23 then t% = rand(5000) - 4000 if t% < 0 then dy%[i%] = 0 else dy%[i%] = -1 endif endif if y%[i%] < 1 then t% = rand(5000) - 4000 if t% < 0 then dy%[i%] = 0 else dy%[i%] = 1 endif endif next colour 14,1 mcursor 8,11 print " MoonRock demonstration program -- press any key to exit " colour ?,0 delay(1) k% = inkey wend if k% = 0 then k% = inkey ' eat up extended keypress colour 7,0 cls @mov ah, 01h @mov cx, 0607h @int 10h ' enable cursor end
[Back to Example Code][TOP]
|Simple command line parsing||CMD.ZIP|
|Direct screen write and colour functions||COLOUR.ZIP|
|Day, date and time functions||DAY.ZIP|
|FINDFIRST / FINDNEXT demo||FF.ZIP|
|Scrolling list demo||LISTF.ZIP|
|File locking demo||LOCK.ZIP|
|Lists messages in any fidonet-style PKTs in the current directory||PKTLIST.ZIP|
|Displays information on the current screen mode. Uses inline asm||SCRLEN.ZIP|
|Time a DOS command||TIMER.ZIP|
|DOS menuing system.||AM.ZIP|
|Recursive file includer||INCLUDE.ZIP|
This page was created by Bruce M. Axtens. The following programs have been used at various times to control the content of this page:
[TOP][Rowan's Home Page]