Support executing words that the user enters
authorJonas Hvid <mail@johv.dk>
Sat, 30 Nov 2019 15:47:04 +0000 (16:47 +0100)
committerJonas Hvid <mail@johv.dk>
Sat, 30 Nov 2019 15:47:24 +0000 (16:47 +0100)
main.asm

index 834872cd54a756fef046f7a67c0dd1463fd8f86b..28cd430df50123520fb322304c3c765e84d788d6 100644 (file)
--- a/main.asm
+++ b/main.asm
@@ -65,8 +65,8 @@ main:
   cld                        ; Clear direction flag so LODSQ does the right thing.
   mov rbp, return_stack_top  ; Initialize return stack
 
-  mov rsi, program
-  next
+  mov rax, MAIN
+  jmp qword [rax]
 
 program: dq MAIN
 
@@ -131,6 +131,17 @@ forth_asm FIND, 'FIND'
   mov rsi, [.rsi]
   next
 
+;; Given an entry in the dictionary, return a pointer to the codeword of that
+;; entry.
+forth_asm TCFA, '>CFA'
+  pop rax
+  add rax, 8                    ; [rax] = length of name
+  movzx rbx, byte [rax]
+  inc rax
+  add rax, rbx                  ; [rax] = codeword
+  push rax
+  next
+
 ;; BRANCH is the fundamental mechanism for branching. BRANCH reads the next word
 ;; as a signed integer literal and jumps by that offset.
 forth_asm BRANCH, 'BRANCH'
@@ -149,6 +160,16 @@ forth_asm ZBRANCH, '0BRANCH'
   add rsi, 8     ; We need to skip over the next word, which contains the offset.
   next
 
+;; Duplicate the top of the stack.
+forth_asm DUP_, 'DUP'
+  push qword [rsp]
+  next
+
+;; Execute the codeword at the given address.
+forth_asm EXEC, 'EXEC'
+  pop rax
+  jmp qword [rax]
+
 ;; Expects a character on the stack and prints it to standard output.
 forth_asm EMIT, 'EMIT'
   pushr rsi
@@ -373,7 +394,7 @@ forth_asm DOTU, '.U'
 
 forth MAIN, 'MAIN'
   dq HELLO
-  dq READ_WORD, FIND, DOTU, NEWLINE
+  dq READ_WORD, FIND, TCFA, EXEC
   dq BRANCH, -8 * 5
   dq TERMINATE