Dave's nasmjf Dev Log 14

Created: 2022-07-22

nasmjf home

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.

← Previous 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 Next →
    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.
← Previous 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 Next →