Implement "next" macro and add related notes
[rrq/jonasforth.git] / notes
1 FASM:
2 - https://flatassembler.net/docs.php?article=fasmg (Introduction)
3 - https://flatassembler.net/docs.php?article=fasmg_manual (Manual)
4 - https://flatassembler.net/docs.php?article=manual (Other manual)
5
6 JONESFORTH:
7 - https://github.com/nornagon/jonesforth/blob/master/jonesforth.S
8
9 # Notes on implementation
10
11 This is my summary of the most important parts of
12 https://raw.githubusercontent.com/nornagon/jonesforth/master/jonesforth.S.
13
14 ## Dictionary
15
16 In Forth, words are stored in a dictionary. The dictionary is a linked list whose entries look like this:
17     +------------------------+--------+---------- - - - - +----------- - - - -
18     | LINK POINTER           | LENGTH/| NAME              | DEFINITION
19     |                        | FLAGS  |                   |
20     +--- (4 bytes) ----------+- byte -+- n bytes  - - - - +----------- - - - -
21 For example, DOUBLE and QUADRUPLE may be stored like this:
22       pointer to previous word
23        ^
24        |
25     +--|------+---+---+---+---+---+---+---+---+------------- - - - -
26     | LINK    | 6 | D | O | U | B | L | E | 0 | (definition ...)
27     +---------+---+---+---+---+---+---+---+---+------------- - - - -
28        ^       len                         padding
29        |
30     +--|------+---+---+---+---+---+---+---+---+---+---+---+---+------------- - - - -
31     | LINK    | 9 | Q | U | A | D | R | U | P | L | E | 0 | 0 | (definition ...)
32     +---------+---+---+---+---+---+---+---+---+---+---+---+---+------------- - - - -
33        ^       len                                     padding
34        |
35        |
36   LATEST
37 The Forth variable LATEST contains a pointer to the most recently defined word.
38
39 ## Threaded code
40
41 In a typical Forth interpreter, code is stored in a peculiar way. (This way of
42 storing code is primarily motivated by space contraints on early systems.)
43
44 The definition of a word is stored as a sequence of memory adresses of each of
45 the words making up that definition. (At the end of a compiled definition, there
46 is also some extra code that causes execution to continue in the correct way.)
47
48 We use a register (ESI) to store a reference to the next index of the
49 word (inside a definition) that we are executing. Then, in order to execute a
50 word, we just jump to whatever address is pointed to by ESI. The code for
51 updating ESI and continuing execution is stored at the end of each subroutine.
52
53 Of course, this approach only works if each of the words that we are executing
54 is defined in assembly, but we also want to be able to execute Forth words!
55
56 We get around this problem by adding a "codeword" to the beginning of any
57 compiled subroutine. This codeword is a pointer to the intrepreter to run the
58 given function. In order to run such functions, we actually need two jumps when
59 executing: In order to execute a word, we jump to the address at the location
60 pointed to by the address in ESI.
61