1     Okay, since the last log, the var_HERE typo has been
     
2     fixed. CREATE is now getting the adddress _at_ HERE, now
     
3     the address _of_ here. We'll test that in this log.
     
4 
     5     And the memory allocator is in. I moved from the bottom
     
6     where Jones had it up into _start where it's used. I get
     
7     why it could be considered distracting from the Forth
     
8     concepts. But it's short and important and this is my
     
9     port, so up
    
10     it goes.
    
11 
    12     We'll start by trying it out:
    
13 
    14 _start () at nasmjf.asm:101
    
15 101         xor ebx, ebx
    
16 102         mov eax, [__NR_brk]       ; syscall brk
    
17 
    18 Program received signal SIGSEGV, Segmentation fault.
    
19 
    20     Oops! __NR_brk is a NASM preprocessor assigned value,
    
21     not a runtime variable!
    
22 
    23 (gdb) load nasmjf
    
24 `/home/dave/nasmjf/nasmjf' has changed; re-reading symbols.
    
25 (gdb) r
    
26 Starting program: /home/dave/nasmjf/nasmjf
    
27 _start () at nasmjf.asm:101
    
28 101         xor ebx, ebx
    
29 102         mov eax, __NR_brk         ; syscall brk
    
30 103         int 0x80
    
31 (gdb) p/x $eax
    
32 $1 = 0x804e000
    
33 
    34     Okay, so we now have our old "break" address. By the way,
    
35     see the source for my explanation of how the brk syscall
    
36     works. A lot of man pages, web pages, and discussion are
    
37     about the C stdlib brk() and sbrk(), but those are NOT
    
38     identical in usage to the syscall!
    
39 
    40     Then we request a new break address which is 0x16000
    
41     bytes "larger" than the old one. When we do this, Linux
    
42     reserves the memory in between for us!
    
43 
    44 104         mov [var_HERE], eax       ; eax has start addr of data segment
    
45 105         add eax, 0x16000          ; add our desired number of bytes to break addr
    
46 106         mov ebx, eax              ; reserve memory by setting this new break addr
    
47 107         mov eax, __NR_brk         ; syscall brk again
    
48 108         int 0x80
    
49 (gdb) p/x $eax
    
50 $2 = 0x8064000
    
51 
    52     That looks right and means the new address means the
    
53     request succeeded.
    
54 
    55         previous break addr: 0x804e000
    
56                              + 0x16000
    
57              new break addr: 0x8064000
    
58 
    59     Now the rest of the startup continues.
    
60 
    61 112         mov esi, cold_start
    
62 27          lodsd     ; NEXT: Load from memory into eax, inc esi to point to next word.
    
63 28          jmp [eax] ; Jump to whatever code we're now pointing at.
    
64 
    65     It's time to see if the new memory allocation and the
    
66     var_HERE fix are working properly together to allow the
    
67     creation of new words in the dictionary.
    
68 
    69 (gdb) break code_CREATE
    
70 Breakpoint 3 at 0x8049251: file nasmjf.asm, line 559.
    
71 (gdb) c
    
72 Continuing.
    
73 : FIVE 5 ;
    
74 
    75 Breakpoint 3, code_CREATE () at nasmjf.asm:559
    
76 559         pop ecx                   ; length of word name
    
77 560         pop ebx                   ; address of word name
    
78 563         mov edi, [var_HERE]       ; the address of the header
    
79 (gdb) p/x (int)var_HERE
    
80 $4 = 0x804e000
    
81 
    82     Excellent, the address at HERE looks like the start of
    
83     the space we reserved (the original "break" address
    
84     and the new break address mark the start and end of the
    
85     data section we've reserved).
    
86 
    87     Now we're going to store the link to the last dictionary
    
88     word entry in LATEST as the first 4 bytes of the header
    
89     of the new FIVE word we're compiling right now.
    
90 
    91     LATEST should point to its own header (how I chose to do
    
92     it), which is labeled "name_LATEST":
    
93 
    94 564         mov eax, [var_LATEST]     ; get link pointer
    
95 565         stosd                     ; and store it in the header.
    
96 (gdb) p/x $eax
    
97 $6 = 0x804a3ac
    
98 (gdb) info sym $eax
    
99 name_LATEST in section .data of /home/dave/nasmjf/nasmjf
   
100 
   101     So far so good. We'll see if it stores it correctly in a
   
102     moment. Now we store the rest of the header:
   
103 
   104            -- Header With Name --
   
105         4 bytes - link to previous word <--- done
   
106         1 byte  - length of name + flags
   
107         N bytes - the ascii characters of the name
   
108         N bytes - possible empty space for 4 byte alignment
   
109            -- Code Body --
   
110         <link to DOCOL to "interpret" the rest>
   
111         <the rest of the word addresses>
   
112 
   113     Neither the header nor the body symbols (name_FIVE,
   
114     code_FIVE) will exist in GDB since they're now written
   
115     in NASM and there aren't any symbols for them in the
   
116     DWARF2 debugging information in the executable.
   
117     From now on, we're making words with real Forth!
   
118 
   119 568         mov al, cl                ; Get the length.
   
120 569         stosb                     ; Store the length/flags byte.
   
121 570         push esi
   
122 571         mov esi, ebx              ; esi = word
   
123 572         rep movsb                 ; Copy the word
   
124 573         pop esi
   
125 574         add edi, 3                ; Align to next 4 byte boundary. See TCFA
   
126 575         and edi, ~3
   
127 
   128     Okay, let's see if the header is correct. First, HERE
   
129     should still be pointing to the beginning of the new
   
130     word's header because we haven't update it yet.
   
131 
   132     And the very first thing in the header should be a link
   
133     to the previous word in the dictionary.
   
134 
   135 (gdb) x/xw (int)var_HERE
   
136 0x804e000:      0x0804a3ac
   
137 
   138     Yup, that looks like the address of name_LATEST we saw
   
139     earlier.
   
140 
   141     Next is the length plus flags. In this case, just
   
142     length. Which should be 4 for the characters in the
   
143     name "FIVE".
   
144 
   145 (gdb) x/xb (int)var_HERE + 4
   
146 0x804e004:      0x04
   
147 
   148     Excellent, and finally, we should have the string "FIVE"
   
149     stored as ascii characters in the next four bytes.
   
150 
   151 (gdb) x/4cb (int)var_HERE + 5
   
152 0x804e005:      70 'F'  73 'I'  86 'V'  69 'E'
   
153 
   154     Bingo!
   
155 
   156     Now CREATE updates HERE to point at the address after
   
157     the header (aligned to 4 bytes) and LATEST to point to
   
158     the header of our new word.
   
159 
   160 578         mov eax, [var_HERE]
   
161 579         mov [var_LATEST], eax
   
162 580         mov [var_HERE], edi
   
163 
   164     Now our old pal NEXT will be moving on to the next word
   
165     in COLON to continue the compilation process.
   
166 
   167     Here's the entire definition of COLON:
   
168 
   169         DEFWORD ":",1,,COLON
   
170         dd FWORD                 ; Get the name of the new word
   
171         dd CREATE               ; CREATE the dictionary entry / header
   
172         dd LIT, DOCOL, COMMA    ; Append DOCOL  (the codeword).
   
173         dd LATEST, FETCH, HIDDEN ; Make the word hidden while it's being compiled.
   
174         dd RBRAC                ; Go into compile mode.
   
175         dd EXIT                 ; Return from the function.
   
176 
   177     So it looks like LIT is next.
   
178 
   179 27          lodsd     ; NEXT: Load from memory into eax, inc esi to point to next word.
   
180 28          jmp [eax] ; Jump to whatever code we're now pointing at.
   
181 code_LIT () at nasmjf.asm:493
   
182 493         lodsd                   ; loads the value at esi into eax, incements esi
   
183 494         push eax                ; push the literal number on to stack
   
184 
   185     Yup! Well, this has been great progress. The header for
   
186     our new word has been stored in memory we reserved.
   
187 
   188     I keep falling asleep, so the next log will pick up
   
189     where this left off. Then I can figure out what the heck
   
190     LIT is supposed to be accomplishing here.