1 ;; This file provides a small collection of fundamental subroutines that
2 ;; are used by the core forth words.
4 section '.text' code readable executable
6 macro printlen msg, len {
24 printlen msg, msg#.len
32 ;; Find the given word in the dictionary of words. If no such word exists,
36 ;; * [find.search_length] = Length of the word in bytes.
37 ;; * [find.search_buffer] = Pointer to the string containing the word.
38 ;; * rsi = Pointer to the last entry in the dictionary.
41 ;; * rsi = Pointer to the found entry in the dictionary or 0.
43 ;; Clobbers rcx, rdx, rdi, rax.
45 ;; RSI contains the entry we are currently looking at
47 movzx rcx, byte [rsi + 8 + 1] ; Length of word being looked at
48 cmp rcx, [.search_length]
49 jne .next ; If the words don't have the same length, we have the
52 ;; Otherwise, we need to compare strings
53 lea rdx, [rsi + 8 + 1 + 1] ; Location of character being compared in entry
54 mov rdi, [.search_buffer] ; Location of character being compared in
60 jne .next ; They don't match; try again
61 inc rdx ; These characters match; look at the
66 jmp .found ; They match! We are done.
69 mov rsi, [rsi] ; Look at the previous entry
71 jnz .loop ; If there is no previous word, exit and return 0
76 ;; Read a word from a buffer. Returns the buffer without the word, as
77 ;; well as the word that was read (including lengths). Treats space,
78 ;; tab and newline as whitespace.
81 ;; * rsi = Input buffer
82 ;; * rcx = Length of buffer
85 ;; * rsi = Updated buffer
86 ;; * rcx = Length of remaining buffer
87 ;; * rdi = Word start in buffer
88 ;; * rdx = Length of word buffer
95 ;; The buffer starts with whitespace: consume that and try again.
110 ;; We got a character that wasn't whitespace. Now read the actual word.
111 mov rdi, rsi ; This is where the word starts
114 inc rdx ; Length of word
116 ;; Extract character from original buffer:
121 ;; When we hit whitespace, we are done with this word
130 ;; It wasn't whitespace; include it in word
134 ;; Finally, we want to skip one whitespace character after the word.
142 ;; Parses a string of decimal digits
145 ;; * rcx = Length of string
146 ;; * rdi = Pointer to string buffer
155 ;; Add (10^(rcx-1) * parse_char(rdi[length - rcx])) to the
156 ;; accumulated value for each rcx.
159 ;; First, calcuate 10^(rcx - 1)
171 ;; Now, rax = 10^(rcx - 1).
173 ;; We need to calulate the value of the character at rdi[length - rcx].
177 movzx rbx, byte [rbx]
183 ;; Multiply this value by rax to get
184 ;; (10^(rcx-1) * parse_char(rdi[length - rcx]))
185 ;; then add this to the result.
188 ;; Add that value to r8
199 print parse_number.error_msg
201 printlen rdi, [.length]
206 section '.data' readable writable
208 find.search_length dq ?
209 find.search_buffer dq ?
211 parse_number.length dq ?
212 parse_number.error_msg string "Invalid number: "