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/log15.txt

Download raw file: devlog/log15.txt

1 Warning, the examples with variables in this log are 2 all wrong. This update explains: 3 4 !!!!!!!!!!!!!!!!!!!! Update !!!!!!!!!!!!!!!!!!!! 5 ! In log19.txt, I realize that my variable ! 6 ! handling is wrong. Variables should leave ! 7 ! their addresses on the stack, not their ! 8 ! values! We need FETCH to get the value from ! 9 ! the address! ! 10 !!!!!!!!!!!!!!!!!!!! Update !!!!!!!!!!!!!!!!!!!! 11 12 Now I've ported the primitive memory words. 13 Actually, I'd already done FETCH ('@') because it was 14 required by INTERPRET. 15 16 ! store value at address 17 @ get value from address 18 +! add value to value at address 19 -! subtract value from value at address 20 C! store byte 21 C@ fetch byte 22 C@C! copy 1 byte from source addr to dest addr 23 CMOVE copy n bytes from source addr to dest addr 24 25 So far, it's been easy to figure out how to test new 26 words as I add them. But these memory primitives aren't 27 so obvious because how do I know where I can read/write 28 memory? 29 30 The VARIABLE word which creates new variables won't be 31 defined until the second half of JonesFORTH runs...and 32 that's defined in FORTH, not asm! 33 34 Thankfully, we have some existing variables which should 35 be helpful: 36 37 STATE compiling (1) or executing (0) 38 LATEST Points to the most recently defined word 39 HERE Points to the next free byte of memory 40 S0 The address of the top of the parameter stack 41 BASE The current base for printing and reading numbers 42 43 So, on with the testing, starting with storing and fetching 44 from HERE. 45 46 HERE . 47 134537216 48 5 HERE ! 49 HERE @ . 50 5 51 HERE @ HERE @ . . 52 55 53 54 Now the in-place addition and subtraction. 55 56 1 HERE +! HERE @ . 57 6 58 2 HERE -! HERE @ . 59 4 60 61 For the byte-wise operators, I'll set the 62 native-sized 4 bytes to all 1s, then it'll be 63 clear if we're just storing/fetching the lower 64 byte. 65 66 0 INVERT HERE ! HERE @ . 67 65535 68 0 HERE C! HERE @ . 69 65280 70 HERE C@ . 71 0 72 73 Now to copy a byte from memory to another 74 memory location, let's get an interesting 75 byte - the 'L' from 'LATEST' in the name 76 portion of the word definition: 77 78 LATEST . 79 134522384 80 LATEST 5 + C@ EMIT 81 L 82 LATEST 5 + HERE C@C! 83 HERE @ . 84 65356 85 HERE C@ EMIT 86 L 87 88 That's neat, but we can do one better by 89 copying the entire string. I'll reformat 90 the responses to make it even clearer: 91 92 LATEST 5 + HERE 6 CMOVE 93 HERE 0 + @ EMIT L 94 HERE 1 + @ EMIT A 95 HERE 2 + @ EMIT T 96 HERE 3 + @ EMIT E 97 HERE 4 + @ EMIT S 98 HERE 5 + @ EMIT T 99 100 Neat! 101 102 Next are return stack manipulation words. Forth 103 is surely unique in inviting programmers to monkey 104 about with the return stack for storing temporary 105 values or perform other clever tricks. 106 107 >R move value from param stack to return stack 108 R> move value from return stack to param stack 109 RSP@ get the actual address RSP points to 110 RSP! set the address RSP points to 111 RDROP move RSP to "pop" value and throw it away 112 113 According to Leo Brodie's Starting Forth, storing stuff 114 on the return stack should be safe to use when defining 115 a word. Outside of that, it'll likely cause a crash. 116 117 : store-add >R + R> ; 118 1 2 3 store-add . . 119 33 120 121 That works. Stows the 3 from the param stack on the return 122 stack, adds the 1 and 2 from the param stack and puts the 123 resulting 3 onto the param stack, restores the 3 from the 124 return stack back to the param stack. 125 126 We can look at the address of the return stack pointer (RSP). 127 Which is currently equal to the top of the return stack 128 memory address, stored in constant R0: 129 130 RSP@ . 131 134530680 132 R0 . 133 134530680 134 135 This isn't a very good demonstration of setting RSP since 136 I'm setting it to the existing value: 137 138 RSP@ RSP! 139 140 Now let's see if we can "drop" the value on the return 141 stack: 142 143 RSP@ @ . 144 0 145 5 >R 146 RSP@ @ . 147 5 148 RDROP 149 RSP@ @ . 150 0 151 152 Yup! 153 154 Like the return stack, we can mess directly with the param 155 stack with two words: 156 157 DSP@ - fetch address of param ("data") stack pointer 158 DSP! - set address of param stack pointer 159 160 Let's view the DSP address: 161 162 DSP@ . 163 3221223824 164 165 And it should go lower when we push a value because it 166 grows "upward": 167 168 55 169 DSP@ . 170 171 We can view the value on the stack by fetching it from 172 the address: 173 174 3221223820 175 DSP@ @ . 176 55 177 178 Let's put another value on the stack. DSP will get lower. 179 And we can view the new value: 180 181 77 182 DSP@ . 183 3221223816 184 DSP@ @ . 185 77 186 187 Let's try setting DSP "back" to a higher address to point 188 to and view the previous value again: 189 190 DSP@ 4 + DSP! 191 DSP@ . 192 3221223820 193 DSP@ @ . 194 55 195 196 Neat!