summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin_echo.asm20
-rw-r--r--builtin_exit.asm17
-rw-r--r--builtin_reboot.asm29
-rw-r--r--builtins.asm19
-rw-r--r--terminal.asm152
5 files changed, 214 insertions, 23 deletions
diff --git a/builtin_echo.asm b/builtin_echo.asm
new file mode 100644
index 0000000..1b4af89
--- /dev/null
+++ b/builtin_echo.asm
@@ -0,0 +1,20 @@
+%ifndef _BUILTIN_ECHO_ASM
+%define _BUILTIN_ECHO_ASM
+
+builtin_echo:
+ push bp
+ mov bp, sp
+
+ mov bx, word [bp + 4]
+ add bx, 2
+ push word [bx]
+ push .msg_fmt
+ call printf
+ add sp, 2 * 2
+
+ mov sp, bp
+ pop bp
+ ret
+ .msg_fmt db '%s\n', 0
+
+%endif
diff --git a/builtin_exit.asm b/builtin_exit.asm
new file mode 100644
index 0000000..74594e1
--- /dev/null
+++ b/builtin_exit.asm
@@ -0,0 +1,17 @@
+%ifndef _BUILTIN_EXIT_ASM
+%define _BUILTIN_EXIT_ASM
+
+builtin_exit:
+ push bp
+ mov bp, sp
+
+ push .msg_fmt
+ call printf
+ add sp, 2 * 1
+
+ add sp, 2 ; cleanup previous call address
+
+ jmp terminal
+ .msg_fmt db 'exiting...\n', 0
+
+%endif
diff --git a/builtin_reboot.asm b/builtin_reboot.asm
new file mode 100644
index 0000000..54d6f8a
--- /dev/null
+++ b/builtin_reboot.asm
@@ -0,0 +1,29 @@
+%ifndef _BUILTIN_REBOOT_ASM
+%define _BUILTIN_REBOOT_ASM
+
+builtin_reboot:
+ mov bx, 3 ; number of seconds
+ .countdown:
+ push bx
+ push .msg_reboot_count
+ call printf
+ add sp, 2 * 2
+
+ mov ah, 86h
+ mov cx, 0fh
+ mov dx, 4240h
+ int 15h
+
+ dec bx
+ jne .countdown
+
+ push .msg_reboot
+ call printf
+ add sp, 2 * 1
+
+ jmp 0FFFFh:0000h ; issue reboot
+ .msg_reboot_count db 'rebooting in %d seconds...\r', 0
+ .msg_reboot db '\nreboot...\n', 0
+ ; no return, and the stack is irrelevant here
+
+%endif
diff --git a/builtins.asm b/builtins.asm
new file mode 100644
index 0000000..268e4b2
--- /dev/null
+++ b/builtins.asm
@@ -0,0 +1,19 @@
+%ifndef _BUILTINS_ASM
+%define _BUILTINS_ASM
+
+%include "builtin_reboot.asm"
+%include "builtin_exit.asm"
+%include "builtin_echo.asm"
+
+t_builtins_fn:
+ dw builtin_echo
+ dw builtin_exit
+ dw builtin_reboot
+ dw 0
+
+t_builtins_str:
+ .echo: db 'echo', 0
+ .exit: db 'exit', 0
+ .reboot: db 'reboot', 0
+ dw 0
+%endif
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