From 4170f15b09ccd8bcafc00bb960a6e56670252256 Mon Sep 17 00:00:00 2001 From: Jonas Hvid Date: Sat, 3 Oct 2020 20:32:39 +0200 Subject: [PATCH] Implement the 'KEY' primitive for user input This is a lower-level primitive for getting user input. We now also use this to implement READ-WORD. --- impl.asm | 51 ----------------------------------- main.asm | 82 +++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 63 insertions(+), 70 deletions(-) diff --git a/impl.asm b/impl.asm index ea6c04e..e8cd883 100644 --- a/impl.asm +++ b/impl.asm @@ -69,52 +69,6 @@ find: .found: ret -;; Read a word from standard input. Returns pointer to string containing word as -;; well as length. -;; -;; Results: -;; * rdx = Length of string -;; * rdi = Pointer to string buffer -;; -;; Clobbers pretty much everything. -read_word: -.skip_whitespace: - ;; Read characters into .char_buffer until one of them is not whitespace. - mov rsi, .char_buffer - sys_read_char - - ;; We consider newlines and spaces to be whitespace. - cmp [.char_buffer], ' ' - je .skip_whitespace - cmp [.char_buffer], $A - je .skip_whitespace - -.alpha: - ;; We got a character that wasn't whitespace. Now read the actual word. - mov [.length], 0 - -.read_alpha: - mov al, [.char_buffer] - movzx rbx, [.length] - mov rsi, .buffer - add rsi, rbx - mov [rsi], al - inc [.length] - - mov rsi, .char_buffer - sys_read_char - - cmp [.char_buffer], ' ' - je .end - cmp [.char_buffer], $A - jne .read_alpha - -.end: - mov rdi, .buffer - movzx rdx, [.length] - - ret - ;; Read a word from a buffer. Returns the buffer without the word, as well as ;; the word that was read (including lengths). ;; @@ -236,11 +190,6 @@ section '.data' readable writable 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: " diff --git a/main.asm b/main.asm index 4ed478d..537d0e8 100644 --- a/main.asm +++ b/main.asm @@ -231,38 +231,77 @@ forth_asm EMIT, 'EMIT' popr rsi next -;; Read a word and push it onto the stack as a pointer and a size. The pointer -;; is valid until the next call to READ_WORD. -forth_asm READ_WORD, 'READ-WORD' +;; Read a single character from the current input stream. Usually, this will wait +;; for the user to press a key, and then return the corresponding character. When +;; reading from a special buffer, it will instead return the next characater from +;; that buffer. +;; +;; The ASCII character code is placed on the stack. +forth_asm KEY, 'KEY' + call .impl + push rax + next + +;; Result in RAX +.impl: ;; Are we reading from user input or from the input buffer? cmp [input_buffer], 0 jne .from_buffer ;; Reading user input - mov [.rsi], rsi - - call read_word - push rdi ; Buffer - push rdx ; Length + push rsi + mov rsi, .buffer + sys_read_char + pop rsi - mov rsi, [.rsi] - next + movzx rax, byte [.buffer] + ret .from_buffer: ;; Reading from buffer - mov [.rsi], rsi + mov rax, [input_buffer] + movzx rax, byte [rax] - mov rsi, [input_buffer] - mov rcx, [input_buffer_length] + inc [input_buffer] + dec [input_buffer_length] + ret - call pop_word +;; Read a word and push it onto the stack as a pointer and a size. The pointer +;; is valid until the next call to READ_WORD. +forth_asm READ_WORD, 'READ-WORD' + push rsi +.skip_whitespace: + ;; Read characters until one of them is not whitespace. + call KEY.impl + ;; We consider newlines and spaces to be whitespace. + cmp al, ' ' + je .skip_whitespace + cmp al, $A + je .skip_whitespace + + ;; We got a character that wasn't whitespace. Now read the actual word. + mov [.length], 0 - mov [input_buffer], rsi ; Updated buffer - mov [input_buffer_length], rcx ; Length of updated buffer - push rdi ; Word buffer - push rdx ; Length of word buffer +.read_alpha: + movzx rbx, [.length] + mov rsi, .buffer + add rsi, rbx + mov [rsi], al + inc [.length] + + call KEY.impl + + cmp al, ' ' + je .end + cmp al, $A + jne .read_alpha + +.end: + pop rsi + push .buffer + movzx rax, [.length] + push rax - mov rsi, [.rsi] next ;; Takes a string on the stack and replaces it with the decimal number that the @@ -643,6 +682,11 @@ DOTU.rbuffer rq 16 DOTU.length dq ? DOTU.printed_length dq ? +KEY.buffer dq ? + +READ_WORD.buffer rb $FF +READ_WORD.length db ? + ;; Reserve space for compiled words, accessed through HERE. here dq here_top here_top rq $4000 -- 2.39.2