1     I find it hard to believe that I've discovered a
     
2     bug in JonesFORTH, but it seems to me that my fix
     
3     of simply removing FETCH from colon so that the
     
4     word header that receives the HIDDEN flag is the
     
5     one being compiled, not the previous one in the
     
6     linked list (dictionary).
     
7 
     8         !!!!!!!!!!!!!!!!!!!! Update !!!!!!!!!!!!!!!!!!!!
     
9         ! In log19.txt, I realize that my variable     !
    
10         ! handling is wrong. Variables should leave    !
    
11         ! their addresses on the stack, not their      !
    
12         ! values! We need FETCH to get the value from  !
    
13         ! the address!                                 !
    
14         !!!!!!!!!!!!!!!!!!!! Update !!!!!!!!!!!!!!!!!!!!
    
15 
    16 
    17     So unless I discover otherwise, I've changed it
    
18     from
    
19 
    20         
    21         dd LATEST, FETCH, HIDDEN ; Make the word hidden while it's being compiled.
    
22 
    23     to
    
24 
    25         dd LATEST, HIDDEN ; Make the word hidden while it's being compiled.
    
26 
    27 (gdb) break code_LATEST
    
28 Breakpoint 2 at 0x804939d: file nasmjf.asm, line 772.
    
29 (gdb) c
    
30 Continuing.
    
31 : FIVE 5 ;
    
32 
    33 Breakpoint 2, code_LATEST () at nasmjf.asm:772
    
34 772             push dword [var_%4]
    
35 27          lodsd     ; NEXT: Load from memory into eax, inc esi to point to next word.
    
36 28          jmp [eax] ; Jump to whatever code we're now pointing at.
    
37 code_HIDDEN () at nasmjf.asm:636
    
38 636         pop edi                 ; Dictionary entry, first byte is link
    
39 637         add edi, 4              ; Move to name/flags byte.
    
40 
    41     If my fix works, then the word "FIVE" that is being compiled
    
42     will be the one we're hiding until compilation is complete:
    
43 
    44 (gdb) x/bx $edi
    
45 0x804e004:      0x04
    
46 (gdb) x/bt $edi
    
47 0x804e004:      00000100
    
48 (gdb) x/4c $edi+1
    
49 0x804e005:      70 'F'  73 'I'  86 'V'  69 'E'
    
50 
    51     Yup, looks good! And the hidden flag?
    
52 
    53 638         xor [edi], word F_HIDDEN  ; Toggle the HIDDEN bit in place.
    
54 (gdb) x/bt $edi
    
55 0x804e004:      00100100
    
56 
    57     Looks good also.
    
58 
    59     Next, let's implement BRANCH!
    
60     Turns out, it's another crazy simple "hack" with
    
61     the esi register (like LIT), this time, adding an
    
62     offset to esi itself to change which word NEXT
    
63     should execute next.
    
64 
    65 (gdb) break code_BRANCH
    
66 Breakpoint 2 at 0x804904e: file nasmjf.asm, line 237.
    
67 (gdb) c
    
68 Continuing.
    
69 : FIVE 5 ;
    
70 
    71 Breakpoint 2, code_BRANCH () at nasmjf.asm:237
    
72 237         add esi, [esi]          ; add the offset to the instruction pointer
    
73 
    74     The line above is the entirety of BRANCH! 
    
75     So before that line executes, esi should point
    
76     to the next "word" in the definition of QUIT, which
    
77     is actually not a word at all, but an offset to
    
78     add to the current value of esi itself.
    
79 
    80     So we should see QUIT + <some offset> in esi
    
81 
    82 (gdb) info sym $esi
    
83 QUIT + 20 in section .data of /home/dave/nasmjf/nasmjf
    
84 
    85     And the value at esi should be our negative offset, -8.
    
86 
    87 (gdb) p *$esi
    
88 $2 = -8
    
89 
    90     What will -8 branch to? Here's the entire definition
    
91     of QUIT:
    
92     
    93         DEFWORD "QUIT",4,0,QUIT
    
94         dd R0           ; push R0 (addr of top of return stack)
    
95         dd RSPSTORE     ; store R0 in return stack pointer (ebp)
    
96         dd INTERPRET    ; interpret the next word
    
97         dd BRANCH,-8    ; and loop (indefinitely)
    
98 
    99     esi was pointing at the "double" (4 bytes) containing
   
100     the value -8. Every word linked here is also 4 bytes.
   
101 
   102         esi   points to -8          (QUIT + 20)
   
103         esi-4 points to BRANCH      (QUIT + 16)
   
104         esi-8 points to INTERPRET   (QUIT + 12)
   
105 
   106     So BRANCH here makes a conditionless loop over INTERPRET.
   
107 
   108 (gdb) info sym $esi
   
109 QUIT + 12 in section .data of /home/dave/nasmjf/nasmjf
   
110 27          lodsd     ; NEXT: Load from memory into eax, inc esi to point to next word.
   
111 28          jmp [eax] ; Jump to whatever code we're now pointing at.
   
112 code_INTERPRET () at nasmjf.asm:244
   
113 244         call _WORD              ; Returns %ecx = length, %edi = pointer to word.
   
114 
   115     This is getting exciting. So we shoud be able to compile
   
116     a word and then execute it. Let's see if my "FIVE" literal
   
117     works:
   
118 
   119 (gdb) c
   
120 Continuing.
   
121 FIVE
   
122 PARSE ERROR: FIVE
   
123 
   124     Oh no! It didn't find FIVE. So something in the
   
125     compilation of ": FIVE 5 ;" isn't quite right yet.
   
126 
   127     Wait a dang second.
   
128 
   129     I've removed the FETCH so it's no longer setting the
   
130     wrong word header to hidden during compilation. But
   
131     I didn't make the same change in SEMICOLON (;) to
   
132     unhide the correct word!
   
133 
   134         dd LATEST, FETCH, HIDDEN ; Unhide word now that it's been compiled.
   
135 
   136     Removing the FETCH so we have
   
137 
   138         dd LATEST, HIDDEN ; Unhide word now that it's been compiled.
   
139 
   140     and let's see what happens.
   
141 
   142 (gdb) break code_INTERPRET
   
143 Breakpoint 2, code_INTERPRET () at nasmjf.asm:244
   
144 (gdb) c
   
145 Continuing.
   
146 : FIVE 5 ;
   
147 
   148 Breakpoint 2, code_INTERPRET () at nasmjf.asm:244
   
149 (gdb) c
   
150 Continuing.
   
151 FIVE
   
152 
   153 Breakpoint 2, code_INTERPRET () at nasmjf.asm:244
   
154 (gdb) p/x $esp
   
155 $3 = 0xbffff98c
   
156 (gdb) x/x $esp
   
157 0xbffff98c:     0x00000005
   
158 
   159     Using my compiled word FIVE put a 5 on the stack!
   
160     It works!
   
161 
   162     I think I've earned a bit of fun, so the next thing
   
163     I'll implement is EMIT, which will let me actually
   
164     display characters on the screen!