+;; This file provides a small collection of fundamental subroutines that
+;; are used by the core forth words.
+
section '.text' code readable executable
macro printlen msg, len {
ret
;; Read a word from a buffer. Returns the buffer without the word, as
-;; well as the word that was read (including lengths).
+;; well as the word that was read (including lengths). Treats space,
+;; tab and newline as whitespace.
;;
;; Inputs:
;; * rsi = Input buffer
;;
;; Outputs:
;; * rsi = Updated buffer
-;; * rcx = Length of updated buffer
-;; * rdi = Word buffer
+;; * rcx = Length of remaining buffer
+;; * rdi = Word start in buffer
;; * rdx = Length of word buffer
+
pop_word:
+ mov rdx, 0
+ jmp .skip_whitespace
+
+.got_whitespace:
+ ;; The buffer starts with whitespace: consume that and try again.
+ ;; Note: indefinite
+ inc rsi
+ dec rcx
+ je .no_more
+
.skip_whitespace:
mov al, [rsi]
cmp al, ' '
je .got_whitespace
+ cmp al, 9
+ je .got_whitespace
cmp al, $A
je .got_whitespace
- jmp .alpha
-.got_whitespace:
- ;; The buffer starts with whitespace; discard the first character
- ;; from the buffer.
- inc rsi
- dec rcx
- jmp .skip_whitespace
-.alpha:
- ;; We got a character that wasn't whitespace. Now read the actual
- ;; word.
+ ;; We got a character that wasn't whitespace. Now read the actual word.
mov rdi, rsi ; This is where the word starts
- mov rdx, 1 ; Length of word
.read_alpha:
+ inc rdx ; Length of word
+
;; Extract character from original buffer:
inc rsi
dec rcx
+ je .no_more
;; When we hit whitespace, we are done with this word
mov al, [rsi]
cmp al, ' '
je .end
+ cmp al, 9
+ je .end
cmp al, $A
je .end
- ;; It wasn't whitespace; add it to word buffer
- inc rdx
+ ;; It wasn't whitespace; include it in word
jmp .read_alpha
.end:
inc rsi
dec rcx
+.no_more:
+ ;; Buffer ended
ret
-;; Parses a string.
+;; Parses a string of decimal digits
;;
;; Parameters:
;; * rcx = Length of string
parse_number.length dq ?
parse_number.error_msg string "Invalid number: "
-
}
;; pushr and popr work on the return stack, whose location is stored in the
-;; register RBP. Always allocates an extra 8 bytes as "local frame"
+;; register RBP. Always allocates an extra 8 bytes as "local frame
+;; variable".
+
macro pushr x {
- sub rbp, 8
+ sub rbp, 16
mov qword [rbp], x
}
+
macro popr x {
mov x, [rbp]
- add rbp, 8
+ add rbp, 16
}
;; The following macro generates the dictionary header. It updates the
.start:
}
+;; ############################################################
section '.text' code readable executable
include "impl.asm" ; Misc. subroutines
; the offset.
next
-;; Push the return stack pointer. "grows" negatively
+;; Push the return stack pointer address. "grows" negatively
forth_asm RSPGET, 'R='
- push rbp
+ lea rax, [rbp]
+ push rax
+ next
+
+;; Push the address of the frame quad
+forth_asm RSP0, 'R1'
+ lea rax, [ rbp + 8 ]
+ push rax
next
;; The return stack "grows" negatively, and rbp is the address of the top
;; Push top of the stack.
forth_asm TOP_, 'TOP'
- push rsp
+ lea rax, [rsp]
+ push rax
next
;; Duplicate the top of the stack.