3 segment readable executable
5 macro printlen msg, len {
25 printlen msg, msg#.len
39 ;; Find the given word in the dictionary of words. If no such word exists,
43 ;; * [find.search_length] = Length of the word in bytes.
44 ;; * [find.search_buffer] = Pointer to the string containing the word.
45 ;; * rsi = Pointer to the last entry in the dictionary.
48 ;; * rsi = Pointer to the found entry in the dictionary or 0.
50 ;; Clobbers rcx, rdx, rdi, rax.
52 ;; RSI contains the entry we are currently looking at
54 movzx rcx, byte [rsi + 8 + 1] ; Length of word being looked at
55 cmp rcx, [.search_length]
56 jne .next ; If the words don't have the same length, we have the wrong word
58 ;; Otherwise, we need to compare strings
59 lea rdx, [rsi + 8 + 1 + 1] ; Location of character being compared in entry
60 mov rdi, [.search_buffer] ; Location of character being compared in search buffer
65 jne .next ; They don't match; try again
66 inc rdx ; These characters match; look at the next ones
70 jmp .found ; They match! We are done.
73 mov rsi, [rsi] ; Look at the previous entry
75 jnz .loop ; If there is no previous word, exit and return 0
80 ;; Read a word from standard input. Returns pointer to string containing word as
84 ;; * rdx = Length of string
85 ;; * rdi = Pointer to string buffer
87 ;; Clobbers pretty much everything.
90 ;; Read characters into .char_buffer until one of them is not whitespace.
97 ;; We consider newlines and spaces to be whitespace.
98 cmp [.char_buffer], ' '
100 cmp [.char_buffer], $A
104 ;; We got a character that wasn't whitespace. Now read the actual word.
108 mov al, [.char_buffer]
117 mov rsi, .char_buffer
121 cmp [.char_buffer], ' '
123 cmp [.char_buffer], $A
132 ;; Read a word from a buffer. Returns the buffer without the word, as well as
133 ;; the word that was read (including lengths).
136 ;; * rsi = Input buffer
137 ;; * rcx = Length of buffer
140 ;; * rsi = Updated buffer
141 ;; * rcx = Length of updated buffer
142 ;; * rdi = Word buffer
143 ;; * rdx = Length of word buffer
153 ;; The buffer starts with whitespace; discard the first character from the buffer.
159 ;; We got a character that wasn't whitespace. Now read the actual word.
160 mov rdi, rsi ; This is where the word starts
161 mov rdx, 1 ; Length of word
164 ;; Extract character from original buffer:
168 ;; When we hit whitespace, we are done with this word
175 ;; It wasn't whitespace; add it to word buffer
186 ;; * rcx = Length of string
187 ;; * rdi = Pointer to string buffer
196 ;; Add (10^(rcx-1) * parse_char(rdi[length - rcx])) to the accumulated value
200 ;; First, calcuate 10^(rcx - 1)
212 ;; Now, rax = 10^(rcx - 1).
214 ;; We need to calulate the value of the character at rdi[length - rcx].
218 movzx rbx, byte [rbx]
224 ;; Multiply this value by rax to get (10^(rcx-1) * parse_char(rdi[length - rcx])),
225 ;; then add this to the result.
228 ;; Add that value to r8
239 print parse_number.error_msg
241 printlen rdi, [.length]
245 segment readable writable
247 find.search_length dq ?
248 find.search_buffer dq ?
250 read_word.max_size = $FF
251 read_word.buffer rb read_word.max_size
252 read_word.length db ?
253 read_word.char_buffer db ?
255 parse_number.length dq ?
256 parse_number.error_msg string "Invalid number: "