1 We'll pick up right where we left off with a convenience
2 word to be used with VALUEs that works just like += in
3 "C-like" languages:
4
5 +TO adds to the value
6
7 50 VALUE foo foo . 50
8 100 TO foo foo . 100
9 10 +TO foo foo . 110
10
11 And now some exciting introspection words:
12
13 ID. prints name of word at address
14 ?HIDDEN returns truthy value if word hidden
15 ?IMMEDATE returns truthy value if word immediate
16
17 LATEST @ ID.
18 foo
19 LATEST @ DUP DUP ID. SPACE ?IMMEDIATE . ?HIDDEN .
20 foo 0 0
21 LATEST @ @ DUP DUP ID. SPACE ?IMMEDIATE . ?HIDDEN .
22 CFA> 0 0
23 LATEST @ @ @ DUP DUP ID. SPACE ?IMMEDIATE . ?HIDDEN .
24 ENDCASE 128 0
25
26 And
27
28 WORDS prints all non-hidden words
29
30 WORDS
31 foo CFA> ENDCASE ENDOF OF CASE DUMP FORGET WORDS ?IMMEDIATE ?HIDDEN ID. +TO TO VALUE VARIABLE CELLS
32 ALLOT CONSTANT ." S" C, ALIGN ALIGNED DEPTH WITHIN ? U. . .R U.R UWIDTH .S U. HEX DECIMAL SPACES PIC
33 K TUCK NIP ( UNLESS REPEAT WHILE AGAIN UNTIL BEGIN ELSE THEN IF RECURSE [COMPILE] '.' '-' '0' 'A' '"
34 ' ')' '(' ';' ':' LITERAL NOT FALSE TRUE NEGATE SPACE CR BL '\n' MOD / LATEST CEND CSTART BASE S0 HE
35 RE STATE O_NONBLOCK O_APPEND O_TRUNC O_EXCL O_CREAT O_RDWR O_WRONLY O_RDONLY SYS_BRK SYS_CREAT SYS_W
36 RITE SYS_READ SYS_CLOSE SYS_OPEN SYS_EXIT F_LENMASK F_HIDDEN F_IMMED DOCOL R0 VERSION SYSCALL0 SYSCA
37 LL1 SYSCALL2 SYSCALL3 EXECUTE CHAR HIDE IMMEDIATE DSP! DSP@ RDROP RSP! RSP@ R> >R CMOVE C@C! C@ C! -
38 ! +! @ ! INVERT XOR OR AND 0>= 0<= 0> 0< 0<> 0= >= <= > < <> = /MOD * - + 4- 4+ 1- 1+ ?DUP 2SWAP 2DU
39 P 2DROP -ROT ROT OVER DUP SWAP DROP PRINTWORD . EMIT ; : EXIT HIDDEN ] [ , CREATE FIND LIT NUMBER >D
40 FA >CFA KEY WORD INTERPRET TELL LITSTRING 0BRANCH BRANCH ' gtfo QUIT
41
42 The next one is pretty crazy. You would think that this
43 would just hide or "forget" the word CR. But it doesn't,
44 it forgets CR and *everything after* it!
45
46 FORGET CR
47
48 So now WORDS should only show up to BL:
49
50 WORDS
51 PARSE ERROR: WORDS
52
53 Huh? Oh, ha ha ha. Right.
54
55 Time to reload.
56 Let's see that again, but maybe not "forget" quite so
57 much:
58
59 LATEST @ ID.
60 CFA>
61 : foo ." Hello" ;
62 foo
63
64 Program received signal SIGSEGV, Segmentation fault.
65 code_LITSTRING () at nasmjf.asm:28
66 28 jmp [eax] ; Jump to whatever code we're now pointing at.
67
68 Argh! I can hardly believe this is the first time I've
69 tried compiling a word that contains a print string
70 statement. But I guess so. So my LITSTRING assembly
71 port of the original must contain a bug?
72
73 Two nights later: debugging this with GDB *sucks*
74 because LITSTRING is written in assembly, but the
75 higher-level S" and ." are written in Forth, so it's
76 really hard to break right when I want to. On top of
77 that, trying to examine Forth constructs with GDB feels
78 like trying to eat soup with a fork. I know it's a
79 programmable fork and I could probably make it an
80 awesome soup fork, but I'd rather work on my soup
81 instead of my utensils.
82
83 Hmmm... you know what? The next word I was going to test
84 after FORGET is DUMP, which is supposed to give a hex
85 dump of memory.
86
87 Maybe I can use it to help debug LITSTRING and friends?
88
89 First, let's see how it works:
90
91 DUMP ( addr len -- )
92
93 DUMP is used to dump out the contents of memory,
94 in the 'traditional' hexdump format.
95
96 So we give it an address of memory and a number of bytes
97 to print. I wonder it will look like if I create a
98 simple word and display it?
99
100 This one has some repetition so maybe I can see the
101 pattern:
102
103 : foobar 5 . 5 . ;
104 foobar
105 5 5
106
107 And let's dump 64 bytes of memory starting at the
108 laatest definition:
109
110 LATEST @ 64 DUMP
111 804EF20 C4 EE 4 8 6 66 6F 6F 62 61 72 0 5A 90 4 8 .....foobar.Z...
112 804EF30 38 A1 4 8 5 0 0 0 2C E7 4 8 38 A1 4 8 8.......,...8...
113 804EF40 5 0 0 0 2C E7 4 8 9C A1 4 8 0 0 0 0 ....,...........
114 804EF50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ................
115
116 Gasp! Oh my goodness! It's beautiful. So handy. And DUMP
117 is less than 50 lines of Forth?
118
119 Okay, my bitter annoyance is melting away.
120
121 I can totally read my word.
122
123 The little-endian data is annoying, but
124
125 C4 EE 4 8
126
127 is 804EEC4, so that'll be the link to the previous word.
128
129 I really wish these were grouped by 4-byte chunks and
130 put into big-endian order...and then run ID. on each
131 recognizable address (since I know they're all
132 0804xxxx)...
133
134 Okay, after midnight now.
135
136 I figured it out after verifying every single statement
137 in the compile-mode execution of S" and wouldn't you
138 know it was the very last statement that was wrecking
139 everything?
140
141 At the very end, it calls ALIGN to get the HERE pointer
142 to the next 4-byte boundary (after writing an address,
143 length, and string to memory).
144
145 ALIGN calls ALIGNED which uses "3 INVERT" to create a
146 mask to zero out the last two bits of an address.
147 Well, it turns out my INVERT word definition was doing
148 this:
149
150 not word [esp]
151
152 which gives you a 16 bit number. Instead, I needed this:
153
154 not dword [esp]
155
156 to operate on the full 32 bit number.
157
158 So let me take another moment here to rant for a second:
159 x86 terminoloy blows! A "word" should be the natural
160 address size on the architecture. But in x86 land,
161 "word" is stuck at 16 bits! So 32 bits is a dword and 64
162 bits is a qword and so on. Argh! This is not the first
163 time I've been bitten by this garbage.
164
165 ************************
166 *** "word" is a lie! ***
167 ************************
168
169 This would *definitely* explain all the segfaults since
170 ALIGN was masking off half of HERE and setting it to an
171 invalid address!
172
173 Do I dare get my hopes up?
174
175 Yeah, why not...
176
177 JONESFORTH VERSION 1
178 20643 CELLS REMAINING
179 OK
180
181 Yes! It works!
182
183 : foo ." Hello World!!!" ;
184 foo
185 Hello World!!!
186
187 Hello World, indeed.
188
189 As far as I know, my NASM interpreter port is complete
190 now. I'll continue with the word testing. And I have a
191 lot of cleanup to do. But this is a great night for
192 nasmjf!
193
194 I'll start the next log with CASE statement testing