colorful rat Ratfactor.com > Dave's Repos

nasmjf

A NASM assembler port of JONESFORTH
git clone http://ratfactor.com/repos/nasmjf/nasmjf.git

nasmjf/devlog/log22.txt

Download raw file: devlog/log22.txt

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