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.