find:
;; RSI contains the entry we are currently looking at
.loop:
- movzx rcx, byte [rsi + 8] ; Length of word being looked at
+ movzx rcx, byte [rsi + 16] ; Length of word being looked at
cmp rcx, [.search_length]
jne .next ; If the words don't have the same length, we have the wrong word
;; Otherwise, we need to compare strings
- lea rdx, [rsi + 8 + 1] ; Location of character being compared in entry
+ lea rdx, [rsi + 16 + 1] ; Location of character being compared in entry
mov rdi, [.search_buffer] ; Location of character being compared in search buffer
.compare_char:
mov al, [rdx]
;;
;; This macro also defines a label LABEL_entry.
initial_latest_entry = 0
-macro header label, name {
+macro header label, name, immediate {
local .string_end
label#_entry:
dq initial_latest_entry
+ dq 0
db .string_end - ($ + 1)
db name
.string_end:
}
;; Define a Forth word that is implemented in assembly. See 'header' for details.
-macro forth_asm label, name {
- header label, name
+macro forth_asm label, name, immediate {
+ header label, name, immediate
dq .start
.start:
}
;; Define a Forth word that is implemented in Forth. (The body will be a list of
;; 'dq' statements.)
-macro forth label, name {
- header label, name
+macro forth label, name, immediate {
+ header label, name, immediate
dq DOCOL
}
;; entry.
forth_asm TCFA, '>CFA'
pop rax
- add rax, 8 ; [rax] = length of name
+ add rax, 16 ; [rax] = length of name
movzx rbx, byte [rax]
inc rax
add rax, rbx ; [rax] = codeword
mov [rdi], rax ; Insert link to previous entry
mov [latest_entry], rdi ; Update LATEST to point to this word
+ add rdi, 8
+ mov rax, 0
+ mov [rdi], rax ; Set immediate flag
+
add rdi, 8
mov [rdi], rcx ; Insert length
next
+;; Mark the last added word as immediate.
+forth IMMEDIATE, 'IMMEDIATE', 1
+ dq LIT, 1
+ dq LATEST, GET
+ dq LIT, 8, PLUS
+ dq PUT
+ dq EXIT
+
+;; Return 0 if the given word is not immediate.
+forth IS_IMMEDIATE, 'IMMEDIATE?'
+ dq FIND
+ dq LIT, 8, PLUS
+ dq GET
+ dq EXIT
+
forth MAIN, 'MAIN'
dq HELLO
dq INTERPRET