X-Git-Url: https://git.rrq.au/?a=blobdiff_plain;f=impl.asm;h=67d11b57ac02a3b7378c6f87d6b0276d39c91b19;hb=4a9ccd4fd3b9b19c696a2f37e0b46eecc1fdd671;hp=9ad22789eb587a03da91ae3773427543006a6253;hpb=24d3a4952e2e2b6db7a64eb2a8caffd2976a02ee;p=rrq%2Fjonasforth.git diff --git a/impl.asm b/impl.asm index 9ad2278..67d11b5 100644 --- a/impl.asm +++ b/impl.asm @@ -1,14 +1,12 @@ -segment readable executable +os_code_section macro printlen msg, len { push rsi add rsp, 8 - mov rsi, msg + mov rcx, msg mov rdx, len - mov rax, 1 - mov rdi, 1 - syscall + call os_print_string sub rsp, 8 pop rsi @@ -23,12 +21,6 @@ macro print msg { printlen msg, msg#.len } -macro exit code { - mov rax, $3C - mov rdi, code - syscall -} - struc string bytes { . db bytes .len = $ - . @@ -75,55 +67,57 @@ find: .found: ret -;; Read a word from standard input. Returns pointer to string containing word as -;; well as length. +;; Read a word from a buffer. Returns the buffer without the word, as well as +;; the word that was read (including lengths). ;; -;; Results: -;; * rdx = Length of string -;; * rdi = Pointer to string buffer +;; Inputs: +;; * rsi = Input buffer +;; * rcx = Length of buffer ;; -;; Clobbers pretty much everything. -read_word: +;; Outputs: +;; * rsi = Updated buffer +;; * rcx = Length of updated buffer +;; * rdi = Word buffer +;; * rdx = Length of word buffer +pop_word: .skip_whitespace: - ;; Read characters into .char_buffer until one of them is not whitespace. - mov rax, 0 - mov rdi, 0 - mov rsi, .char_buffer - mov rdx, 1 - syscall - - ;; We consider newlines and spaces to be whitespace. - cmp [.char_buffer], ' ' - je .skip_whitespace - cmp [.char_buffer], $A - je .skip_whitespace + mov al, [rsi] + cmp al, ' ' + 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. - mov [.length], 0 + mov rdi, rsi ; This is where the word starts + mov rdx, 1 ; Length of word .read_alpha: - mov al, [.char_buffer] - movzx rbx, [.length] - mov rsi, .buffer - add rsi, rbx - mov [rsi], al - inc [.length] - - mov rax, 0 - mov rdi, 0 - mov rsi, .char_buffer - mov rdx, 1 - syscall - - cmp [.char_buffer], ' ' + ;; Extract character from original buffer: + inc rsi + dec rcx + + ;; When we hit whitespace, we are done with this word + mov al, [rsi] + cmp al, ' ' + je .end + cmp al, $A je .end - cmp [.char_buffer], $A - jne .read_alpha + + ;; It wasn't whitespace; add it to word buffer + inc rdx + jmp .read_alpha .end: - mov rdi, .buffer - movzx rdx, [.length] + ;; Finally, we want to skip one whitespace character after the word. + inc rsi + dec rcx ret @@ -187,18 +181,14 @@ parse_number: pop rdi printlen rdi, [.length] newline - exit 100 + mov rax, 100 + call os_terminate -segment readable writable +os_data_section find.search_length dq ? find.search_buffer dq ? -read_word.max_size = $FF -read_word.buffer rb read_word.max_size -read_word.length db ? -read_word.char_buffer db ? - parse_number.length dq ? parse_number.error_msg string "Invalid number: "