http://www.xs4all.nl/~lennartb/firstforth.txt 

MY FIRST EXPERIENCES WITH FORTH.

This article is based on an article that I published in 1992 in the
Dutch Forth magazine "het Vijgeblad" (literally this means "fig leaf",
but "blad" also means "magazine"). And everyone knows that FIG means
"Forth Interest Group". This magazine was published by the HCC Forth
Interesse Groep.

I'd like to talk about my first experiences with Forth on the ZX
Spectrum.  Most people remember the venerable Sinclair ZX Spectrum as
a game machine. Although I did play some games on it every now and
then, the primary reason I had the spectrum was hobby programming, or
"hacking" in the positive sense. But let's start a few years earlier.

THE BEGINNING.

The first time I read about Forth was in the October 1983 issue of the
Dutch magazine "Radio Bulletin", which contained a review of the
Jupiter Ace computer. This machine looked a lot like the ZX81, but it
had Forth in its ROM instead of BASIC. Forth was fast and compact and
it offered structured programming.

In 1984 our family purchased a Texas Instruments TI 99/4A. Alas this
is not a very "hackable" machine, at least not if you are not a
hardware hacker and you cannot afford the extra add-ons like "Extended
Basic" or "Mini Memory". Though Forth did exist for that machine, it
was not within reach. Problem was, on the bare machine you could not
PEEK and POKE and basically there was no way you could enter and run
your own machine code programs. The hardware contained all kinds of
interesting goodies, like sprites, that you couldn't access. At that
time I'd rather own a ZX81 on which you did have the opportunity to
hack with machine code.

In 1985 I started my study at the Eindhoven University of Technology
and though I was a poor student, I could afford the 299 guilders (say
150 dollars) that a 48k ZX Spectrum cost. I had to use an "antique"
black and white TV and cassette recorder. Though it was an inferior
machine hardware-wise and its BASIC was as slow, I could do a lot more
with it than with the TI. Spectrum BASIC had some pretty cool
features, like high resolution graphics, that TI and even the
Commodore 64 lacked. Apart from BASIC you could easily hack your way
with PEEK, POKE and machine code. "The Complete Spectrum ROM
Disassembly" was the best reference manual you could get.

At the end of 1986 I became a bit dissatisfied with the ZX
Spectrum. BASIC was way too slow for many purposes and Assembler was
so low-level. I couldn't afford Pascal at the moment (I did purchase
it later). Forth seemed the way to go. While at the university I did
read the occasional Forth book. the book "The Complete Forth" by Alan
Winfield got me hooked.  But how to get a Forth system? Well I _knew_
someone who had Aackosoft Forth and who could send me a copy, but I
even tried to buy it myself. But it turned out it was no longer
available. When I did get a copy I was glad I didn't spend good money
on it.

The editor was very stupid. It turned out that there could be one! 1k
block of Forth source in memory at a time and that you had to save and
load each source block separately on the cassette.  If you edited one
block of source, you had to save it back right at the place of the old
block on the tape. That was not the way I wanted to edit my source
code! The editor had to be loaded from tape too. Worst of all, you
couldn't simply save the image of your Forth system with some
precompiled extensions (the editor). After some time I did manage to
hack my way out of that, but by then I had already decided to roll my
own Forth.

WRITING MY OWN FORTH

Forthunately there were a lot of Forth books in the university
library, mostly related to FIG Forth. Aackosoft Forth itself was also
a FIG Forth and I had laid my hands on a book about Abersoft Forth, a
competing Forth for the Spectrum that stored 10 blocks into a RAM
disk that you could save as a whole. I definitely wanted a '79 Forth
as described by Winfield, a RAM disk and a full-screen editor. Some
other goodies I wanted: Full 32-bit number capability and a BREAK key
to stop an endless loop without having to load all the stuff again from
cassette.

At that time I pretty much knew what a Forth system looked like
internally and what made it tick, but I didn't know about
metacompiling (for which you need a working Forth to begin with).

Neither did I want to build the whole thing in assembler like the
Fig Forth listings. So I started to write the machine code primitives
in assembler. Below you see a small piece of the assembler source,
containing the inner interpreter itself (NEXT) and a few primitives.

Note that the address of the NEXT routine is kept in the IX
register. This Idea I got from "Threaded Interpretive Languages" by
Loeliger. BTW: Loeliger was a _real_ programmer. He managed to hack
his Forth together in a week without using any tools other than peek
and poke.

NEXT    LD      A,(BC)
        LD      L,A
        INC     BC
        LD      A,(BC)
        LD      H,A
        INC     BC
EXE     LD      E,(HL)
        INC     HL
        LD      D,(HL)
        EX      DE,HL
        JP      (HL)
EXECUTE POP HL
        JR      EXE
COLON   LD      HL,(RSP)
        DEC     HL
        LD      (HL),B
        DEC     HL
        LD      (HL),C
        LD      (RSP),HL
        INC     DE
        LD      B,D
        LD      C,E
        JP      (IX)
EXIT    LD      HL,(RSP)
        LD      C,(HL)
        INC     HL
        LD      B,(HL)
        INC     HL
        LD      (RSP),HL
        JP      (IX)

The assembler source compiled to a piece of machine code of around 1
kilobyte. It contained the code of all primitives, including double
precision multiplication and division. It contained no headers. When
this piece of code was assembled, I made a note of all the relevant
label addresses.

This Forth was located at a comparatively high address (9000h
IIRC). At the lower addresses there would be room for the BASIC
program that I describe next. When the Forth was finished, the same
space would be occupied by the RAM disk.

The rest of the Forth system was compiled using a BASIC program, which
was loaded and run in more parts. The BASIC program built up all the
headers. The first part compiled the headers for the primitives and
the variables and constants. Subsequent parts compiled the colon
definitions. The program contained a BASIC subroutine that would
search the Forth dictionary in memory just like the Forth system
would. Below you see this FIND routine. It needs the name in A$ and
returns the address in FA.

1090 LET FA=LK
1091 LET A=PEEK FA-128: IF A>=64 THEN LET A=A-64
1095 IF A=LEN A$ THEN FOR I=1 TO LEN A$: IF PEEK (FA+I)=CODE A$(I)
     THEN NEXT I: GO TO 1120
1100 LET FA=FA+A+1: LET FA=PEEK FA+256*PEEK (FA+1): IF FA=0 THEN
     PRINT "FOUT ";A$: GO TO 9000
1110 GO TO 1091
1120 LET FA=FA+A+3: RETURN

The compiler was indeed very primitive. It contained no words like IF
and BEGIN and you had to manually compute branch offsets. The Forth
words were contained in DATA lines, like this one.

3130 DATA "MEM", "LIT", "&L9005", "@", "DEPTH", "-", "DEPTH", "-",
     "HERE", "-", "LIT", "&L0080", "-", "EXIT", "?STACK", "DEPTH",
     "0<", "0BRANCH", "&B16", "(."")", "&SSTACK EMPTY", "ERROR",
     "MEM", "0<", "0BRANCH", "&B15", "(."")", "&SSTACK FULL",
     "ERROR", "EXIT"

In normal Forth these definitions would look like

: MEM ( --- size)     ( return amount of free memory)
  9005 @  DEPTH -  DEPTH -  HERE -  80 - ;
: ?STACK ( --- )      ( check the stack pointer)
  DEPTH 0<
  IF
   ." STACK EMPTY" ERROR
  THEN
  MEM 0<
  IF
   ." STACK FULL" ERROR
  THEN ;

Needless to say this BASIC program was SLOW!  Compilation of the
complete system took nearly one hour! Most bugs turned out to be
branch offsets. About half January 1987 I started and by the end of
February the whole thing was finished.

The Forth that I built using the BASIC program was not very complete,
but complete enough to compile the rest of itself. Words like IF and
BEGIN were among the first that needed compilation. No editor? You
could enter the code using 1 BLOCK 704 EXPECT. Making the Forth system
complete and writing the editor took relatively very little time.

The resulting Forth system had a RAM disk of 16 blocks of 704 bytes
each. Why 704 bytes? Those fitted nicely onto a screen of 32 columns
and 24 lines (22 lines in use for the actual text). It contained a
full-screen editor (primitive indeed by today's standards) and it fit
my requirements exactly. It was a compact program, about 8kB.

Of course it had a few peculiarities: The word VOCABULARY was very
buggy and CREATE reserved two extra bytes (for the DOES> pointer) like
<BUILDS in Fig Forth does.

THE HCC FORTH USER GROUP.

About that time I joined the HCC Forth user group. I was already a
member of the HCC Sinclair user group. I demo'ed my new Forth system
at meetings of both the Forth and the Sinclair group. The Spectrum was
a very portable computer if you could arrange that someone else took a
TV set with him. At those meetings I met Coos Haak, who lived in
Utrecht (the meetings were also in Utrecht).

Coos had written a Forth for the Spectrum as well. His Forth was very
complete. It contained some Forth83 features but it conformed to no
standard. He also had 64 columns on the screen (as it was a bitmapped
screen you could do that in software!), but that was awkward to read
on a TV. His Forth contained an assembler and it could also use
Microdrives (a primitive but very fast system using very small tapes,
that could more or less emulate a disk) instead of cassettes.
Coos also taught me some of the secrets of metacompiling.

THE SECOND FORTH ON THE SPECTRUM.

At the end of 1987 I decided to write a Forth83 system for the ZX
Spectrum. This system had to take advantage of the Spectrum 128 (that
I had purchased by then) and Microdrives. I purchased the Forth 83
Standard and I read several articles from Laxen and Perry (the authors
of F83) in Forth Dimensions.

So my (comparatively primitive) Spectrum Forth had to become the home
of a real metacompiler. I used the assembler of Coos Haak (with his
permission of course) and also some machine code primitives and other
ideas. The Z80 assembler was a bit like the 8080 assembler from Laxen
and Perry, but with some different mnemonics and adapted to the Z80.

The metaforth source consisted of 4 parts, about 10kB each. In the
long run it became VERY annoying to load them all from tape, only to
see the system crash in a split second. Therefore I purchased an
Interface 1 with Microdrives (very expensive media at about 100
guilders a megabyte! And even today's low quality floppies are more
reliable). As my Forth didn't access Microdrives I had to save and
load the RAM disk from BASIC by hand.

It took me quite a bit more time to get this Forth started than my
first Forth took. I kept confusing vocabularies (It's metaforth!) and
the new system was a bit more complex (with vectored I/O and the
like). Forth assembler syntax is also a bit awkward and unforgiving.
Of course I had a trace routine so I could watch Forth on its way to
the next crash. By March 1988 I had the thing happily running. I
adapted the editor to the new system and I edited the meta source code
so it could be run from the new system.

This system had blocks of 1kB (as the standard specified), but they
were 32 lines of 32 characters. My screen editor showed only one half
of each block. The RAM disk was 10kB (could be changed) on the 48k
Spectrum and 80kB on the 128k Spectrum. I could access Microdrives and
tapes (I vectored the load and save routines through BASIC). Like the
first Forth the editor had a mode in which you could edit the RAM disk
as one big file. I used this to edit documents like the manual for the
system.

Next you see the first two blocks of the (cryptic) source code for the
Forth kernel. Forward references were handled in a very ad-hoc way!
(see the lines containing HERE-T ' FOO >BODY ! )

Scr#1
\ METAFORTH83 INNER INTERPRETER
HEX ASSEMBLER
 0 JP 0 JP 0 JP
FORTH          DEFINITIONS
HERE-T CONSTANT 'BASE
HERE-T 2 + CONSTANT 'DP
HERE-T 4 + CONSTANT 'KEY
HERE-T 6 + CONSTANT 'EMIT
HERE-T 8 + CONSTANT RPTR
HERE-T A + CONSTANT 'WAIT
HERE-T C + CONSTANT 'FENCE
HERE-T E + CONSTANT 'S0
HERE-T 10 + CONSTANT 'R0
ORIGIN 2- CONSTANT UPTR
3C ALLOT-T VARIABLE 'I
ASSEMBLER DEFINITIONS
: JPIX %X X JPHL ;
( INNER INTERPRETER)
HERE-T ' NEXT >BODY  !
EXDE M E LD H INC M D LD H INC
EXDE JPHL
HERE-T ' DOCON >BODY !
H POP M C LD H INC M B LD
B PUSH JPIX
HERE-T ' DOCOL >BODY !
RPTR LDHL H DEC D M LD H DEC
E M LD RPTR STHL D POP JPIX
HERE-T ' DOUSER >BODY !
H POP M C LD 0 B LD# UPTR LDHL
B ADDP H PUSH JPIX
-->

Scr#2
\ META PRIMITIVES LIT,BRANCH,DO
META DEFINITIONS
CODE LIT HERE-T 'LIT !
EXDE M C LD H INC M B LD H INC B
 PUSH NEXT 1+  JP ;C
CODE BRANCH HERE-T 'BRANCH !
 EXDE M E LD H INC M D LD JPIX ;
C
CODE ?BRANCH HERE-T '?BR !
B POP B A LD C OR 'BRANCH @   JP
Z D INC D INC JPIX ;C
CODE EXECUTE H POP JPHL ;C
CODE EXIT HERE-T 'EXIT !
RPTR LDHL M E LD H INC M D LD H
INC RPTR STHL JPIX ;C
CODE (DO) HERE-T 'DO !
H POP B POP H PUSH RPTR LDHL H D
EC B M LD H DEC C M LD D INC D I
NC H DEC D M LD H DEC E M LD EXS
P A AND B SBCP H A LD 80 XOR#
A B LD L C LD H POP H DEC B M LD
 H DEC C M LD RPTR STHL JPIX ;C
CODE (?DO) HERE-T '?DO !
H POP B POP B SUBP NZ IF B ADDP
B PUSH H PUSH 'DO @ JR THEN
'BRANCH @ JP ;C

-->

I wrote a complete manual for it (in Dutch) using the Forth editor. I
printed this on a 32 column thermal printer. Next I cut the thermal
paper and pasted it to A4 sheets (in two columns). These I could
photocopy.

I wrote the following extensions to my Forth.
- Full double precision words.
- A floating point package including transcendental functions (not
  using the slow ROM routines).
- Graphics and sound routines.
- A decompiler.
- Words to handle strings and other data types.
- A primitive multitasker!
I documented all of these in the manual.

I wrote The following Forth applications.
- A user defined graphics editor.
- A logic simulator.
- A very primitive chess program.
- A turtle graphics, Logo, screen drawing package.

Later I printed the entire manual in two columns on Coos Haak's matrix
printer and printed it 12 times. (matrix printing was cheaper than
Xeroxing.) At the "HCC days" (November 1988) several cassettes and
manuals were sold.

THE PC AND BEYOND.

In August 1988 I purchased a PC clone. After all I really needed an
80 column screen and real disks for text processing.

Forth continued to be the primary language used, especially when I got
F-PC in early 1989 (I had F83 before). One of the things I wrote in it
was a BASIC interpreter with all the floating point and string
functions you would expect on the old home computers. Another program
was a complete 6809 simulator/assembler/disassembler.

In 1991 I got hold of a Spectrum emulator running on PC (It was called
Z80 and I actually registered that shareware package). I wrote a
primitive tape loading program for the PC (the emulator didn't have
this function back then) and someone transferred some of my files to
diskettes, for which I also made a program to read them on a PC. With
those tools I got most of the Spectrum stuff transferred to the PC.
Thanks to this effort you can now download forth83.zip from
ftp.nvg.unit.no.

In 1992 I purchased a 386 and I moved to Linux. While there are Forths
under Linux and I even contributed to bug fixing, Forth was no longer
my primary language. I continued to work on the 6809 emulator and
BASIC in Forth. In Linux with its abstract device files, Forth is very
far removed from its original home, hardware control. I did write an
instruction set simulator for an imaginary 32-bit processor specially
designed to run Forth. Of course I wrote a Forth for it. The 6809
simulator (now rewritten in C) also has Forth running on it. You guess
it right: I'm fascinated by emulators and I'm not satisfied until it
runs both Forth and Tetris (preferably Dirk Zoller's Tetris for
Forth). Of course I can run my Spectrum Forth on xzx under Linux.

--
Lennart
