c73dd3200329e2b6d2ae126cbaaf56f52818a6a6
[jonesforth.git] / jonesforth.S
1 /*      A sometimes minimal FORTH compiler and tutorial for Linux / i386 systems. -*- asm -*-
2         By Richard W.M. Jones <rich@annexia.org> http://annexia.org/forth
3         This is PUBLIC DOMAIN (see public domain release statement below).
4         $Id: jonesforth.S,v 1.21 2007-09-23 11:00:30 rich Exp $
5
6         gcc -m32 -nostdlib -static -Wl,-Ttext,0 -o jonesforth jonesforth.S
7 */
8         .set JONES_VERSION,20
9 /*
10         INTRODUCTION ----------------------------------------------------------------------
11
12         FORTH is one of those alien languages which most working programmers regard in the same
13         way as Haskell, LISP, and so on.  Something so strange that they'd rather any thoughts
14         of it just go away so they can get on with writing this paying code.  But that's wrong
15         and if you care at all about programming then you should at least understand all these
16         languages, even if you will never use them.
17
18         LISP is the ultimate high-level language, and features from LISP are being added every
19         decade to the more common languages.  But FORTH is in some ways the ultimate in low level
20         programming.  Out of the box it lacks features like dynamic memory management and even
21         strings.  In fact, at its primitive level it lacks even basic concepts like IF-statements
22         and loops.
23
24         Why then would you want to learn FORTH?  There are several very good reasons.  First
25         and foremost, FORTH is minimal.  You really can write a complete FORTH in, say, 2000
26         lines of code.  I don't just mean a FORTH program, I mean a complete FORTH operating
27         system, environment and language.  You could boot such a FORTH on a bare PC and it would
28         come up with a prompt where you could start doing useful work.  The FORTH you have here
29         isn't minimal and uses a Linux process as its 'base PC' (both for the purposes of making
30         it a good tutorial). It's possible to completely understand the system.  Who can say they
31         completely understand how Linux works, or gcc?
32
33         Secondly FORTH has a peculiar bootstrapping property.  By that I mean that after writing
34         a little bit of assembly to talk to the hardware and implement a few primitives, all the
35         rest of the language and compiler is written in FORTH itself.  Remember I said before
36         that FORTH lacked IF-statements and loops?  Well of course it doesn't really because
37         such a lanuage would be useless, but my point was rather that IF-statements and loops are
38         written in FORTH itself.
39
40         Now of course this is common in other languages as well, and in those languages we call
41         them 'libraries'.  For example in C, 'printf' is a library function written in C.  But
42         in FORTH this goes way beyond mere libraries.  Can you imagine writing C's 'if' in C?
43         And that brings me to my third reason: If you can write 'if' in FORTH, then why restrict
44         yourself to the usual if/while/for/switch constructs?  You want a construct that iterates
45         over every other element in a list of numbers?  You can add it to the language.  What
46         about an operator which pulls in variables directly from a configuration file and makes
47         them available as FORTH variables?  Or how about adding Makefile-like dependencies to
48         the language?  No problem in FORTH.  This concept isn't common in programming languages,
49         but it has a name (in fact two names): "macros" (by which I mean LISP-style macros, not
50         the lame C preprocessor) and "domain specific languages" (DSLs).
51
52         This tutorial isn't about learning FORTH as the language.  I'll point you to some references
53         you should read if you're not familiar with using FORTH.  This tutorial is about how to
54         write FORTH.  In fact, until you understand how FORTH is written, you'll have only a very
55         superficial understanding of how to use it.
56
57         So if you're not familiar with FORTH or want to refresh your memory here are some online
58         references to read:
59
60         http://en.wikipedia.org/wiki/Forth_%28programming_language%29
61
62         http://galileo.phys.virginia.edu/classes/551.jvn.fall01/primer.htm
63
64         http://wiki.laptop.org/go/Forth_Lessons
65
66         http://www.albany.net/~hello/simple.htm
67
68         Here is another "Why FORTH?" essay: http://www.jwdt.com/~paysan/why-forth.html
69
70         Discussion and criticism of this FORTH here: http://lambda-the-ultimate.org/node/2452
71
72         ACKNOWLEDGEMENTS ----------------------------------------------------------------------
73
74         This code draws heavily on the design of LINA FORTH (http://home.hccnet.nl/a.w.m.van.der.horst/lina.html)
75         by Albert van der Horst.  Any similarities in the code are probably not accidental.
76
77         Also I used this document (http://ftp.funet.fi/pub/doc/IOCCC/1992/buzzard.2.design) which really
78         defies easy explanation.
79
80         PUBLIC DOMAIN ----------------------------------------------------------------------
81
82         I, the copyright holder of this work, hereby release it into the public domain. This applies worldwide.
83
84         In case this is not legally possible, I grant any entity the right to use this work for any purpose,
85         without any conditions, unless such conditions are required by law.
86
87         SETTING UP ----------------------------------------------------------------------
88
89         Let's get a few housekeeping things out of the way.  Firstly because I need to draw lots of
90         ASCII-art diagrams to explain concepts, the best way to look at this is using a window which
91         uses a fixed width font and is at least this wide:
92
93  <------------------------------------------------------------------------------------------------------------------------>
94
95         Secondly make sure TABS are set to 8 characters.  The following should be a vertical
96         line.  If not, sort out your tabs.
97
98         |
99         |
100         |
101
102         Thirdly I assume that your screen is at least 50 characters high.
103
104         ASSEMBLING ----------------------------------------------------------------------
105
106         If you want to actually run this FORTH, rather than just read it, you will need Linux on an
107         i386.  Linux because instead of programming directly to the hardware on a bare PC which I
108         could have done, I went for a simpler tutorial by assuming that the 'hardware' is a Linux
109         process with a few basic system calls (read, write and exit and that's about all).  i386
110         is needed because I had to write the assembly for a processor, and i386 is by far the most
111         common.  (Of course when I say 'i386', any 32- or 64-bit x86 processor will do.  I'm compiling
112         this on a 64 bit AMD Opteron).
113
114         Again, to assemble this you will need gcc and gas (the GNU assembler).  The commands to
115         assemble and run the code (save this file as 'jonesforth.S') are:
116
117         gcc -m32 -nostdlib -static -Wl,-Ttext,0 -o jonesforth jonesforth.S
118         ./jonesforth
119
120         You will see lots of 'Warning: unterminated string; newline inserted' messages from the
121         assembler.  That's just because the GNU assembler doesn't have a good syntax for multi-line
122         strings (or rather it used to, but the developers removed it!) so I've abused the syntax
123         slightly to make things readable.  Ignore these warnings.
124
125         If you want to run your own FORTH programs you can do:
126
127         ./jonesforth < myprog.f
128
129         If you want to load your own FORTH code and then continue reading user commands, you can do:
130
131         cat myfunctions.f - | ./jonesforth
132
133         ASSEMBLER ----------------------------------------------------------------------
134
135         (You can just skip to the next section -- you don't need to be able to read assembler to
136         follow this tutorial).
137
138         However if you do want to read the assembly code here are a few notes about gas (the GNU assembler):
139
140         (1) Register names are prefixed with '%', so %eax is the 32 bit i386 accumulator.  The registers
141             available on i386 are: %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp and %esp, and most of them
142             have special purposes.
143
144         (2) Add, mov, etc. take arguments in the form SRC,DEST.  So mov %eax,%ecx moves %eax -> %ecx
145
146         (3) Constants are prefixed with '$', and you mustn't forget it!  If you forget it then it
147             causes a read from memory instead, so:
148             mov $2,%eax         moves number 2 into %eax
149             mov 2,%eax          reads the 32 bit word from address 2 into %eax (ie. most likely a mistake)
150
151         (4) gas has a funky syntax for local labels, where '1f' (etc.) means label '1:' "forwards"
152             and '1b' (etc.) means label '1:' "backwards".
153
154         (5) 'ja' is "jump if above", 'jb' for "jump if below", 'je' "jump if equal" etc.
155
156         (6) gas has a reasonably nice .macro syntax, and I use them a lot to make the code shorter and
157             less repetitive.
158
159         For more help reading the assembler, do "info gas" at the Linux prompt.
160
161         Now the tutorial starts in earnest.
162
163         THE DICTIONARY ----------------------------------------------------------------------
164
165         In FORTH as you will know, functions are called "words", and just as in other languages they
166         have a name and a definition.  Here are two FORTH words:
167
168         : DOUBLE DUP + ;                \ name is "DOUBLE", definition is "DUP +"
169         : QUADRUPLE DOUBLE DOUBLE ;     \ name is "QUADRUPLE", definition is "DOUBLE DOUBLE"
170
171         Words, both built-in ones and ones which the programmer defines later, are stored in a dictionary
172         which is just a linked list of dictionary entries.
173
174         <--- DICTIONARY ENTRY (HEADER) ----------------------->
175         +------------------------+--------+---------- - - - - +----------- - - - -
176         | LINK POINTER           | LENGTH/| NAME              | DEFINITION
177         |                        | FLAGS  |                   |
178         +--- (4 bytes) ----------+- byte -+- n bytes  - - - - +----------- - - - -
179
180         I'll come to the definition of the word later.  For now just look at the header.  The first
181         4 bytes are the link pointer.  This points back to the previous word in the dictionary, or, for
182         the first word in the dictionary it is just a NULL pointer.  Then comes a length/flags byte.
183         The length of the word can be up to 31 characters (5 bits used) and the top three bits are used
184         for various flags which I'll come to later.  This is followed by the name itself, and in this
185         implementation the name is rounded up to a multiple of 4 bytes by padding it with zero bytes.
186         That's just to ensure that the definition starts on a 32 bit boundary.
187
188         A FORTH variable called LATEST contains a pointer to the most recently defined word, in
189         other words, the head of this linked list.
190
191         DOUBLE and QUADRUPLE might look like this:
192
193           pointer to previous word
194            ^
195            |
196         +--|------+---+---+---+---+---+---+---+---+------------- - - - -
197         | LINK    | 6 | D | O | U | B | L | E | 0 | (definition ...)
198         +---------+---+---+---+---+---+---+---+---+------------- - - - -
199            ^       len                         padding
200            |
201         +--|------+---+---+---+---+---+---+---+---+---+---+---+---+------------- - - - -
202         | LINK    | 9 | Q | U | A | D | R | U | P | L | E | 0 | 0 | (definition ...)
203         +---------+---+---+---+---+---+---+---+---+---+---+---+---+------------- - - - -
204            ^       len                                     padding
205            |
206            |
207           LATEST
208
209         You should be able to see from this how you might implement functions to find a word in
210         the dictionary (just walk along the dictionary entries starting at LATEST and matching
211         the names until you either find a match or hit the NULL pointer at the end of the dictionary);
212         and add a word to the dictionary (create a new definition, set its LINK to LATEST, and set
213         LATEST to point to the new word).  We'll see precisely these functions implemented in
214         assembly code later on.
215
216         One interesting consequence of using a linked list is that you can redefine words, and
217         a newer definition of a word overrides an older one.  This is an important concept in
218         FORTH because it means that any word (even "built-in" or "standard" words) can be
219         overridden with a new definition, either to enhance it, to make it faster or even to
220         disable it.  However because of the way that FORTH words get compiled, which you'll
221         understand below, words defined using the old definition of a word continue to use
222         the old definition.  Only words defined after the new definition use the new definition.
223
224         DIRECT THREADED CODE ----------------------------------------------------------------------
225
226         Now we'll get to the really crucial bit in understanding FORTH, so go and get a cup of tea
227         or coffee and settle down.  It's fair to say that if you don't understand this section, then you
228         won't "get" how FORTH works, and that would be a failure on my part for not explaining it well.
229         So if after reading this section a few times you don't understand it, please email me
230         (rich@annexia.org).
231
232         Let's talk first about what "threaded code" means.  Imagine a peculiar version of C where
233         you are only allowed to call functions without arguments.  (Don't worry for now that such a
234         language would be completely useless!)  So in our peculiar C, code would look like this:
235
236         f ()
237         {
238           a ();
239           b ();
240           c ();
241         }
242
243         and so on.  How would a function, say 'f' above, be compiled by a standard C compiler?
244         Probably into assembly code like this.  On the right hand side I've written the actual
245         i386 machine code.
246
247         f:
248           CALL a                        E8 08 00 00 00
249           CALL b                        E8 1C 00 00 00
250           CALL c                        E8 2C 00 00 00
251           ; ignore the return from the function for now
252
253         "E8" is the x86 machine code to "CALL" a function.  In the first 20 years of computing
254         memory was hideously expensive and we might have worried about the wasted space being used
255         by the repeated "E8" bytes.  We can save 20% in code size (and therefore, in expensive memory)
256         by compressing this into just:
257
258         08 00 00 00             Just the function addresses, without
259         1C 00 00 00             the CALL prefix.
260         2C 00 00 00
261
262         [Historical note: If the execution model that FORTH uses looks strange from the following
263         paragraphs, then it was motivated entirely by the need to save memory on early computers.
264         This code compression isn't so important now when our machines have more memory in their L1
265         caches than those early computers had in total, but the execution model still has some
266         useful properties].
267
268         Of course this code won't run directly any more.  Instead we need to write an interpreter
269         which takes each pair of bytes and calls it.
270
271         On an i386 machine it turns out that we can write this interpreter rather easily, in just
272         two assembly instructions which turn into just 3 bytes of machine code.  Let's store the
273         pointer to the next word to execute in the %esi register:
274
275                 08 00 00 00     <- We're executing this one now.  %esi is the _next_ one to execute.
276         %esi -> 1C 00 00 00
277                 2C 00 00 00
278
279         The all-important i386 instruction is called LODSL (or in Intel manuals, LODSW).  It does
280         two things.  Firstly it reads the memory at %esi into the accumulator (%eax).  Secondly it
281         increments %esi by 4 bytes.  So after LODSL, the situation now looks like this:
282
283                 08 00 00 00     <- We're still executing this one
284                 1C 00 00 00     <- %eax now contains this address (0x0000001C)
285         %esi -> 2C 00 00 00
286
287         Now we just need to jump to the address in %eax.  This is again just a single x86 instruction
288         written JMP *(%eax).  And after doing the jump, the situation looks like:
289
290                 08 00 00 00
291                 1C 00 00 00     <- Now we're executing this subroutine.
292         %esi -> 2C 00 00 00
293
294         To make this work, each subroutine is followed by the two instructions 'LODSL; JMP *(%eax)'
295         which literally make the jump to the next subroutine.
296
297         And that brings us to our first piece of actual code!  Well, it's a macro.
298 */
299
300 /* NEXT macro. */
301         .macro NEXT
302         lodsl
303         jmp *(%eax)
304         .endm
305
306 /*      The macro is called NEXT.  That's a FORTH-ism.  It expands to those two instructions.
307
308         Every FORTH primitive that we write has to be ended by NEXT.  Think of it kind of like
309         a return.
310
311         The above describes what is known as direct threaded code.
312
313         To sum up: We compress our function calls down to a list of addresses and use a somewhat
314         magical macro to act as a "jump to next function in the list".  We also use one register (%esi)
315         to act as a kind of instruction pointer, pointing to the next function in the list.
316
317         I'll just give you a hint of what is to come by saying that a FORTH definition such as:
318
319         : QUADRUPLE DOUBLE DOUBLE ;
320
321         actually compiles (almost, not precisely but we'll see why in a moment) to a list of
322         function addresses for DOUBLE, DOUBLE and a special function called EXIT to finish off.
323
324         At this point, REALLY EAGLE-EYED ASSEMBLY EXPERTS are saying "JONES, YOU'VE MADE A MISTAKE!".
325
326         I lied about JMP *(%eax).  
327
328         INDIRECT THREADED CODE ----------------------------------------------------------------------
329
330         It turns out that direct threaded code is interesting but only if you want to just execute
331         a list of functions written in assembly language.  So QUADRUPLE would work only if DOUBLE
332         was an assembly language function.  In the direct threaded code, QUADRUPLE would look like:
333
334                 +------------------+
335                 | addr of DOUBLE  --------------------> (assembly code to do the double)
336                 +------------------+                    NEXT
337         %esi -> | addr of DOUBLE   |
338                 +------------------+
339
340         We can add an extra indirection to allow us to run both words written in assembly language
341         (primitives written for speed) and words written in FORTH themselves as lists of addresses.
342
343         The extra indirection is the reason for the brackets in JMP *(%eax).
344
345         Let's have a look at how QUADRUPLE and DOUBLE really look in FORTH:
346
347                 : QUADRUPLE DOUBLE DOUBLE ;
348
349                 +------------------+
350                 | codeword         |               : DOUBLE DUP + ;
351                 +------------------+
352                 | addr of DOUBLE  ---------------> +------------------+
353                 +------------------+               | codeword         |
354                 | addr of DOUBLE   |               +------------------+
355                 +------------------+               | addr of DUP   --------------> +------------------+
356                 | addr of EXIT     |               +------------------+            | codeword      -------+
357                 +------------------+       %esi -> | addr of +     --------+       +------------------+   |
358                                                    +------------------+    |       | assembly to    <-----+
359                                                    | addr of EXIT     |    |       | implement DUP    |
360                                                    +------------------+    |       |    ..            |
361                                                                            |       |    ..            |
362                                                                            |       | NEXT             |
363                                                                            |       +------------------+
364                                                                            |
365                                                                            +-----> +------------------+
366                                                                                    | codeword      -------+
367                                                                                    +------------------+   |
368                                                                                    | assembly to   <------+
369                                                                                    | implement +      |
370                                                                                    |    ..            |
371                                                                                    |    ..            |
372                                                                                    | NEXT             |
373                                                                                    +------------------+
374
375         This is the part where you may need an extra cup of tea/coffee/favourite caffeinated
376         beverage.  What has changed is that I've added an extra pointer to the beginning of
377         the definitions.  In FORTH this is sometimes called the "codeword".  The codeword is
378         a pointer to the interpreter to run the function.  For primitives written in
379         assembly language, the "interpreter" just points to the actual assembly code itself.
380         They don't need interpreting, they just run.
381
382         In words written in FORTH (like QUADRUPLE and DOUBLE), the codeword points to an interpreter
383         function.
384
385         I'll show you the interpreter function shortly, but let's recall our indirect
386         JMP *(%eax) with the "extra" brackets.  Take the case where we're executing DOUBLE
387         as shown, and DUP has been called.  Note that %esi is pointing to the address of +
388
389         The assembly code for DUP eventually does a NEXT.  That:
390
391         (1) reads the address of + into %eax            %eax points to the codeword of +
392         (2) increments %esi by 4
393         (3) jumps to the indirect %eax                  jumps to the address in the codeword of +,
394                                                         ie. the assembly code to implement +
395
396                 +------------------+
397                 | codeword         |
398                 +------------------+
399                 | addr of DOUBLE  ---------------> +------------------+
400                 +------------------+               | codeword         |
401                 | addr of DOUBLE   |               +------------------+
402                 +------------------+               | addr of DUP   --------------> +------------------+
403                 | addr of EXIT     |               +------------------+            | codeword      -------+
404                 +------------------+               | addr of +     --------+       +------------------+   |
405                                                    +------------------+    |       | assembly to    <-----+
406                                            %esi -> | addr of EXIT     |    |       | implement DUP    |
407                                                    +------------------+    |       |    ..            |
408                                                                            |       |    ..            |
409                                                                            |       | NEXT             |
410                                                                            |       +------------------+
411                                                                            |
412                                                                            +-----> +------------------+
413                                                                                    | codeword      -------+
414                                                                                    +------------------+   |
415                                                                         now we're  | assembly to    <-----+
416                                                                         executing  | implement +      |
417                                                                         this       |    ..            |
418                                                                         function   |    ..            |
419                                                                                    | NEXT             |
420                                                                                    +------------------+
421
422         So I hope that I've convinced you that NEXT does roughly what you'd expect.  This is
423         indirect threaded code.
424
425         I've glossed over four things.  I wonder if you can guess without reading on what they are?
426
427         .
428         .
429         .
430
431         My list of four things are: (1) What does "EXIT" do?  (2) which is related to (1) is how do
432         you call into a function, ie. how does %esi start off pointing at part of QUADRUPLE, but
433         then point at part of DOUBLE.  (3) What goes in the codeword for the words which are written
434         in FORTH?  (4) How do you compile a function which does anything except call other functions
435         ie. a function which contains a number like : DOUBLE 2 * ; ?
436
437         THE INTERPRETER AND RETURN STACK ------------------------------------------------------------
438
439         Going at these in no particular order, let's talk about issues (3) and (2), the interpreter
440         and the return stack.
441
442         Words which are defined in FORTH need a codeword which points to a little bit of code to
443         give them a "helping hand" in life.  They don't need much, but they do need what is known
444         as an "interpreter", although it doesn't really "interpret" in the same way that, say,
445         Java bytecode used to be interpreted (ie. slowly).  This interpreter just sets up a few
446         machine registers so that the word can then execute at full speed using the indirect
447         threaded model above.
448
449         One of the things that needs to happen when QUADRUPLE calls DOUBLE is that we save the old
450         %esi ("instruction pointer") and create a new one pointing to the first word in DOUBLE.
451         Because we will need to restore the old %esi at the end of DOUBLE (this is, after all, like
452         a function call), we will need a stack to store these "return addresses" (old values of %esi).
453
454         As you will have read, when reading the background documentation, FORTH has two stacks,
455         an ordinary stack for parameters, and a return stack which is a bit more mysterious.  But
456         our return stack is just the stack I talked about in the previous paragraph, used to save
457         %esi when calling from a FORTH word into another FORTH word.
458
459         In this FORTH, we are using the normal stack pointer (%esp) for the parameter stack.
460         We will use the i386's "other" stack pointer (%ebp, usually called the "frame pointer")
461         for our return stack.
462
463         I've got two macros which just wrap up the details of using %ebp for the return stack.
464         You use them as for example "PUSHRSP %eax" (push %eax on the return stack) or "POPRSP %ebx"
465         (pop top of return stack into %ebx).
466 */
467
468 /* Macros to deal with the return stack. */
469         .macro PUSHRSP reg
470         lea -4(%ebp),%ebp       // push reg on to return stack
471         movl \reg,(%ebp)
472         .endm
473
474         .macro POPRSP reg
475         mov (%ebp),\reg         // pop top of return stack to reg
476         lea 4(%ebp),%ebp
477         .endm
478
479 /*
480         And with that we can now talk about the interpreter.
481
482         In FORTH the interpreter function is often called DOCOL (I think it means "DO COLON" because
483         all FORTH definitions start with a colon, as in : DOUBLE DUP + ;
484
485         The "interpreter" (it's not really "interpreting") just needs to push the old %esi on the
486         stack and set %esi to the first word in the definition.  Remember that we jumped to the
487         function using JMP *(%eax)?  Well a consequence of that is that conveniently %eax contains
488         the address of this codeword, so just by adding 4 to it we get the address of the first
489         data word.  Finally after setting up %esi, it just does NEXT which causes that first word
490         to run.
491 */
492
493 /* DOCOL - the interpreter! */
494         .text
495         .align 4
496 DOCOL:
497         PUSHRSP %esi            // push %esi on to the return stack
498         addl $4,%eax            // %eax points to codeword, so make
499         movl %eax,%esi          // %esi point to first data word
500         NEXT
501
502 /*
503         Just to make this absolutely clear, let's see how DOCOL works when jumping from QUADRUPLE
504         into DOUBLE:
505
506                 QUADRUPLE:
507                 +------------------+
508                 | codeword         |
509                 +------------------+               DOUBLE:
510                 | addr of DOUBLE  ---------------> +------------------+
511                 +------------------+       %eax -> | addr of DOCOL    |
512         %esi -> | addr of DOUBLE   |               +------------------+
513                 +------------------+               | addr of DUP      |
514                 | addr of EXIT     |               +------------------+
515                 +------------------+               | etc.             |
516
517         First, the call to DOUBLE calls DOCOL (the codeword of DOUBLE).  DOCOL does this:  It
518         pushes the old %esi on the return stack.  %eax points to the codeword of DOUBLE, so we
519         just add 4 on to it to get our new %esi:
520
521                 QUADRUPLE:
522                 +------------------+
523                 | codeword         |
524                 +------------------+               DOUBLE:
525                 | addr of DOUBLE  ---------------> +------------------+
526 top of return   +------------------+       %eax -> | addr of DOCOL    |
527 stack points -> | addr of DOUBLE   |       + 4 =   +------------------+
528                 +------------------+       %esi -> | addr of DUP      |
529                 | addr of EXIT     |               +------------------+
530                 +------------------+               | etc.             |
531
532         Then we do NEXT, and because of the magic of threaded code that increments %esi again
533         and calls DUP.
534
535         Well, it seems to work.
536
537         One minor point here.  Because DOCOL is the first bit of assembly actually to be defined
538         in this file (the others were just macros), and because I usually compile this code with the
539         text segment starting at address 0, DOCOL has address 0.  So if you are disassembling the
540         code and see a word with a codeword of 0, you will immediately know that the word is
541         written in FORTH (it's not an assembler primitive) and so uses DOCOL as the interpreter.
542
543         STARTING UP ----------------------------------------------------------------------
544
545         Now let's get down to nuts and bolts.  When we start the program we need to set up
546         a few things like the return stack.  But as soon as we can, we want to jump into FORTH
547         code (albeit much of the "early" FORTH code will still need to be written as
548         assembly language primitives).
549
550         This is what the set up code does.  Does a tiny bit of house-keeping, sets up the
551         separate return stack (NB: Linux gives us the ordinary parameter stack already), then
552         immediately jumps to a FORTH word called COLD.  COLD stands for cold-start.  In ISO
553         FORTH (but not in this FORTH), COLD can be called at any time to completely reset
554         the state of FORTH, and there is another word called WARM which does a partial reset.
555 */
556
557 /* ELF entry point. */
558         .text
559         .globl _start
560 _start:
561         cld
562         mov %esp,var_S0         // Store the initial data stack pointer.
563         mov $return_stack,%ebp  // Initialise the return stack.
564
565         mov $cold_start,%esi    // Initialise interpreter.
566         NEXT                    // Run interpreter!
567
568         .section .rodata
569 cold_start:                     // High-level code without a codeword.
570         .int COLD
571
572 /*
573         We also allocate some space for the return stack and some space to store user
574         definitions.  These are static memory allocations using fixed-size buffers, but it
575         wouldn't be a great deal of work to make them dynamic.
576 */
577
578         .bss
579 /* FORTH return stack. */
580 #define RETURN_STACK_SIZE 8192
581         .align 4096
582         .space RETURN_STACK_SIZE
583 return_stack:                   // Initial top of return stack.
584
585 /* Space for user-defined words. */
586 #define USER_DEFS_SIZE 16384
587         .align 4096
588 user_defs_start:
589         .space USER_DEFS_SIZE
590
591 /*
592         BUILT-IN WORDS ----------------------------------------------------------------------
593
594         Remember our dictionary entries (headers).  Let's bring those together with the codeword
595         and data words to see how : DOUBLE DUP + ; really looks in memory.
596
597           pointer to previous word
598            ^
599            |
600         +--|------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+
601         | LINK    | 6 | D | O | U | B | L | E | 0 | DOCOL      | DUP        | +          | EXIT       |
602         +---------+---+---+---+---+---+---+---+---+------------+--|---------+------------+------------+
603            ^       len                         pad  codeword      |
604            |                                                      V
605           LINK in next word                             points to codeword of DUP
606         
607         Initially we can't just write ": DOUBLE DUP + ;" (ie. that literal string) here because we
608         don't yet have anything to read the string, break it up at spaces, parse each word, etc. etc.
609         So instead we will have to define built-in words using the GNU assembler data constructors
610         (like .int, .byte, .string, .ascii and so on -- look them up in the gas info page if you are
611         unsure of them).
612
613         The long way would be:
614         .int <link to previous word>
615         .byte 6                 // len
616         .ascii "DOUBLE"         // string
617         .byte 0                 // padding
618 DOUBLE: .int DOCOL              // codeword
619         .int DUP                // pointer to codeword of DUP
620         .int PLUS               // pointer to codeword of +
621         .int EXIT               // pointer to codeword of EXIT
622
623         That's going to get quite tedious rather quickly, so here I define an assembler macro
624         so that I can just write:
625
626         defword "DOUBLE",6,,DOUBLE
627         .int DUP,PLUS,EXIT
628
629         and I'll get exactly the same effect.
630
631         Don't worry too much about the exact implementation details of this macro - it's complicated!
632 */
633
634 /* Flags - these are discussed later. */
635 #define F_IMMED 0x80
636 #define F_HIDDEN 0x20
637
638         // Store the chain of links.
639         .set link,0
640
641         .macro defword name, namelen, flags=0, label
642         .section .rodata
643         .align 4
644         .globl name_\label
645 name_\label :
646         .int link               // link
647         .set link,name_\label
648         .byte \flags+\namelen   // flags + length byte
649         .ascii "\name"          // the name
650         .align 4
651         .globl \label
652 \label :
653         .int DOCOL              // codeword - the interpreter
654         // list of word pointers follow
655         .endm
656
657 /*
658         Similarly I want a way to write words written in assembly language.  There will quite a few
659         of these to start with because, well, everything has to start in assembly before there's
660         enough "infrastructure" to be able to start writing FORTH words, but also I want to define
661         some common FORTH words in assembly language for speed, even though I could write them in FORTH.
662
663         This is what DUP looks like in memory:
664
665           pointer to previous word
666            ^
667            |
668         +--|------+---+---+---+---+------------+
669         | LINK    | 3 | D | U | P | code_DUP ---------------------> points to the assembly
670         +---------+---+---+---+---+------------+                    code used to write DUP,
671            ^       len              codeword                        which ends with NEXT.
672            |
673           LINK in next word
674
675         Again, for brevity in writing the header I'm going to write an assembler macro called defcode.
676 */
677
678         .macro defcode name, namelen, flags=0, label
679         .section .rodata
680         .align 4
681         .globl name_\label
682 name_\label :
683         .int link               // link
684         .set link,name_\label
685         .byte \flags+\namelen   // flags + length byte
686         .ascii "\name"          // the name
687         .align 4
688         .globl \label
689 \label :
690         .int code_\label        // codeword
691         .text
692         .align 4
693         .globl code_\label
694 code_\label :                   // assembler code follows
695         .endm
696
697 /*
698         Now some easy FORTH primitives.  These are written in assembly for speed.  If you understand
699         i386 assembly language then it is worth reading these.  However if you don't understand assembly
700         you can skip the details.
701 */
702
703         defcode "DUP",3,,DUP
704         pop %eax                // duplicate top of stack
705         push %eax
706         push %eax
707         NEXT
708
709         defcode "DROP",4,,DROP
710         pop %eax                // drop top of stack
711         NEXT
712
713         defcode "SWAP",4,,SWAP
714         pop %eax                // swap top of stack
715         pop %ebx
716         push %eax
717         push %ebx
718         NEXT
719
720         defcode "OVER",4,,OVER
721         mov 4(%esp),%eax        // get the second element of stack
722         push %eax               // and push it on top
723         NEXT
724
725         defcode "ROT",3,,ROT
726         pop %eax
727         pop %ebx
728         pop %ecx
729         push %eax
730         push %ecx
731         push %ebx
732         NEXT
733
734         defcode "-ROT",4,,NROT
735         pop %eax
736         pop %ebx
737         pop %ecx
738         push %ebx
739         push %eax
740         push %ecx
741         NEXT
742
743         defcode "1+",2,,INCR
744         incl (%esp)             // increment top of stack
745         NEXT
746
747         defcode "1-",2,,DECR
748         decl (%esp)             // decrement top of stack
749         NEXT
750
751         defcode "4+",2,,INCR4
752         addl $4,(%esp)          // add 4 to top of stack
753         NEXT
754
755         defcode "4-",2,,DECR4
756         subl $4,(%esp)          // subtract 4 from top of stack
757         NEXT
758
759         defcode "+",1,,ADD
760         pop %eax                // get top of stack
761         addl %eax,(%esp)        // and add it to next word on stack
762         NEXT
763
764         defcode "-",1,,SUB
765         pop %eax                // get top of stack
766         subl %eax,(%esp)        // and subtract it from next word on stack
767         NEXT
768
769         defcode "*",1,,MUL
770         pop %eax
771         pop %ebx
772         imull %ebx,%eax
773         push %eax               // ignore overflow
774         NEXT
775
776         defcode "/",1,,DIV
777         xor %edx,%edx
778         pop %ebx
779         pop %eax
780         idivl %ebx
781         push %eax               // push quotient
782         NEXT
783
784         defcode "MOD",3,,MOD
785         xor %edx,%edx
786         pop %ebx
787         pop %eax
788         idivl %ebx
789         push %edx               // push remainder
790         NEXT
791
792         defcode "=",1,,EQU      // top two words are equal?
793         pop %eax
794         pop %ebx
795         cmp %ebx,%eax
796         je 1f
797         pushl $0
798         NEXT
799 1:      pushl $1
800         NEXT
801
802         defcode "<>",2,,NEQU    // top two words are not equal?
803         pop %eax
804         pop %ebx
805         cmp %ebx,%eax
806         je 1f
807         pushl $1
808         NEXT
809 1:      pushl $0
810         NEXT
811
812         defcode "0=",2,,ZEQU    // top of stack equals 0?
813         pop %eax
814         test %eax,%eax
815         jz 1f
816         pushl $0
817         NEXT
818 1:      pushl $1
819         NEXT
820
821         defcode "AND",3,,AND
822         pop %eax
823         andl %eax,(%esp)
824         NEXT
825
826         defcode "OR",2,,OR
827         pop %eax
828         orl %eax,(%esp)
829         NEXT
830
831         defcode "INVERT",6,,INVERT // this is the FORTH "NOT" function
832         notl (%esp)
833         NEXT
834
835 /*
836         RETURNING FROM FORTH WORDS ----------------------------------------------------------------------
837
838         Time to talk about what happens when we EXIT a function.  In this diagram QUADRUPLE has called
839         DOUBLE, and DOUBLE is about to exit (look at where %esi is pointing):
840
841                 QUADRUPLE
842                 +------------------+
843                 | codeword         |
844                 +------------------+               DOUBLE
845                 | addr of DOUBLE  ---------------> +------------------+
846                 +------------------+               | codeword         |
847                 | addr of DOUBLE   |               +------------------+
848                 +------------------+               | addr of DUP      |
849                 | addr of EXIT     |               +------------------+
850                 +------------------+               | addr of +        |
851                                                    +------------------+
852                                            %esi -> | addr of EXIT     |
853                                                    +------------------+
854
855         What happens when the + function does NEXT?  Well, the following code is executed.
856 */
857
858         defcode "EXIT",4,,EXIT
859         POPRSP %esi             // pop return stack into %esi
860         NEXT
861
862 /*
863         EXIT gets the old %esi which we saved from before on the return stack, and puts it in %esi.
864         So after this (but just before NEXT) we get:
865
866                 QUADRUPLE
867                 +------------------+
868                 | codeword         |
869                 +------------------+               DOUBLE
870                 | addr of DOUBLE  ---------------> +------------------+
871                 +------------------+               | codeword         |
872         %esi -> | addr of DOUBLE   |               +------------------+
873                 +------------------+               | addr of DUP      |
874                 | addr of EXIT     |               +------------------+
875                 +------------------+               | addr of +        |
876                                                    +------------------+
877                                                    | addr of EXIT     |
878                                                    +------------------+
879
880         And NEXT just completes the job by, well in this case just by calling DOUBLE again :-)
881
882         LITERALS ----------------------------------------------------------------------
883
884         The final point I "glossed over" before was how to deal with functions that do anything
885         apart from calling other functions.  For example, suppose that DOUBLE was defined like this:
886
887         : DOUBLE 2 * ;
888
889         It does the same thing, but how do we compile it since it contains the literal 2?  One way
890         would be to have a function called "2" (which you'd have to write in assembler), but you'd need
891         a function for every single literal that you wanted to use.
892
893         FORTH solves this by compiling the function using a special word called LIT:
894
895         +---------------------------+-------+-------+-------+-------+-------+
896         | (usual header of DOUBLE)  | DOCOL | LIT   | 2     | *     | EXIT  |
897         +---------------------------+-------+-------+-------+-------+-------+
898
899         LIT is executed in the normal way, but what it does next is definitely not normal.  It
900         looks at %esi (which now points to the literal 2), grabs it, pushes it on the stack, then
901         manipulates %esi in order to skip the literal as if it had never been there.
902
903         What's neat is that the whole grab/manipulate can be done using a single byte single
904         i386 instruction, our old friend LODSL.  Rather than me drawing more ASCII-art diagrams,
905         see if you can find out how LIT works:
906 */
907
908         defcode "LIT",3,,LIT
909         // %esi points to the next command, but in this case it points to the next
910         // literal 32 bit integer.  Get that literal into %eax and increment %esi.
911         // On x86, it's a convenient single byte instruction!  (cf. NEXT macro)
912         lodsl
913         push %eax               // push the literal number on to stack
914         NEXT
915
916 /*
917         MEMORY ----------------------------------------------------------------------
918
919         As important point about FORTH is that it gives you direct access to the lowest levels
920         of the machine.  Manipulating memory directly is done frequently in FORTH, and these are
921         the primitive words for doing it.
922 */
923
924         defcode "!",1,,STORE
925         pop %ebx                // address to store at
926         pop %eax                // data to store there
927         mov %eax,(%ebx)         // store it
928         NEXT
929
930         defcode "@",1,,FETCH
931         pop %ebx                // address to fetch
932         mov (%ebx),%eax         // fetch it
933         push %eax               // push value onto stack
934         NEXT
935
936         defcode "+!",2,,ADDSTORE
937         pop %ebx                // address
938         pop %eax                // the amount to add
939         addl %eax,(%ebx)        // add it
940         NEXT
941
942         defcode "-!",2,,SUBSTORE
943         pop %ebx                // address
944         pop %eax                // the amount to subtract
945         subl %eax,(%ebx)        // add it
946         NEXT
947
948 /* ! and @ (STORE and FETCH) store 32-bit words.  It's also useful to be able to read and write bytes.
949  * I don't know whether FORTH has these words, so I invented my own, called !b and @b.
950  * Byte-oriented operations only work on architectures which permit them (i386 is one of those).
951  * UPDATE: writing a byte to the dictionary pointer is called C, in FORTH.
952  */
953         defcode "!b",2,,STOREBYTE
954         pop %ebx                // address to store at
955         pop %eax                // data to store there
956         movb %al,(%ebx)         // store it
957         NEXT
958
959         defcode "@b",2,,FETCHBYTE
960         pop %ebx                // address to fetch
961         xor %eax,%eax
962         movb (%ebx),%al         // fetch it
963         push %eax               // push value onto stack
964         NEXT
965
966 /*
967         BUILT-IN VARIABLES ----------------------------------------------------------------------
968
969         These are some built-in variables and related standard FORTH words.  Of these, the only one that we
970         have discussed so far was LATEST, which points to the last (most recently defined) word in the
971         FORTH dictionary.  LATEST is also a FORTH word which pushes the address of LATEST (the variable)
972         on to the stack, so you can read or write it using @ and ! operators.  For example, to print
973         the current value of LATEST (and this can apply to any FORTH variable) you would do:
974
975         LATEST @ . CR
976
977         To make defining variables shorter, I'm using a macro called defvar, similar to defword and
978         defcode above.  (In fact the defvar macro uses defcode to do the dictionary header).
979 */
980
981         .macro defvar name, namelen, flags=0, label, initial=0
982         defcode \name,\namelen,\flags,\label
983         push $var_\name
984         NEXT
985         .data
986         .align 4
987 var_\name :
988         .int \initial
989         .endm
990
991 /*
992         The built-in variables are:
993
994         STATE           Is the interpreter executing code (0) or compiling a word (non-zero)?
995         LATEST          Points to the latest (most recently defined) word in the dictionary.
996         HERE            Points to the next free byte of memory.  When compiling, compiled words go here.
997         _X              These are three scratch variables, used by some standard dictionary words.
998         _Y
999         _Z
1000         S0              Stores the address of the top of the parameter stack.
1001         R0              Stores the address of the top of the return stack.
1002         VERSION         Is the current version of this FORTH.
1003
1004 */
1005         defvar "STATE",5,,STATE
1006         defvar "HERE",4,,HERE,user_defs_start
1007         defvar "LATEST",6,,LATEST,name_SYSEXIT // SYSEXIT must be last in built-in dictionary
1008         defvar "_X",2,,TX
1009         defvar "_Y",2,,TY
1010         defvar "_Z",2,,TZ
1011         defvar "S0",2,,SZ
1012         defvar "R0",2,,RZ,return_stack
1013         defvar "VERSION",7,,VERSION,JONES_VERSION
1014
1015 /*
1016         RETURN STACK ----------------------------------------------------------------------
1017
1018         These words allow you to access the return stack.  Recall that the register %ebp always points to
1019         the top of the return stack.
1020 */
1021
1022         defcode ">R",2,,TOR
1023         pop %eax                // pop parameter stack into %eax
1024         PUSHRSP %eax            // push it on to the return stack
1025         NEXT
1026
1027         defcode "R>",2,,FROMR
1028         POPRSP %eax             // pop return stack on to %eax
1029         push %eax               // and push on to parameter stack
1030         NEXT
1031
1032         defcode "RSP@",4,,RSPFETCH
1033         push %ebp
1034         NEXT
1035
1036         defcode "RSP!",4,,RSPSTORE
1037         pop %ebp
1038         NEXT
1039
1040         defcode "RDROP",5,,RDROP
1041         lea 4(%ebp),%ebp        // pop return stack and throw away
1042         NEXT
1043
1044 /*
1045         PARAMETER (DATA) STACK ----------------------------------------------------------------------
1046
1047         These functions allow you to manipulate the parameter stack.  Recall that Linux sets up the parameter
1048         stack for us, and it is accessed through %esp.
1049 */
1050
1051         defcode "DSP@",4,,DSPFETCH
1052         mov %esp,%eax
1053         push %eax
1054         NEXT
1055
1056         defcode "DSP!",4,,DSPSTORE
1057         pop %esp
1058         NEXT
1059
1060 /*
1061         INPUT AND OUTPUT ----------------------------------------------------------------------
1062
1063         These are our first really meaty/complicated FORTH primitives.  I have chosen to write them in
1064         assembler, but surprisingly in "real" FORTH implementations these are often written in terms
1065         of more fundamental FORTH primitives.  I chose to avoid that because I think that just obscures
1066         the implementation.  After all, you may not understand assembler but you can just think of it
1067         as an opaque block of code that does what it says.
1068
1069         Let's discuss input first.
1070
1071         The FORTH word KEY reads the next byte from stdin (and pushes it on the parameter stack).
1072         So if KEY is called and someone hits the space key, then the number 32 (ASCII code of space)
1073         is pushed on the stack.
1074
1075         In FORTH there is no distinction between reading code and reading input.  We might be reading
1076         and compiling code, we might be reading words to execute, we might be asking for the user
1077         to type their name -- ultimately it all comes in through KEY.
1078
1079         The implementation of KEY uses an input buffer of a certain size (defined at the end of the
1080         program).  It calls the Linux read(2) system call to fill this buffer and tracks its position
1081         in the buffer using a couple of variables, and if it runs out of input buffer then it refills
1082         it automatically.  The other thing that KEY does is if it detects that stdin has closed, it
1083         exits the program, which is why when you hit ^D the FORTH system cleanly exits.
1084 */
1085
1086 #include <asm-i386/unistd.h>
1087
1088         defcode "KEY",3,,KEY
1089         call _KEY
1090         push %eax               // push return value on stack
1091         NEXT
1092 _KEY:
1093         mov (currkey),%ebx
1094         cmp (bufftop),%ebx
1095         jge 1f
1096         xor %eax,%eax
1097         mov (%ebx),%al
1098         inc %ebx
1099         mov %ebx,(currkey)
1100         ret
1101
1102 1:      // out of input; use read(2) to fetch more input from stdin
1103         xor %ebx,%ebx           // 1st param: stdin
1104         mov $buffer,%ecx        // 2nd param: buffer
1105         mov %ecx,currkey
1106         mov $buffend-buffer,%edx // 3rd param: max length
1107         mov $__NR_read,%eax     // syscall: read
1108         int $0x80
1109         test %eax,%eax          // If %eax <= 0, then exit.
1110         jbe 2f
1111         addl %eax,%ecx          // buffer+%eax = bufftop
1112         mov %ecx,bufftop
1113         jmp _KEY
1114
1115 2:      // error or out of input: exit
1116         xor %ebx,%ebx
1117         mov $__NR_exit,%eax     // syscall: exit
1118         int $0x80
1119
1120 /*
1121         By contrast, output is much simpler.  The FORTH word EMIT writes out a single byte to stdout.
1122         This implementation just uses the write system call.  No attempt is made to buffer output, but
1123         it would be a good exercise to add it.
1124 */
1125
1126         defcode "EMIT",4,,EMIT
1127         pop %eax
1128         call _EMIT
1129         NEXT
1130 _EMIT:
1131         mov $1,%ebx             // 1st param: stdout
1132
1133         // write needs the address of the byte to write
1134         mov %al,(2f)
1135         mov $2f,%ecx            // 2nd param: address
1136
1137         mov $1,%edx             // 3rd param: nbytes = 1
1138
1139         mov $__NR_write,%eax    // write syscall
1140         int $0x80
1141         ret
1142
1143         .bss
1144 2:      .space 1                // scratch used by EMIT
1145
1146 /*
1147         Back to input, WORD is a FORTH word which reads the next full word of input.
1148
1149         What it does in detail is that it first skips any blanks (spaces, tabs, newlines and so on).
1150         Then it calls KEY to read characters into an internal buffer until it hits a blank.  Then it
1151         calculates the length of the word it read and returns the address and the length as
1152         two words on the stack (with address at the top).
1153
1154         Notice that WORD has a single internal buffer which it overwrites each time (rather like
1155         a static C string).  Also notice that WORD's internal buffer is just 32 bytes long and
1156         there is NO checking for overflow.  31 bytes happens to be the maximum length of a
1157         FORTH word that we support, and that is what WORD is used for: to read FORTH words when
1158         we are compiling and executing code.  The returned strings are not NUL-terminated, so
1159         in some crazy-world you could define FORTH words containing ASCII NULs, although why
1160         you'd want to is a bit beyond me.
1161
1162         WORD is not suitable for just reading strings (eg. user input) because of all the above
1163         peculiarities and limitations.
1164
1165         Note that when executing, you'll see:
1166         WORD FOO
1167         which puts "FOO" and length 3 on the stack, but when compiling:
1168         : BAR WORD FOO ;
1169         is an error (or at least it doesn't do what you might expect).  Later we'll talk about compiling
1170         and immediate mode, and you'll understand why.
1171 */
1172
1173         defcode "WORD",4,,WORD
1174         call _WORD
1175         push %ecx               // push length
1176         push %edi               // push base address
1177         NEXT
1178
1179 _WORD:
1180         /* Search for first non-blank character.  Also skip \ comments. */
1181 1:
1182         call _KEY               // get next key, returned in %eax
1183         cmpb $'\\',%al          // start of a comment?
1184         je 3f                   // if so, skip the comment
1185         cmpb $' ',%al
1186         jbe 1b                  // if so, keep looking
1187
1188         /* Search for the end of the word, storing chars as we go. */
1189         mov $5f,%edi            // pointer to return buffer
1190 2:
1191         stosb                   // add character to return buffer
1192         call _KEY               // get next key, returned in %al
1193         cmpb $' ',%al           // is blank?
1194         ja 2b                   // if not, keep looping
1195
1196         /* Return the word (well, the static buffer) and length. */
1197         sub $5f,%edi
1198         mov %edi,%ecx           // return length of the word
1199         mov $5f,%edi            // return address of the word
1200         ret
1201
1202         /* Code to skip \ comments to end of the current line. */
1203 3:
1204         call _KEY
1205         cmpb $'\n',%al          // end of line yet?
1206         jne 3b
1207         jmp 1b
1208
1209         .bss
1210         // A static buffer where WORD returns.  Subsequent calls
1211         // overwrite this buffer.  Maximum word length is 32 chars.
1212 5:      .space 32
1213
1214 /*
1215         . (also called DOT) prints the top of the stack as an integer.  In real FORTH implementations
1216         it should print it in the current base, but this assembler version is simpler and can only
1217         print in base 10.
1218
1219         Remember that you can override even built-in FORTH words easily, so if you want to write a
1220         more advanced DOT then you can do so easily at a later point, and probably in FORTH.
1221 */
1222
1223         defcode ".",1,,DOT
1224         pop %eax                // Get the number to print into %eax
1225         call _DOT               // Easier to do this recursively ...
1226         NEXT
1227 _DOT:
1228         mov $10,%ecx            // Base 10
1229 1:
1230         cmp %ecx,%eax
1231         jb 2f
1232         xor %edx,%edx           // %edx:%eax / %ecx -> quotient %eax, remainder %edx
1233         idivl %ecx
1234         pushl %edx
1235         call _DOT
1236         popl %eax
1237         jmp 1b
1238 2:
1239         xor %ah,%ah
1240         aam $10
1241         cwde
1242         addl $'0',%eax
1243         call _EMIT
1244         ret
1245
1246 /*
1247         Almost the opposite of DOT (but not quite), SNUMBER parses a numeric string such as one returned
1248         by WORD and pushes the number on the parameter stack.
1249
1250         This function does absolutely no error checking, and in particular the length of the string
1251         must be >= 1 bytes, and should contain only digits 0-9.  If it doesn't you'll get random results.
1252
1253         This function is only used when reading literal numbers in code, and shouldn't really be used
1254         in user code at all.
1255 */
1256         defcode "SNUMBER",7,,SNUMBER
1257         pop %edi
1258         pop %ecx
1259         call _SNUMBER
1260         push %eax
1261         NEXT
1262 _SNUMBER:
1263         xor %eax,%eax
1264         xor %ebx,%ebx
1265 1:
1266         imull $10,%eax          // %eax *= 10
1267         movb (%edi),%bl
1268         inc %edi
1269         subb $'0',%bl           // ASCII -> digit
1270         add %ebx,%eax
1271         dec %ecx
1272         jnz 1b
1273         ret
1274
1275 /*
1276         DICTIONARY LOOK UPS ----------------------------------------------------------------------
1277
1278         We're building up to our prelude on how FORTH code is compiled, but first we need yet more infrastructure.
1279
1280         The FORTH word FIND takes a string (a word as parsed by WORD -- see above) and looks it up in the
1281         dictionary.  What it actually returns is the address of the dictionary header, if it finds it,
1282         or 0 if it didn't.
1283
1284         So if DOUBLE is defined in the dictionary, then WORD DOUBLE FIND returns the following pointer:
1285
1286     pointer to this
1287         |
1288         |
1289         V
1290         +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+
1291         | LINK    | 6 | D | O | U | B | L | E | 0 | DOCOL      | DUP        | +          | EXIT       |
1292         +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+
1293
1294         See also >CFA which takes a dictionary entry pointer and returns a pointer to the codeword.
1295
1296         FIND doesn't find dictionary entries which are flagged as HIDDEN.  See below for why.
1297 */
1298
1299         defcode "FIND",4,,FIND
1300         pop %edi                // %edi = address
1301         pop %ecx                // %ecx = length
1302         call _FIND
1303         push %eax
1304         NEXT
1305
1306 _FIND:
1307         push %esi               // Save %esi so we can use it in string comparison.
1308
1309         // Now we start searching backwards through the dictionary for this word.
1310         mov var_LATEST,%edx     // LATEST points to name header of the latest word in the dictionary
1311 1:
1312         test %edx,%edx          // NULL pointer?  (end of the linked list)
1313         je 4f
1314
1315         // Compare the length expected and the length of the word.
1316         // Note that if the F_HIDDEN flag is set on the word, then by a bit of trickery
1317         // this won't pick the word (the length will appear to be wrong).
1318         xor %eax,%eax
1319         movb 4(%edx),%al        // %al = flags+length field
1320         andb $(F_HIDDEN|0x1f),%al // %al = name length
1321         cmpb %cl,%al            // Length is the same?
1322         jne 2f
1323
1324         // Compare the strings in detail.
1325         push %ecx               // Save the length
1326         push %edi               // Save the address (repe cmpsb will move this pointer)
1327         lea 5(%edx),%esi        // Dictionary string we are checking against.
1328         repe cmpsb              // Compare the strings.
1329         pop %edi
1330         pop %ecx
1331         jne 2f                  // Not the same.
1332
1333         // The strings are the same - return the header pointer in %eax
1334         pop %esi
1335         mov %edx,%eax
1336         ret
1337
1338 2:
1339         mov (%edx),%edx         // Move back through the link field to the previous word
1340         jmp 1b                  // .. and loop.
1341
1342 4:      // Not found.
1343         pop %esi
1344         xor %eax,%eax           // Return zero to indicate not found.
1345         ret
1346
1347 /*
1348         FIND returns the dictionary pointer, but when compiling we need the codeword pointer (recall
1349         that FORTH definitions are compiled into lists of codeword pointers).  The standard FORTH
1350         word >CFA turns a dictionary pointer into a codeword pointer.
1351
1352         The example below shows the result of:
1353
1354                 WORD DOUBLE FIND >CFA
1355
1356         FIND returns a pointer to this
1357         |                               >CFA converts it to a pointer to this
1358         |                                          |
1359         V                                          V
1360         +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+
1361         | LINK    | 6 | D | O | U | B | L | E | 0 | DOCOL      | DUP        | +          | EXIT       |
1362         +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+
1363
1364         Notes:
1365
1366         Because names vary in length, this isn't just a simple increment.
1367
1368         In this FORTH you cannot easily turn a codeword pointer back into a dictionary entry pointer, but
1369         that is not true in most FORTH implementations where they store a back pointer in the definition
1370         (with an obvious memory/complexity cost).  The reason they do this is that it is useful to be
1371         able to go backwards (codeword -> dictionary entry) in order to decompile FORTH definitions.
1372
1373         What does CFA stand for?  My best guess is "Code Field Address".
1374 */
1375
1376         defcode ">CFA",4,,TCFA
1377         pop %edi
1378         call _TCFA
1379         push %edi
1380         NEXT
1381 _TCFA:
1382         xor %eax,%eax
1383         add $4,%edi             // Skip link pointer.
1384         movb (%edi),%al         // Load flags+len into %al.
1385         inc %edi                // Skip flags+len byte.
1386         andb $0x1f,%al          // Just the length, not the flags.
1387         add %eax,%edi           // Skip the name.
1388         addl $3,%edi            // The codeword is 4-byte aligned.
1389         andl $~3,%edi
1390         ret
1391
1392 /*
1393         COMPILING ----------------------------------------------------------------------
1394
1395         Now we'll talk about how FORTH compiles words.  Recall that a word definition looks like this:
1396
1397                 : DOUBLE DUP + ;
1398
1399         and we have to turn this into:
1400
1401           pointer to previous word
1402            ^
1403            |
1404         +--|------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+
1405         | LINK    | 6 | D | O | U | B | L | E | 0 | DOCOL      | DUP        | +          | EXIT       |
1406         +---------+---+---+---+---+---+---+---+---+------------+--|---------+------------+------------+
1407            ^       len                         pad  codeword      |
1408            |                                                      V
1409           LATEST points here                            points to codeword of DUP
1410
1411         There are several problems to solve.  Where to put the new word?  How do we read words?  How
1412         do we define the words : (COLON) and ; (SEMICOLON)?
1413
1414         FORTH solves this rather elegantly and as you might expect in a very low-level way which
1415         allows you to change how the compiler works on your own code.
1416
1417         FORTH has an INTERPRETER function (a true interpreter this time, not DOCOL) which runs in a
1418         loop, reading words (using WORD), looking them up (using FIND), turning them into codeword
1419         pointers (using >CFA) and deciding what to do with them.
1420
1421         What it does depends on the mode of the interpreter (in variable STATE).
1422
1423         When STATE is zero, the interpreter just runs each word as it looks them up.  This is known as
1424         immediate mode.
1425
1426         The interesting stuff happens when STATE is non-zero -- compiling mode.  In this mode the
1427         interpreter appends the codeword pointer to user memory (the HERE variable points to the next
1428         free byte of user memory).
1429
1430         So you may be able to see how we could define : (COLON).  The general plan is:
1431
1432         (1) Use WORD to read the name of the function being defined.
1433
1434         (2) Construct the dictionary entry -- just the header part -- in user memory:
1435
1436     pointer to previous word (from LATEST)                      +-- Afterwards, HERE points here, where
1437            ^                                                    |   the interpreter will start appending
1438            |                                                    V   codewords.
1439         +--|------+---+---+---+---+---+---+---+---+------------+
1440         | LINK    | 6 | D | O | U | B | L | E | 0 | DOCOL      |
1441         +---------+---+---+---+---+---+---+---+---+------------+
1442                    len                         pad  codeword
1443
1444         (3) Set LATEST to point to the newly defined word, ...
1445
1446         (4) .. and most importantly leave HERE pointing just after the new codeword.  This is where
1447             the interpreter will append codewords.
1448
1449         (5) Set STATE to 1.  This goes into compile mode so the interpreter starts appending codewords to
1450             our partially-formed header.
1451
1452         After : has run, our input is here:
1453
1454         : DOUBLE DUP + ;
1455                  ^
1456                  |
1457                 Next byte returned by KEY
1458
1459         so the interpreter (now it's in compile mode, so I guess it's really the compiler) reads DUP,
1460         gets its codeword pointer, and appends it:
1461
1462                                                                              +-- HERE updated to point here.
1463                                                                              |
1464                                                                              V
1465         +---------+---+---+---+---+---+---+---+---+------------+------------+
1466         | LINK    | 6 | D | O | U | B | L | E | 0 | DOCOL      | DUP        |
1467         +---------+---+---+---+---+---+---+---+---+------------+------------+
1468                    len                         pad  codeword
1469
1470         Next we read +, get the codeword pointer, and append it:
1471
1472                                                                                           +-- HERE updated to point here.
1473                                                                                           |
1474                                                                                           V
1475         +---------+---+---+---+---+---+---+---+---+------------+------------+------------+
1476         | LINK    | 6 | D | O | U | B | L | E | 0 | DOCOL      | DUP        | +          |
1477         +---------+---+---+---+---+---+---+---+---+------------+------------+------------+
1478                    len                         pad  codeword
1479
1480         The issue is what happens next.  Obviously what we _don't_ want to happen is that we
1481         read ";" and compile it and go on compiling everything afterwards.
1482
1483         At this point, FORTH uses a trick.  Remember the length byte in the dictionary definition
1484         isn't just a plain length byte, but can also contain flags.  One flag is called the
1485         IMMEDIATE flag (F_IMMED in this code).  If a word in the dictionary is flagged as
1486         IMMEDIATE then the interpreter runs it immediately _even if it's in compile mode_.
1487
1488         I hope I don't need to explain that ; (SEMICOLON) is just such a word, flagged as IMMEDIATE.
1489         And all it does is append the codeword for EXIT on to the current definition and switch
1490         back to immediate mode (set STATE back to 0).  Shortly we'll see the actual definition
1491         of ; and we'll see that it's really a very simple definition, declared IMMEDIATE.
1492
1493         After the interpreter reads ; and executes it 'immediately', we get this:
1494
1495         +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+
1496         | LINK    | 6 | D | O | U | B | L | E | 0 | DOCOL      | DUP        | +          | EXIT       |
1497         +---------+---+---+---+---+---+---+---+---+------------+------------+------------+------------+
1498                    len                         pad  codeword                                           ^
1499                                                                                                        |
1500                                                                                                       HERE
1501
1502         STATE is set to 0.
1503
1504         And that's it, job done, our new definition is compiled, and we're back in immediate mode
1505         just reading and executing words, perhaps including a call to test our new word DOUBLE.
1506
1507         The only last wrinkle in this is that while our word was being compiled, it was in a
1508         half-finished state.  We certainly wouldn't want DOUBLE to be called somehow during
1509         this time.  There are several ways to stop this from happening, but in FORTH what we
1510         do is flag the word with the HIDDEN flag (F_HIDDEN in this code) just while it is
1511         being compiled.  This prevents FIND from finding it, and thus in theory stops any
1512         chance of it being called.
1513
1514         Compared to the description above, the actual definition of : (COLON) is comparatively simple:
1515 */
1516
1517         defcode ":",1,,COLON
1518
1519         // Get the word and create a dictionary entry header for it.
1520         call _WORD              // Returns %ecx = length, %edi = pointer to word.
1521         mov %edi,%ebx           // %ebx = address of the word
1522
1523         movl var_HERE,%edi      // %edi is the address of the header
1524         movl var_LATEST,%eax    // Get link pointer
1525         stosl                   // and store it in the header.
1526
1527         mov %cl,%al             // Get the length.
1528         orb $F_HIDDEN,%al       // Set the HIDDEN flag on this entry.
1529         stosb                   // Store the length/flags byte.
1530         push %esi
1531         mov %ebx,%esi           // %esi = word
1532         rep movsb               // Copy the word
1533         pop %esi
1534         addl $3,%edi            // Align to next 4 byte boundary.
1535         andl $~3,%edi
1536
1537         movl $DOCOL,%eax        // The codeword for user-created words is always DOCOL (the interpreter)
1538         stosl
1539
1540         // Header built, so now update LATEST and HERE.
1541         // We'll be compiling words and putting them HERE.
1542         movl var_HERE,%eax
1543         movl %eax,var_LATEST
1544         movl %edi,var_HERE
1545
1546         // And go into compile mode by setting STATE to 1.
1547         movl $1,var_STATE
1548         NEXT
1549
1550 /*
1551         , (COMMA) is a standard FORTH word which appends a 32 bit integer (normally a codeword
1552         pointer) to the user data area pointed to by HERE, and adds 4 to HERE.
1553 */
1554
1555         defcode ",",1,,COMMA
1556         pop %eax                // Code pointer to store.
1557         call _COMMA
1558         NEXT
1559 _COMMA:
1560         movl var_HERE,%edi      // HERE
1561         stosl                   // Store it.
1562         movl %edi,var_HERE      // Update HERE (incremented)
1563         ret
1564
1565 /*
1566         ; (SEMICOLON) is also elegantly simple.  Notice the F_IMMED flag.
1567 */
1568
1569         defcode ";",1,F_IMMED,SEMICOLON
1570         movl $EXIT,%eax         // EXIT is the final codeword in compiled words.
1571         call _COMMA             // Store it.
1572         call _HIDDEN            // Toggle the HIDDEN flag (unhides the new word).
1573         xor %eax,%eax           // Set STATE to 0 (back to execute mode).
1574         movl %eax,var_STATE
1575         NEXT
1576
1577 /*
1578         EXTENDING THE COMPILER ----------------------------------------------------------------------
1579
1580         Words flagged with IMMEDIATE (F_IMMED) aren't just for the FORTH compiler to use.  You can define
1581         your own IMMEDIATE words too, and this is a crucial aspect when extending basic FORTH, because
1582         it allows you in effect to extend the compiler itself.  Does gcc let you do that?
1583
1584         Standard FORTH words like IF, WHILE, .", [ and so on are all written as extensions to the basic
1585         compiler, and are all IMMEDIATE words.
1586
1587         The IMMEDIATE word toggles the F_IMMED (IMMEDIATE flag) on the most recently defined word,
1588         or on the current word if you call it in the middle of a definition.
1589
1590         Typical usage is:
1591
1592         : MYIMMEDWORD IMMEDIATE
1593                 ...definition...
1594         ;
1595
1596         but some FORTH programmers write this instead:
1597
1598         : MYIMMEDWORD
1599                 ...definition...
1600         ; IMMEDIATE
1601
1602         The two usages are equivalent, to a first approximation.
1603 */
1604
1605         defcode "IMMEDIATE",9,F_IMMED,IMMEDIATE
1606         call _IMMEDIATE
1607         NEXT
1608 _IMMEDIATE:
1609         movl var_LATEST,%edi    // LATEST word.
1610         addl $4,%edi            // Point to name/flags byte.
1611         xorb $F_IMMED,(%edi)    // Toggle the IMMED bit.
1612         ret
1613
1614 /*
1615         HIDDEN toggles the other flag, F_HIDDEN, of the latest word.  Note that words flagged
1616         as hidden are defined but cannot be called, so this is rarely used.
1617 */
1618
1619         defcode "HIDDEN",6,,HIDDEN
1620         call _HIDDEN
1621         NEXT
1622 _HIDDEN:
1623         movl var_LATEST,%edi    // LATEST word.
1624         addl $4,%edi            // Point to name/flags byte.
1625         xorb $F_HIDDEN,(%edi)   // Toggle the HIDDEN bit.
1626         ret
1627
1628 /*
1629         ' (TICK) is a standard FORTH word which returns the codeword pointer of the next word.
1630
1631         The common usage is:
1632
1633         ' FOO ,
1634
1635         which appends the codeword of FOO to the current word we are defining (this only works in compiled code).
1636
1637         You tend to use ' in IMMEDIATE words.  For example an alternate (and rather useless) way to define
1638         a literal 2 might be:
1639
1640         : LIT2 IMMEDIATE
1641                 ' LIT ,         \ Appends LIT to the currently-being-defined word
1642                 2 ,             \ Appends the number 2 to the currently-being-defined word
1643         ;
1644
1645         So you could do:
1646
1647         : DOUBLE LIT2 * ;
1648
1649         (If you don't understand how LIT2 works, then you should review the material about compiling words
1650         and immediate mode).
1651
1652         This definition of ' uses a cheat which I copied from buzzard92.  As a result it only works in
1653         compiled code.  It is possible to write a version of ' based on WORD, FIND, >CFA which works in
1654         immediate mode too.
1655 */
1656         defcode "'",1,,TICK
1657         lodsl                   // Get the address of the next word and skip it.
1658         pushl %eax              // Push it on the stack.
1659         NEXT
1660
1661 /*
1662         BRANCHING ----------------------------------------------------------------------
1663
1664         It turns out that all you need in order to define looping constructs, IF-statements, etc.
1665         are two primitives.
1666
1667         BRANCH is an unconditional branch. 0BRANCH is a conditional branch (it only branches if the
1668         top of stack is zero).
1669
1670         The diagram below shows how BRANCH works in some imaginary compiled word.  When BRANCH executes,
1671         %esi starts by pointing to the offset field (compare to LIT above):
1672
1673         +---------------------+-------+---- - - ---+------------+------------+---- - - - ----+------------+
1674         | (Dictionary header) | DOCOL |            | BRANCH     | offset     | (skipped)     | word       |
1675         +---------------------+-------+---- - - ---+------------+-----|------+---- - - - ----+------------+
1676                                                                    ^  |                       ^
1677                                                                    |  |                       |
1678                                                                    |  +-----------------------+
1679                                                                   %esi added to offset
1680
1681         The offset is added to %esi to make the new %esi, and the result is that when NEXT runs, execution
1682         continues at the branch target.  Negative offsets work as expected.
1683
1684         0BRANCH is the same except the branch happens conditionally.
1685
1686         Now standard FORTH words such as IF, THEN, ELSE, WHILE, REPEAT, etc. can be implemented entirely
1687         in FORTH.  They are IMMEDIATE words which append various combinations of BRANCH or 0BRANCH
1688         into the word currently being compiled.
1689
1690         As an example, code written like this:
1691
1692                 condition-code IF true-part THEN rest-code
1693
1694         compiles to:
1695
1696                 condition-code 0BRANCH OFFSET true-part rest-code
1697                                           |             ^
1698                                           |             |
1699                                           +-------------+
1700 */
1701
1702         defcode "BRANCH",6,,BRANCH
1703         add (%esi),%esi         // add the offset to the instruction pointer
1704         NEXT
1705
1706         defcode "0BRANCH",7,,ZBRANCH
1707         pop %eax
1708         test %eax,%eax          // top of stack is zero?
1709         jz code_BRANCH          // if so, jump back to the branch function above
1710         lodsl                   // otherwise we need to skip the offset
1711         NEXT
1712
1713 /*
1714         PRINTING STRINGS ----------------------------------------------------------------------
1715
1716         LITSTRING and EMITSTRING are primitives used to implement the ." operator (which is
1717         written in FORTH).  See the definition of that operator below.
1718 */
1719
1720         defcode "LITSTRING",9,,LITSTRING
1721         lodsl                   // get the length of the string
1722         push %eax               // push it on the stack
1723         push %esi               // push the address of the start of the string
1724         addl %eax,%esi          // skip past the string
1725         addl $3,%esi            // but round up to next 4 byte boundary
1726         andl $~3,%esi
1727         NEXT
1728
1729         defcode "EMITSTRING",10,,EMITSTRING
1730         mov $1,%ebx             // 1st param: stdout
1731         pop %ecx                // 2nd param: address of string
1732         pop %edx                // 3rd param: length of string
1733         mov $__NR_write,%eax    // write syscall
1734         int $0x80
1735         NEXT
1736
1737 /*
1738         COLD START AND INTERPRETER ----------------------------------------------------------------------
1739
1740         COLD is the first FORTH function called, almost immediately after the FORTH system "boots".
1741
1742         INTERPRETER is the FORTH interpreter ("toploop", "toplevel" or "REPL" might be a more accurate
1743         description -- see: http://en.wikipedia.org/wiki/REPL).
1744 */
1745
1746
1747         // COLD must not return (ie. must not call EXIT).
1748         defword "COLD",4,,COLD
1749         .int INTERPRETER        // call the interpreter loop (never returns)
1750         .int LIT,1,SYSEXIT      // hmmm, but in case it does, exit(1).
1751
1752 /* This interpreter is pretty simple, but remember that in FORTH you can always override
1753  * it later with a more powerful one!
1754  */
1755         defword "INTERPRETER",11,,INTERPRETER
1756         .int INTERPRET,RDROP,INTERPRETER
1757
1758         defcode "INTERPRET",9,,INTERPRET
1759         call _WORD              // Returns %ecx = length, %edi = pointer to word.
1760
1761         // Is it in the dictionary?
1762         xor %eax,%eax
1763         movl %eax,interpret_is_lit // Not a literal number (not yet anyway ...)
1764         call _FIND              // Returns %eax = pointer to header or 0 if not found.
1765         test %eax,%eax          // Found?
1766         jz 1f
1767
1768         // In the dictionary.  Is it an IMMEDIATE codeword?
1769         mov %eax,%edi           // %edi = dictionary entry
1770         movb 4(%edi),%al        // Get name+flags.
1771         push %ax                // Just save it for now.
1772         call _TCFA              // Convert dictionary entry (in %edi) to codeword pointer.
1773         pop %ax
1774         andb $F_IMMED,%al       // Is IMMED flag set?
1775         mov %edi,%eax
1776         jnz 4f                  // If IMMED, jump straight to executing.
1777
1778         jmp 2f
1779
1780 1:      // Not in the dictionary (not a word) so assume it's a literal number.
1781         incl interpret_is_lit
1782         call _SNUMBER           // Returns the parsed number in %eax
1783         mov %eax,%ebx
1784         mov $LIT,%eax           // The word is LIT
1785
1786 2:      // Are we compiling or executing?
1787         movl var_STATE,%edx
1788         test %edx,%edx
1789         jz 4f                   // Jump if executing.
1790
1791         // Compiling - just append the word to the current dictionary definition.
1792         call _COMMA
1793         mov interpret_is_lit,%ecx // Was it a literal?
1794         test %ecx,%ecx
1795         jz 3f
1796         mov %ebx,%eax           // Yes, so LIT is followed by a number.
1797         call _COMMA
1798 3:      NEXT
1799
1800 4:      // Executing - run it!
1801         mov interpret_is_lit,%ecx // Literal?
1802         test %ecx,%ecx          // Literal?
1803         jnz 5f
1804
1805         // Not a literal, execute it now.  This never returns, but the codeword will
1806         // eventually call NEXT which will reenter the loop in INTERPRETER.
1807         jmp *(%eax)
1808
1809 5:      // Executing a literal, which means push it on the stack.
1810         push %ebx
1811         NEXT
1812
1813         .data
1814         .align 4
1815 interpret_is_lit:
1816         .int 0                  // Flag used to record if reading a literal
1817
1818 /*
1819         ODDS AND ENDS ----------------------------------------------------------------------
1820
1821         CHAR puts the ASCII code of the first character of the following word on the stack.  For example
1822         CHAR A puts 65 on the stack.
1823
1824         SYSEXIT exits the process using Linux exit syscall.
1825 */
1826
1827         defcode "CHAR",4,,CHAR
1828         call _WORD              // Returns %ecx = length, %edi = pointer to word.
1829         xor %eax,%eax
1830         movb (%edi),%al         // Get the first character of the word.
1831         push %eax               // Push it onto the stack.
1832         NEXT
1833
1834         // NB: SYSEXIT must be the last entry in the built-in dictionary.
1835         defcode SYSEXIT,7,,SYSEXIT
1836         pop %ebx
1837         mov $__NR_exit,%eax
1838         int $0x80
1839
1840 /*
1841         START OF FORTH CODE ----------------------------------------------------------------------
1842
1843         We've now reached the stage where the FORTH system is running and self-hosting.  All further
1844         words can be written as FORTH itself, including words like IF, THEN, .", etc which in most
1845         languages would be considered rather fundamental.
1846
1847         As a kind of trick, I prefill the input buffer with the initial FORTH code.  Once this code
1848         has run (when we get to the "OK" prompt), this input buffer is reused for reading any further
1849         user input.
1850
1851         Some notes about the code:
1852
1853         \ (backslash) is the FORTH way to start a comment which goes up to the next newline.  However
1854         because this is a C-style string, I have to escape the backslash, which is why they appear as
1855         \\ comment.
1856
1857         Similarly, any backslashes in the code are doubled, and " becomes \" (eg. the definition of ."
1858         is written as : .\" ... ;)
1859
1860         I use indenting to show structure.  The amount of whitespace has no meaning to FORTH however
1861         except that you must use at least one whitespace character between words, and words themselves
1862         cannot contain whitespace.
1863
1864         FORTH is case-sensitive.  Use capslock!
1865
1866         Enjoy!
1867 */
1868
1869         .data
1870         .align 4096
1871 buffer:
1872         // Multi-line constant gives 'Warning: unterminated string; newline inserted' messages which you can ignore.
1873         .ascii "\
1874 \\ Define some character constants
1875 : '\\n'   10 ;
1876 : 'SPACE' 32 ;
1877 : '\"'    34 ;
1878 : ':'     58 ;
1879
1880 \\ CR prints a carriage return
1881 : CR '\\n' EMIT ;
1882
1883 \\ SPACE prints a space
1884 : SPACE 'SPACE' EMIT ;
1885
1886 \\ Primitive . (DOT) function doesn't follow with a blank, so redefine it to behave like FORTH.
1887 \\ Notice how we can trivially redefine existing functions.
1888 : . . SPACE ;
1889
1890 \\ DUP, DROP are defined in assembly for speed, but this is how you might define them
1891 \\ in FORTH.  Notice use of the scratch variables _X and _Y.
1892 \\ : DUP _X ! _X @ _X @ ;
1893 \\ : DROP _X ! ;
1894
1895 \\ The 2... versions of the standard operators work on pairs of stack entries.  They're not used
1896 \\ very commonly so not really worth writing in assembler.  Here is how they are defined in FORTH.
1897 : 2DUP OVER OVER ;
1898 : 2DROP DROP DROP ;
1899
1900 \\ More standard FORTH words.
1901 : 2* 2 * ;
1902 : 2/ 2 / ;
1903
1904 \\ [ and ] allow you to break into immediate mode while compiling a word.
1905 : [ IMMEDIATE           \\ define [ as an immediate word
1906         0 STATE !       \\ go into immediate mode
1907         ;
1908
1909 : ]
1910         1 STATE !       \\ go back to compile mode
1911         ;
1912
1913 \\ LITERAL takes whatever is on the stack and compiles LIT <foo>
1914 : LITERAL IMMEDIATE
1915         ' LIT ,         \\ compile LIT
1916         ,               \\ compile the literal itself (from the stack)
1917         ;
1918
1919 \\ condition IF true-part THEN rest
1920 \\   compiles to:
1921 \\ condition 0BRANCH OFFSET true-part rest
1922 \\   where OFFSET is the offset of 'rest'
1923 \\ condition IF true-part ELSE false-part THEN
1924 \\   compiles to:
1925 \\ condition 0BRANCH OFFSET true-part BRANCH OFFSET2 false-part rest
1926 \\   where OFFSET if the offset of false-part and OFFSET2 is the offset of rest
1927
1928 \\ IF is an IMMEDIATE word which compiles 0BRANCH followed by a dummy offset, and places
1929 \\ the address of the 0BRANCH on the stack.  Later when we see THEN, we pop that address
1930 \\ off the stack, calculate the offset, and back-fill the offset.
1931 : IF IMMEDIATE
1932         ' 0BRANCH ,     \\ compile 0BRANCH
1933         HERE @          \\ save location of the offset on the stack
1934         0 ,             \\ compile a dummy offset
1935 ;
1936
1937 : THEN IMMEDIATE
1938         DUP
1939         HERE @ SWAP -   \\ calculate the offset from the address saved on the stack
1940         SWAP !          \\ store the offset in the back-filled location
1941 ;
1942
1943 : ELSE IMMEDIATE
1944         ' BRANCH ,      \\ definite branch to just over the false-part
1945         HERE @          \\ save location of the offset on the stack
1946         0 ,             \\ compile a dummy offset
1947         SWAP            \\ now back-fill the original (IF) offset
1948         DUP             \\ same as for THEN word above
1949         HERE @ SWAP -
1950         SWAP !
1951 ;
1952
1953 \\ BEGIN loop-part condition UNTIL
1954 \\   compiles to:
1955 \\ loop-part condition 0BRANCH OFFSET
1956 \\   where OFFSET points back to the loop-part
1957 \\ This is like do { loop-part } while (condition) in the C language
1958 : BEGIN IMMEDIATE
1959         HERE @          \\ save location on the stack
1960 ;
1961
1962 : UNTIL IMMEDIATE
1963         ' 0BRANCH ,     \\ compile 0BRANCH
1964         HERE @ -        \\ calculate the offset from the address saved on the stack
1965         ,               \\ compile the offset here
1966 ;
1967
1968 \\ BEGIN loop-part AGAIN
1969 \\   compiles to:
1970 \\ loop-part BRANCH OFFSET
1971 \\   where OFFSET points back to the loop-part
1972 \\ In other words, an infinite loop which can only be returned from with EXIT
1973 : AGAIN IMMEDIATE
1974         ' BRANCH ,      \\ compile BRANCH
1975         HERE @ -        \\ calculate the offset back
1976         ,               \\ compile the offset here
1977 ;
1978
1979 \\ BEGIN condition WHILE loop-part REPEAT
1980 \\   compiles to:
1981 \\ condition 0BRANCH OFFSET2 loop-part BRANCH OFFSET
1982 \\   where OFFSET points back to condition (the beginning) and OFFSET2 points to after the whole piece of code
1983 \\ So this is like a while (condition) { loop-part } loop in the C language
1984 : WHILE IMMEDIATE
1985         ' 0BRANCH ,     \\ compile 0BRANCH
1986         HERE @          \\ save location of the offset2 on the stack
1987         0 ,             \\ compile a dummy offset2
1988 ;
1989
1990 : REPEAT IMMEDIATE
1991         ' BRANCH ,      \\ compile BRANCH
1992         SWAP            \\ get the original offset (from BEGIN)
1993         HERE @ - ,      \\ and compile it after BRANCH
1994         DUP
1995         HERE @ SWAP -   \\ calculate the offset2
1996         SWAP !          \\ and back-fill it in the original location
1997 ;
1998
1999 \\ With the looping constructs, we can now write SPACES, which writes n spaces to stdout.
2000 : SPACES
2001         BEGIN
2002                 SPACE   \\ print a space
2003                 1-      \\ until we count down to 0
2004                 DUP 0=
2005         UNTIL
2006 ;
2007
2008 \\ .S prints the contents of the stack.  Very useful for debugging.
2009 : .S
2010         DSP@            \\ get current stack pointer
2011         BEGIN
2012                 DUP @ .         \\ print the stack element
2013                 4+              \\ move up
2014                 DUP S0 @ 4- =   \\ stop when we get to the top
2015         UNTIL
2016         DROP
2017 ;
2018
2019 \\ DEPTH returns the depth of the stack.
2020 : DEPTH S0 @ DSP@ - ;
2021
2022 \\ .\" is the print string operator in FORTH.  Example: .\" Something to print\"
2023 \\ The space after the operator is the ordinary space required between words.
2024 \\ This is tricky to define because it has to do different things depending on whether
2025 \\ we are compiling or in immediate mode.  (Thus the word is marked IMMEDIATE so it can
2026 \\ detect this and do different things).
2027 \\ In immediate mode we just keep reading characters and printing them until we get to
2028 \\ the next double quote.
2029 \\ In compile mode we have the problem of where we're going to store the string (remember
2030 \\ that the input buffer where the string comes from may be overwritten by the time we
2031 \\ come round to running the function).  We store the string in the compiled function
2032 \\ like this:
2033 \\   ..., LITSTRING, string length, string rounded up to 4 bytes, EMITSTRING, ...
2034 : .\" IMMEDIATE
2035         STATE @         \\ compiling?
2036         IF
2037                 ' LITSTRING ,   \\ compile LITSTRING
2038                 HERE @          \\ save the address of the length word on the stack
2039                 0 ,             \\ dummy length - we don't know what it is yet
2040                 BEGIN
2041                         KEY             \\ get next character of the string
2042                         DUP '\"' <>
2043                 WHILE
2044                         HERE @ !b       \\ store the character in the compiled image
2045                         1 HERE +!       \\ increment HERE pointer by 1 byte
2046                 REPEAT
2047                 DROP            \\ drop the double quote character at the end
2048                 DUP             \\ get the saved address of the length word
2049                 HERE @ SWAP -   \\ calculate the length
2050                 4-              \\ subtract 4 (because we measured from the start of the length word)
2051                 SWAP !          \\ and back-fill the length location
2052                 HERE @          \\ round up to next multiple of 4 bytes for the remaining code
2053                 3 +
2054                 3 INVERT AND
2055                 HERE !
2056                 ' EMITSTRING ,  \\ compile the final EMITSTRING
2057         ELSE
2058                 \\ In immediate mode, just read characters and print them until we get
2059                 \\ to the ending double quote.  Much simpler than the above code!
2060                 BEGIN
2061                         KEY
2062                         DUP '\"' = IF EXIT THEN
2063                         EMIT
2064                 AGAIN
2065         THEN
2066 ;
2067
2068 \\ While compiling, [COMPILE] WORD compiles WORD if it would otherwise be IMMEDIATE.
2069 : [COMPILE] IMMEDIATE
2070         WORD            \\ get the next word
2071         FIND            \\ find it in the dictionary
2072         >CFA            \\ get its codeword
2073         ,               \\ and compile that
2074 ;
2075
2076 \\ RECURSE makes a recursive call to the current word that is being compiled.
2077 \\ Normally while a word is being compiled, it is marked HIDDEN so that references to the
2078 \\ same word within are calls to the previous definition of the word.
2079 : RECURSE IMMEDIATE
2080         LATEST @ >CFA   \\ LATEST points to the word being compiled at the moment
2081         ,               \\ compile it
2082 ;
2083
2084 \\ ALLOT is used to allocate (static) memory when compiling.  It increases HERE by
2085 \\ the amount given on the stack.
2086 \\: ALLOT HERE +! ;
2087
2088
2089 \\ Finally print the welcome prompt.
2090 .\" JONESFORTH VERSION \" VERSION @ . CR
2091 .\" OK \"
2092 "
2093
2094 _initbufftop:
2095         .align 4096
2096 buffend:
2097
2098 currkey:
2099         .int buffer
2100 bufftop:
2101         .int _initbufftop
2102
2103 /* END OF jonesforth.S */