summaryrefslogtreecommitdiff
path: root/terminal.asm
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2018-06-19 00:54:43 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2018-06-19 00:54:43 -0400
commit47e691cb0b7a49a797c622b6c79162428358fbe1 (patch)
tree11cbfcd397d92567953507a0f8482d269bd299d6 /terminal.asm
parent16ce91dac78f9a522d6b5a5f4b0f651e25635a4f (diff)
downloadminos-47e691cb0b7a49a797c622b6c79162428358fbe1.tar.gz
Implement builtin terminal commands
* Reboot * Exit * Echo
Diffstat (limited to 'terminal.asm')
-rw-r--r--terminal.asm152
1 files changed, 129 insertions, 23 deletions
diff --git a/terminal.asm b/terminal.asm
index 376595a..718a304 100644
--- a/terminal.asm
+++ b/terminal.asm
@@ -1,16 +1,18 @@
%ifndef _TERMINAL_ASM
%define _TERMINAL_ASM
+%include "builtins.asm"
+
T_BUFSZ equ 255 ; maximum length of terminal input buffer
+
terminal:
push bp
mov bp, sp
- push ds
- push es
mov ax, ds
mov es, ax
+ sub sp, 2 ; variable for buffer start address
sub sp, T_BUFSZ ; reserve space for tokens
cld
@@ -18,9 +20,9 @@ terminal:
.clear_buffer:
xor ax, ax
mov cx, T_BUFSZ / 2
- lea di, [bp - T_BUFSZ]
- mov dx, di
- repne stosb ; zero out token storage
+ lea di, [bp - T_BUFSZ] ; load buffer start address
+ mov [bp - 2], di ; store start address for later
+ repne stosb ; zero out token storage
xor ax, ax
mov cx, T_BUFSZ / 2 ; counter is length of buffer
@@ -45,6 +47,7 @@ terminal:
cmp al, ASCII_CR ; return pressed?
jne .update_buffer
mov al, ASCII_LF ; convert CR to LF
+ mov byte [di], 0
.update_buffer:
cmp al, ASCII_LF
@@ -62,29 +65,20 @@ terminal:
.flush_buffer:
cmp [di-1], byte 0 ; stosb above increments di.
; (di - 1) is the previous input
- je .do_prompt ; if no input (null), start over
+ je .clear_buffer ; if no input (null), start over
mov al, ASCII_LF
call putc ; print carriage return
push ' '
- push dx
- push t_buffer
- call strtok
+ push word [bp - 2] ; token array address
+ push t_buffer ; address of terminal input buffer
+ call strtok ; tokenize
add sp, 2 * 3
- push ax
- call printh
- add sp, 2
-
- ; ---- TEMPORARY ---
- ; a command parser will be here eventually
- ; TODO: write string tokenizer
- ;push t_buffer ; push buffer string address
- ;push t_buffer_fmt ; push buffer format string address
- ;call printf ; write input to console
- ;add sp, 2 * 2 ; clean up stack
- ; --- END TEMPORARY ---
+ push ax ; push token array
+ call terminal_check_input ; parse terminal input
+ add sp, 2 * 1
jmp .clear_buffer ; zero out buffer / start over
@@ -95,13 +89,125 @@ terminal:
jmp .do_prompt ; start over
add sp, 2
- pop es
- pop ds
mov sp, bp
pop bp
ret
+terminal_check_input:
+ %define .input_len [bp - 2]
+ %define .scan_count [bp - 4]
+ %define .compare_count [bp - 6]
+ %define .input_baseaddr [bp - 8]
+ %define .builtins_count [bp - 10]
+
+ push bp
+ mov bp, sp
+ sub sp, 2 * 5
+
+ pusha
+
+ mov bx, word [bp + 4] ; arg1 - Token array
+ mov .input_baseaddr, bx ; store base address of tokenized string
+
+ mov cx, 0 ; Initialize scan counter
+ mov .scan_count, cx ; store initial counter value
+
+ mov di, t_builtins_str ; Load destination index with a
+ ; list of builtin command
+ mov si, .input_baseaddr ; Load source index with the address
+ mov si, [si] ; Load the string at token address
+
+ push si
+ call strlen
+ pop si
+ mov .input_len, ax ; identifiers (strings)
+
+ mov cx, 0
+ mov si, t_builtins_fn
+ .count_builtins:
+ cmp word [si], 0
+ je .count_builtins_done
+ add si, 2
+ inc cx
+ jmp .count_builtins
+
+ .count_builtins_done:
+ mov word .builtins_count, cx
+
+ .scan_builtins:
+ mov cx, .scan_count
+ cmp cx, .builtins_count
+ jge .scan_no_match
+
+
+ mov si, .input_baseaddr ; Load source index with the address
+ mov si, [si] ; Load the string at token address
+
+ push di ; get the length of builtin string...
+ call strlen ; strtok returns pointers to the
+ pop di
+ ; beginning of a substring, so in order
+ ; to scan for matches, we need to know
+ ; how many bytes to compare ahead
+ ; of time.
+
+ mov cx, .input_len
+ cmp ax, cx
+ jne .compare_prefail
+
+ ;sub ax, 1 ; Modify strlen return value (+1 null terminator)
+ mov .compare_count, ax ; Store return value of strlen in counter
+ xor ax, ax
+ xor dx, dx
+ xor cx, cx
+
+ .compare:
+ mov al, byte [si] ; Load byte from input string
+ mov dl, byte [di] ; Load byte from builtin identifier string
+
+ cmp al, dl ; Compare bytes
+ jne .compare_fail ; bytes did not match, so try the next string
+
+ dec word .compare_count ; decrement counter
+ je .return ; if counter == 0; return
+
+ inc si ; Increment input string offset
+ inc di ; Increment builtin identifier string offset
+ jmp .compare ; ... continue
+
+ .compare_fail:
+ inc word .scan_count ; Increment builtin identifier string attempt count
+ inc di
+ add di, word .compare_count ; Load the offset of the next builtin identifier
+ jmp .scan_builtins ; Continue scanning
+
+ .compare_prefail:
+ inc word .scan_count
+ inc ax ; adjust for null terminator
+ add di, ax ; Load the offset of the next builtin identifier
+ jmp .scan_builtins
+
+
+ .return:
+ mov bx, t_builtins_fn ; Load address of function pointer array
+ mov cx, word .scan_count ; Load offset count
+ shl cx, 1 ; Multiply offset count by 2 (next WORD)
+ add bx, cx ; Add offset to address of function pointer array
+
+ mov si, .input_baseaddr
+ push si ; address of next token
+ call word [bx] ; Execute builtin command
+ add sp, 2 * 1
+
+ .scan_no_match:
+ popa
+ add sp, 2 * 5
+ mov sp, bp
+ pop bp
+ ret
+
+
; data
t_msg_prompt_fmt: db '%s', 0
t_msg_prompt: db '$ ', 0