Dave's nasmjf Dev Log 14
Created: 2022-07-22
This is an entry in my developer’s log series written between December 2021 and August 2022 (started project in September). I wrote these as I completed my port of the JONESFORTH assembly language Forth interpreter.
First, we've got some horrible failure in ADD (+) to
fix:
6 6 + .
134914672
Sure enough, I was doing this
pop byte [eax]
instead of this
pop eax
for reasons involving being very sleepy.
Is it fixed with the right stack poppin'?
5 5 + .
10
33 7 + .
40
Yup! Now continuing on, we've got a bunch of comparison
operators - some of them seem downright silly. But Leo
Brodie explains in Starting Forth that having all these
means smaller word definitions (space being paramount on
those original systems) and potentially faster.
I'll put the answers on the same line to make it much
easier to read (and many FORTH systems would have displayed
the response on the same line anyway, so this output is
super authentic).
4 4 = . 1
5 4 = . 0
4 4 <> . 0
5 4 <> . 1
7 3 < . 0
3 7 < . 1
7 3 > . 1
3 7 > . 0
7 3 >= . 1
3 3 >= . 1
4 3 >= . 1
7 3 <= . 0
3 3 <= . 1
5 0= . 0
0 0= . 1
5 0<> . 1
0 0<> . 0
5 0< .. PARSE ERROR: 5 0< ..
5 0< . 0
-5 0< . 1
5 0> . 1
-5 0> . 0
0 0> . 0
5 0>= . 1
0 0>= . 1
-7 0>= . 0
-7 0<= . 1
0 0<= . 1
7 0<= . 0
I left in that fat-fingered '..' to break up the monotony.
Everyone enjoys a good PARSE ERROR, no?
But you can see how these work. The comparisons expect
either 1 or 2 numbers on the stack. They leave a 1 for
true and 0 for false.
Next come some bitwise operators:
1 2 AND . 0
01 AND 10 = 00
3 2 AND . 2
11 AND 10 = 10
1 2 OR . 3
01 OR 10 = 11
1 2 XOR . 3
01 XOR 10 = 11
3 2 OR . 3
11 OR 10 = 11
3 2 XOR . 1
11 XOR 10 = 01
1 INVERT . 65534
00000000000001 NOT = 111111111111110
0 INVERT .
Program received signal SIGSEGV, Segmentation fault.
_FIND.test_word () at nasmjf.asm:532
532 mov al, [edx+4] ; al = flags+length field
10 INVERT .
65525
100 INVERT .
Program received signal SIGSEGV, Segmentation fault.
_FIND.test_word () at nasmjf.asm:532
532 mov al, [edx+4] ; al = flags+length field
Hmmmm... I've run into this before - certain numeric
literals sometimes crash the interpreter with a segfault
in FIND.test_word. I need to step through that eventually.
Aha! Got it. Really silly problem as it turns out.
I had defined the word_buffer memory space in the
.data segment like so:
word_buffer:
db 32 ; 32 bytes of buffer for word names
But that didn't do what the comment said - instead, it
put the single value 32 in a single byte of space!
So whenever I entered *anything* in the interpreter
longer than a handful of characters (not just one because
of 4 byte alignment), I was overwriting whatever came
next in memory, which happened to be word definitions!
The correct definition:
word_buffer:
db 32 dup (0) ; 32 bytes of buffer for word names
actually initializes the memory with 32 bytes all
containing the value 0.
1111 .
1111
11111111 .
11111111
That would have always crashed before. Now it's fixed.
Looks like next up are some low-level memory primitives.