commit 937eeaf9644e79c69f4d975c0f2025070f137fba
parent 7b25cf69ab44609948328847545e02f941436bda
Author: Christian Ermann <christianermann@gmail.com>
Date:   Sat, 15 Jun 2024 19:21:12 -0400
Add base.forth and load into dictionary at startup
Diffstat:
| M | Dockerfile | | | 1 | + | 
| A | base.forth | | | 42 | ++++++++++++++++++++++++++++++++++++++++++ | 
| M | forth.asm | | | 91 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- | 
3 files changed, 129 insertions(+), 5 deletions(-)
diff --git a/Dockerfile b/Dockerfile
@@ -9,6 +9,7 @@ RUN apt-get update && apt-get -y upgrade && \
 
 COPY forth.asm /
 COPY efi.asm /
+COPY base.forth /
 COPY run.sh /
 
 RUN fasm forth.asm BOOTX64.EFI
diff --git a/base.forth b/base.forth
@@ -0,0 +1,42 @@
+
+: [COMPILE] IMMEDIATE
+    WORD FIND
+    >CFA ,
+;
+
+: CODE
+    WORD CREATE
+    LATEST @ >CFA 8 + ,
+    LATEST @ HIDDEN
+    ]
+;
+
+: NEXT IMMEDIATE
+    48 C,
+    AD C,
+    FF C,
+    20 C,
+;
+
+: ;CODE IMMEDIATE
+    [COMPILE] NEXT
+    ALIGN
+    LATEST @ HIDDEN
+    [COMPILE] [
+;
+
+: RAX IMMEDIATE 0 ;
+: RCX IMMEDIATE 1 ;
+: RDX IMMEDIATE 3 ;
+: RBX IMMEDIATE 4 ;
+: R8  IMMEDIATE 41 C, 0 ;
+: R9  IMMEDIATE 41 C, 1 ;
+
+: PUSH IMMEDIATE 50 + C, ;
+: POP  IMMEDIATE 58 + C, ;
+
+: CALL-INDIRECT IMMEDIATE
+    FF C,
+    10 + C,
+;
+
diff --git a/forth.asm b/forth.asm
@@ -268,6 +268,8 @@ main:
     initialize_stack
     mov rbp, return_stack_top
     mov rsi, program
+    mov [input_buffer], forth_base
+    mov [input_buffer.len], forth_base.len
     NEXT
 }
 
@@ -343,10 +345,32 @@ set_program initialize_stack_s3, program_s3
 defcode "KEY", 3, 0, KEY
 ; Read a character.
 ;
-    call sys_read_char
+    call _KEY
     push rax
     NEXT
 
+_KEY:
+    cmp [input_buffer], 0
+    jne .buffer
+
+.stdin:
+    call sys_read_char
+    ret
+
+.buffer:
+    cmp [input_buffer.len], 0
+    je .buffer_empty
+    mov rax, [input_buffer]
+    movzx rax, byte [rax]
+    inc [input_buffer]
+    dec [input_buffer.len]
+    ret
+
+.buffer_empty:
+    mov [input_buffer], 0
+    jmp .stdin
+
+
 defcode "WORD", 4, 0, WORD_
 ; Read a word.
 ;
@@ -378,7 +402,8 @@ _WORD:
 ; After a non-whitespace character is found, RDI is used to hold the address
 ; of the next character to be stored.
 ;
-    call sys_read_char
+    
+    call _KEY
     cmp al, ' '
     je .skip_whitespace
     cmp al, 0xA
@@ -404,7 +429,7 @@ _WORD:
 .next_char:
 ; Keep processing characters until we find the end of the word.
 ;
-    call sys_read_char
+    call _KEY
     cmp al, ' '
     je .end
     cmp al, 0xA
@@ -894,7 +919,10 @@ defcode "HERE", 4, 0, HERE
 defcode "CREATE", 6, 0, CREATE
     pop rcx ; string length
     pop rbx ; string address
+    call _CREATE
+    NEXT
 
+_CREATE:
     mov rdi, [here] ; address of new header
     mov rax, [latest] ; address of last entry
     stosq ; add link to last entry
@@ -922,7 +950,7 @@ defcode "CREATE", 6, 0, CREATE
     mov rax, [here]
     mov [latest], rax
     mov [here], rdi
-    NEXT
+    ret
 
 defcode ",", 1, 0, COMMA
     pop rax
@@ -935,6 +963,13 @@ _COMMA:
     mov [here], rdi
     ret
 
+defcode "C,", 2,  0, CHAR_COMMA
+    pop rax
+    mov rdi, [here]
+    stosb
+    mov [here], rdi
+    NEXT
+
 defcode "LIT", 3, 0, LIT
     lodsq
     push rax
@@ -959,6 +994,12 @@ defcode "HIDDEN", 6, 0, HIDDEN
     xor [rdi], rcx
     NEXT
 
+defcode "IMMEDIATE", 9, FLAG_IMMEDIATE, IMMEDIATE
+    mov rdi, [latest]
+    add rdi, 8
+    xor byte [rdi], FLAG_IMMEDIATE
+    NEXT
+
 defcode "+", 1, 0, PLUS
     pop rbx
     pop rcx
@@ -982,6 +1023,40 @@ defword ";", 1, FLAG_IMMEDIATE, SEMICOLON
     dq LEFT_BRACKET          ; Switch to IMMEDIATE mode
     dq EXIT
 
+defcode "ALIGN", 5, 0, ALIGN_
+    mov rax, [here]
+    add rax, 7
+    and rax, 0xFFFFFFFFFFFFFFF8
+    mov [here], rax
+    NEXT
+
+defcode "DUP", 3, 0, DUP_
+    pop rcx
+    push rcx
+    push rcx
+    NEXT
+
+defcode "DROP", 4, 0, DROP
+    pop rcx
+    NEXT
+
+defword "CONSTANT", 8, 0, CONSTANT
+    dq WORD_
+    dq CREATE
+    dq LIT, DOCOL
+    dq COMMA
+    dq LIT, LIT
+    dq COMMA
+    dq COMMA
+    dq LIT, EXIT
+    dq COMMA
+    dq EXIT
+
+defword "FIELD", 5, 0, FIELD
+    dq DUP_
+    dq CONSTANT
+    dq EXIT
+
 ;------------------------------------------------------------------------------
 ;
 ; Section 8 - String operations
@@ -1072,7 +1147,6 @@ defcode "WORDS", 5, 0, WORDS
     NEXT
 
 
-
 section '.data' data readable writable
 
 version_string db 'soup forth v0.1', 0xA
@@ -1081,6 +1155,9 @@ version_string db 'soup forth v0.1', 0xA
 unrecognized_msg db 'unrecognized word', 0xA
 .length = $ - unrecognized_msg
 
+input_buffer dq 0
+input_buffer.len dq 0
+
 code_EMIT.char_buffer db ?
 
 code_DOT.buffer rb 64
@@ -1108,6 +1185,10 @@ state dq 0
 FLAG_IMMEDIATE = 0x40
 FLAG_HIDDEN = 0x20
 
+forth_base:
+file './base.forth'
+forth_base.len = $ - forth_base
+
 align 4096
 return_stack rb 8192
 return_stack_top: