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