Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
245cfa57f3 | ||
|
|
88716c0b64 | ||
|
|
7a9b82d57c |
7
Makefile
7
Makefile
@@ -15,7 +15,7 @@ $(BUILD_DIR)/crawos.iso: floppy_image
|
|||||||
# Floppy image
|
# Floppy image
|
||||||
# Fat12
|
# Fat12
|
||||||
floppy_image: $(BUILD_DIR)/crawos.img
|
floppy_image: $(BUILD_DIR)/crawos.img
|
||||||
$(BUILD_DIR)/crawos.img: bootloader kernel
|
$(BUILD_DIR)/crawos.img: bootloader kernel check-fat83
|
||||||
mkdir -p disk_images
|
mkdir -p disk_images
|
||||||
dd if=/dev/zero of=$(BUILD_DIR)/crawos.img bs=512 count=2880 # Use dd to make a disk image
|
dd if=/dev/zero of=$(BUILD_DIR)/crawos.img bs=512 count=2880 # Use dd to make a disk image
|
||||||
mkfs.fat -F 12 -n "CRAWOS" $(BUILD_DIR)/crawos.img # Format the disk image with fat12
|
mkfs.fat -F 12 -n "CRAWOS" $(BUILD_DIR)/crawos.img # Format the disk image with fat12
|
||||||
@@ -36,6 +36,11 @@ $(BUILD_DIR)/kernel.bin:
|
|||||||
mkdir -p disk_images
|
mkdir -p disk_images
|
||||||
$(ASM) $(SRC_DIR)/kernel/kernel.asm -f bin -o $ $(BUILD_DIR)/kernel.bin
|
$(ASM) $(SRC_DIR)/kernel/kernel.asm -f bin -o $ $(BUILD_DIR)/kernel.bin
|
||||||
|
|
||||||
|
check-fat83:
|
||||||
|
@echo "Checking filenames for FAT 8.3 compliance..."
|
||||||
|
@find ./data -type f | awk -F/ '{print $$NF}' | \
|
||||||
|
awk -F. 'length($$1)>8 || length($$2)>3 || NF>2 {print "Invalid FAT 8.3 filename:", $$0; bad=1} END{exit bad}'
|
||||||
|
|
||||||
# Clean
|
# Clean
|
||||||
clean:
|
clean:
|
||||||
rm -f disk_images/*
|
rm -f disk_images/*
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
Kernel written in Assmebly
|
# What is this?
|
||||||
I'm using a modified JazzOS Bootloader
|
This is a simple implementation of a computer kernel
|
||||||
|
written in pure x86 assembly with features including
|
||||||
|
- Read/Write disk operations
|
||||||
|
- The ability to boot from the BIOS using the JazzOS Bootloader
|
||||||
|
- A modified MikeOS BASIC interpreter
|
||||||
|
- A functional POSIX inspired CLI
|
||||||
|
|
||||||
Commands:
|
# Commands
|
||||||
CAT
|
- CAT <filename>: outputs the contents of the file.
|
||||||
HELP
|
- LS: outputs a list of files on the system .
|
||||||
CLEAR
|
- CLEAR: clears the screen.
|
||||||
REBOOT
|
- REBOOT: or esc reboots the system
|
||||||
PONG
|
- BAS <filename>: runs a basic script.
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
PORT OUT 80 5
|
PRINT "Hello, what is your name?"
|
||||||
|
INPUT $1
|
||||||
|
PRINT "Hello " ;
|
||||||
|
PRINT $1
|
||||||
END
|
END
|
||||||
|
|||||||
2
data/test.asm
Normal file
2
data/test.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
X = 100
|
||||||
|
PRINT X
|
||||||
@@ -1 +0,0 @@
|
|||||||
x = 5
|
|
||||||
@@ -26,7 +26,7 @@ ebr_system_id: db 'FAT12 ' ; must be 8 bytes
|
|||||||
fat12_file_name: db ' ' ; 11 free bytes to store a filename in
|
fat12_file_name: db ' ' ; 11 free bytes to store a filename in
|
||||||
boot_message: db 'OK] Kernel successfully loaded!\n"HELP" to see a list of available commands\n', 0
|
boot_message: db 'OK] Kernel successfully loaded!\n"HELP" to see a list of available commands\n', 0
|
||||||
user_input: times 20 db 0
|
user_input: times 20 db 0
|
||||||
prompt_length: db 20
|
prompt_length: dw 20
|
||||||
prompt: db 'sh > ', 0
|
prompt: db 'sh > ', 0
|
||||||
help_string: db 'HELP', 0
|
help_string: db 'HELP', 0
|
||||||
clear_string: db 'CLEAR', 0
|
clear_string: db 'CLEAR', 0
|
||||||
@@ -34,7 +34,8 @@ reboot_string: db 'REBOOT', 0
|
|||||||
basic_string: db 'BAS', 0
|
basic_string: db 'BAS', 0
|
||||||
cat_string: db 'CAT', 0
|
cat_string: db 'CAT', 0
|
||||||
ls_string: db 'LS', 0
|
ls_string: db 'LS', 0
|
||||||
help_text: db 'This is for Cowards:\n"LS" to list the directory,\n"CAT" to output the contents of a file,\n"BAS" to run a basic script,\n"HELP" for this helpful text,\n"CLEAR" to clear the screen,\n"REBOOT" or esc to reboot\n', 0
|
ed_string: db 'ED', 0
|
||||||
|
help_text: db 'This is for Cowards:\n"LS" to list the directory,\n"CAT <filename>" to output the contents of a file,\n"BAS <filename>" to run a basic script,\n"HELP" for this helpful text,\n"CLEAR" to clear the screen,\n"REBOOT" or esc to reboot\n', 0
|
||||||
basic_text: db 'BASIC PROGRAM BEGUN:\n', 0
|
basic_text: db 'BASIC PROGRAM BEGUN:\n', 0
|
||||||
command_result_text: db 'You typed: ', 0
|
command_result_text: db 'You typed: ', 0
|
||||||
unknown_command: db 'Error: Unkown Command..\n ', 0
|
unknown_command: db 'Error: Unkown Command..\n ', 0
|
||||||
@@ -47,12 +48,6 @@ file_not_found: db 'File not found\n', 0
|
|||||||
too_long_filename: db 'Filename too long for Fat12\n', 0
|
too_long_filename: db 'Filename too long for Fat12\n', 0
|
||||||
file_found: db 'File found\n', 0
|
file_found: db 'File found\n', 0
|
||||||
loading_root: db 'Loading root diretory\n', 0
|
loading_root: db 'Loading root diretory\n', 0
|
||||||
read_only: db 'Read Only', 0 ; 1
|
|
||||||
hidden: db ' Hidden ', 0 ; 2
|
|
||||||
system: db ' System ', 0 ; 4
|
|
||||||
volume: db ' Volume ', 0 ; 8
|
|
||||||
directory: db 'Directory', 0 ; 10
|
|
||||||
archive: db ' Archive ', 0 ; 20
|
|
||||||
file_name_length: db 0
|
file_name_length: db 0
|
||||||
file_cluster: dw 0
|
file_cluster: dw 0
|
||||||
file_length: dd 0
|
file_length: dd 0
|
||||||
|
|||||||
@@ -842,14 +842,14 @@ do_break:
|
|||||||
do_call:
|
do_call:
|
||||||
call get_token
|
call get_token
|
||||||
cmp ax, NUMBER
|
cmp ax, NUMBER
|
||||||
je .is_number
|
je .check_is_number
|
||||||
|
|
||||||
mov ax, 0
|
mov ax, 0
|
||||||
mov byte al, [token]
|
mov byte al, [token]
|
||||||
call get_var
|
call get_var
|
||||||
jmp .execute_call
|
jmp .execute_call
|
||||||
|
|
||||||
.is_number:
|
.check_is_number:
|
||||||
mov si, token
|
mov si, token
|
||||||
call string_cast_to_int
|
call string_cast_to_int
|
||||||
|
|
||||||
@@ -1325,7 +1325,7 @@ do_for:
|
|||||||
cmp ax, NUMBER
|
cmp ax, NUMBER
|
||||||
jne .error
|
jne .error
|
||||||
|
|
||||||
.second_is_number:
|
.second_check_is_number:
|
||||||
mov si, token ; Get target number
|
mov si, token ; Get target number
|
||||||
call string_cast_to_int
|
call string_cast_to_int
|
||||||
jmp .continue2
|
jmp .continue2
|
||||||
@@ -1625,7 +1625,7 @@ do_if:
|
|||||||
je .equals_char
|
je .equals_char
|
||||||
|
|
||||||
mov byte al, [token]
|
mov byte al, [token]
|
||||||
call is_letter
|
call check_is_letter
|
||||||
jc .equals_var
|
jc .equals_var
|
||||||
|
|
||||||
mov si, token ; Otherwise it's, eg 'X = 1' (a number)
|
mov si, token ; Otherwise it's, eg 'X = 1' (a number)
|
||||||
@@ -1711,7 +1711,7 @@ do_if:
|
|||||||
.greater:
|
.greater:
|
||||||
call get_token ; Greater than a variable or number?
|
call get_token ; Greater than a variable or number?
|
||||||
mov byte al, [token]
|
mov byte al, [token]
|
||||||
call is_letter
|
call check_is_letter
|
||||||
jc .greater_var
|
jc .greater_var
|
||||||
|
|
||||||
mov si, token ; Must be a number here...
|
mov si, token ; Must be a number here...
|
||||||
@@ -1736,7 +1736,7 @@ do_if:
|
|||||||
.less:
|
.less:
|
||||||
call get_token
|
call get_token
|
||||||
mov byte al, [token]
|
mov byte al, [token]
|
||||||
call is_letter
|
call check_is_letter
|
||||||
jc .less_var
|
jc .less_var
|
||||||
|
|
||||||
mov si, token
|
mov si, token
|
||||||
@@ -1950,8 +1950,9 @@ do_input:
|
|||||||
|
|
||||||
.number_var:
|
.number_var:
|
||||||
mov ax, .tmpstring ; Get input from the user
|
mov ax, .tmpstring ; Get input from the user
|
||||||
mov bx, 6
|
mov bx, 20
|
||||||
call keyboard_display_input
|
call keyboard_display_input
|
||||||
|
jc .end
|
||||||
|
|
||||||
mov ax, .tmpstring
|
mov ax, .tmpstring
|
||||||
call string_length
|
call string_length
|
||||||
@@ -1973,8 +1974,6 @@ do_input:
|
|||||||
call os_print_newline
|
call os_print_newline
|
||||||
|
|
||||||
jmp mainloop
|
jmp mainloop
|
||||||
|
|
||||||
|
|
||||||
.string_var:
|
.string_var:
|
||||||
mov ax, 128
|
mov ax, 128
|
||||||
mul bx
|
mul bx
|
||||||
@@ -1987,8 +1986,9 @@ do_input:
|
|||||||
|
|
||||||
jmp mainloop
|
jmp mainloop
|
||||||
|
|
||||||
|
.tmpstring times 20 db 0
|
||||||
.tmpstring times 6 db 0
|
.end
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
; -----------------------------------------------------------
|
; -----------------------------------------------------------
|
||||||
@@ -2636,7 +2636,7 @@ do_peekint:
|
|||||||
cmp ax, NUMBER
|
cmp ax, NUMBER
|
||||||
jne .error
|
jne .error
|
||||||
|
|
||||||
.address_is_number:
|
.address_check_is_number:
|
||||||
mov si, token
|
mov si, token
|
||||||
call string_cast_to_int
|
call string_cast_to_int
|
||||||
jmp .load_data
|
jmp .load_data
|
||||||
@@ -3770,14 +3770,14 @@ do_string:
|
|||||||
call get_token ; Now there should be a number
|
call get_token ; Now there should be a number
|
||||||
|
|
||||||
cmp ax, NUMBER
|
cmp ax, NUMBER
|
||||||
je .third_is_number
|
je .third_check_is_number
|
||||||
|
|
||||||
cmp ax, VARIABLE
|
cmp ax, VARIABLE
|
||||||
je .third_is_variable
|
je .third_is_variable
|
||||||
|
|
||||||
jmp .error
|
jmp .error
|
||||||
|
|
||||||
.third_is_number:
|
.third_check_is_number:
|
||||||
mov si, token
|
mov si, token
|
||||||
call string_cast_to_int
|
call string_cast_to_int
|
||||||
jmp .got_number
|
jmp .got_number
|
||||||
@@ -3984,7 +3984,7 @@ get_token:
|
|||||||
cmp al, ' '
|
cmp al, ' '
|
||||||
je .newline
|
je .newline
|
||||||
|
|
||||||
call is_number
|
call check_is_number
|
||||||
jc get_number_token
|
jc get_number_token
|
||||||
|
|
||||||
cmp al, '"'
|
cmp al, '"'
|
||||||
@@ -4030,7 +4030,7 @@ get_number_token:
|
|||||||
je .done
|
je .done
|
||||||
cmp al, ' '
|
cmp al, ' '
|
||||||
je .done
|
je .done
|
||||||
call is_number
|
call check_is_number
|
||||||
jc .fine
|
jc .fine
|
||||||
|
|
||||||
mov si, err_char_in_num
|
mov si, err_char_in_num
|
||||||
@@ -4153,7 +4153,7 @@ get_string_token:
|
|||||||
|
|
||||||
.is_not_string:
|
.is_not_string:
|
||||||
mov byte al, [token]
|
mov byte al, [token]
|
||||||
call is_letter
|
call check_is_letter
|
||||||
jc .is_var
|
jc .is_var
|
||||||
|
|
||||||
mov ax, UNKNOWN
|
mov ax, UNKNOWN
|
||||||
@@ -4164,37 +4164,6 @@ get_string_token:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------
|
|
||||||
; Set carry flag if AL contains ASCII number
|
|
||||||
|
|
||||||
is_number:
|
|
||||||
cmp al, 48
|
|
||||||
jl .not_number
|
|
||||||
cmp al, 57
|
|
||||||
jg .not_number
|
|
||||||
stc
|
|
||||||
ret
|
|
||||||
.not_number:
|
|
||||||
clc
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------
|
|
||||||
; Set carry flag if AL contains ASCII letter
|
|
||||||
|
|
||||||
is_letter:
|
|
||||||
cmp al, 65
|
|
||||||
jl .not_letter
|
|
||||||
cmp al, 90
|
|
||||||
jg .not_letter
|
|
||||||
stc
|
|
||||||
ret
|
|
||||||
|
|
||||||
.not_letter:
|
|
||||||
clc
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------
|
; ------------------------------------------------------------------
|
||||||
; Print error message and quit out
|
; Print error message and quit out
|
||||||
|
|
||||||
|
|||||||
29
source/kernel/features/check.asm
Normal file
29
source/kernel/features/check.asm
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
check_is_number:
|
||||||
|
cmp al, 48
|
||||||
|
jl .not_number
|
||||||
|
cmp al, 57
|
||||||
|
jg .not_number
|
||||||
|
stc
|
||||||
|
ret
|
||||||
|
.not_number:
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
|
||||||
|
check_is_letter:
|
||||||
|
cmp al, 65
|
||||||
|
jl .not_letter
|
||||||
|
cmp al, 122
|
||||||
|
jg .not_letter
|
||||||
|
cmp al, 90
|
||||||
|
jg .maybe_not_letter
|
||||||
|
stc
|
||||||
|
ret
|
||||||
|
.maybe_not_letter:
|
||||||
|
cmp al, 97
|
||||||
|
jl .not_letter
|
||||||
|
stc
|
||||||
|
ret
|
||||||
|
.not_letter:
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
os_start_cli:
|
os_start_cli:
|
||||||
pusha
|
pusha
|
||||||
|
|
||||||
|
|
||||||
call os_print_newline
|
call os_print_newline
|
||||||
|
|
||||||
mov si, prompt
|
mov si, prompt
|
||||||
@@ -11,6 +12,7 @@ os_start_cli:
|
|||||||
mov ax, user_input
|
mov ax, user_input
|
||||||
|
|
||||||
call keyboard_display_input
|
call keyboard_display_input
|
||||||
|
jc power_reboot
|
||||||
jmp os_read_cli
|
jmp os_read_cli
|
||||||
|
|
||||||
|
|
||||||
@@ -30,14 +32,14 @@ os_read_cli:
|
|||||||
mov di, help_string
|
mov di, help_string
|
||||||
call os_compare_strings
|
call os_compare_strings
|
||||||
cmp cl, 1
|
cmp cl, 1
|
||||||
je help
|
je .help
|
||||||
|
|
||||||
; Clear screen
|
; Clear screen
|
||||||
mov si, user_input
|
mov si, user_input
|
||||||
mov di, clear_string
|
mov di, clear_string
|
||||||
call os_compare_strings
|
call os_compare_strings
|
||||||
cmp cl, 1
|
cmp cl, 1
|
||||||
je clear
|
je .clear
|
||||||
|
|
||||||
; Reboot
|
; Reboot
|
||||||
mov si, user_input
|
mov si, user_input
|
||||||
@@ -51,21 +53,28 @@ os_read_cli:
|
|||||||
mov di, basic_string
|
mov di, basic_string
|
||||||
call os_compare_strings
|
call os_compare_strings
|
||||||
cmp cl, 1
|
cmp cl, 1
|
||||||
je basic
|
je .basic
|
||||||
|
|
||||||
; Cat
|
; Cat
|
||||||
mov si, user_input
|
mov si, user_input
|
||||||
mov di, cat_string
|
mov di, cat_string
|
||||||
call os_compare_strings
|
call os_compare_strings
|
||||||
cmp cl, 1
|
cmp cl, 1
|
||||||
je cat
|
je .cat
|
||||||
|
|
||||||
; LS
|
; LS
|
||||||
mov si, user_input
|
mov si, user_input
|
||||||
mov di, ls_string
|
mov di, ls_string
|
||||||
call os_compare_strings
|
call os_compare_strings
|
||||||
cmp cl, 1
|
cmp cl, 1
|
||||||
je ls
|
je .ls
|
||||||
|
|
||||||
|
;ED
|
||||||
|
mov si, user_input
|
||||||
|
mov di, ed_string
|
||||||
|
call os_compare_strings
|
||||||
|
cmp cl, 1
|
||||||
|
je .ed
|
||||||
|
|
||||||
jmp .unkown
|
jmp .unkown
|
||||||
|
|
||||||
@@ -77,24 +86,33 @@ os_read_cli:
|
|||||||
jmp .finish
|
jmp .finish
|
||||||
|
|
||||||
.finish:
|
.finish:
|
||||||
|
; Clear the user input
|
||||||
|
mov al, 0
|
||||||
|
mov cx, 20
|
||||||
|
mov di,user_input
|
||||||
|
repe stosb
|
||||||
popa
|
popa
|
||||||
call os_start_cli
|
call os_start_cli
|
||||||
|
|
||||||
clear:
|
.clear:
|
||||||
call os_set_text_mode
|
call os_set_text_mode
|
||||||
call os_read_cli.finish
|
call os_read_cli.finish
|
||||||
|
|
||||||
help:
|
.help:
|
||||||
mov si, help_text
|
mov si, help_text
|
||||||
call os_print_string
|
call os_print_string
|
||||||
call os_read_cli.finish
|
call os_read_cli.finish
|
||||||
|
|
||||||
basic:
|
.basic:
|
||||||
call util_basic
|
call util_basic
|
||||||
call os_read_cli.finish
|
call os_read_cli.finish
|
||||||
cat:
|
.cat:
|
||||||
call util_cat
|
call util_cat
|
||||||
call os_read_cli.finish
|
call os_read_cli.finish
|
||||||
ls:
|
.ls:
|
||||||
call util_ls
|
call util_ls
|
||||||
call os_read_cli.finish
|
call os_read_cli.finish
|
||||||
|
.ed:
|
||||||
|
call util_ed
|
||||||
|
call os_read_cli.finish
|
||||||
|
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ disk_clear_output_buffer:
|
|||||||
; OUT
|
; OUT
|
||||||
; data_buffer: file contents
|
; data_buffer: file contents
|
||||||
; TODO use predefined data for calculations
|
; TODO use predefined data for calculations
|
||||||
|
; CX = 0 if failed to load
|
||||||
disk_load_file:
|
disk_load_file:
|
||||||
pusha
|
pusha
|
||||||
call string_length ; cl = string length
|
call string_length ; cl = string length
|
||||||
@@ -227,13 +228,18 @@ disk_load_file:
|
|||||||
.file_not_found:
|
.file_not_found:
|
||||||
mov si, file_not_found
|
mov si, file_not_found
|
||||||
call os_print_string
|
call os_print_string
|
||||||
jmp .done
|
jmp .done_fail
|
||||||
.filename_too_long:
|
.filename_too_long:
|
||||||
mov si, too_long_filename
|
mov si, too_long_filename
|
||||||
call os_print_string
|
call os_print_string
|
||||||
jmp .done
|
jmp .done_fail
|
||||||
|
.done_fail:
|
||||||
|
popa
|
||||||
|
mov bx, 1
|
||||||
|
ret
|
||||||
.done:
|
.done:
|
||||||
popa
|
popa
|
||||||
|
xor bx,bx
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Write data to file
|
; Write data to file
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ os_read_input:
|
|||||||
|
|
||||||
; AX = key pressed
|
; AX = key pressed
|
||||||
; Returns straight away
|
; Returns straight away
|
||||||
|
; carry flag is set when escape is pressed and data is returned straight away
|
||||||
keyboard_check_key:
|
keyboard_check_key:
|
||||||
xor ax,ax
|
xor ax,ax
|
||||||
mov ah, 11h ; BIOS call to check for key
|
mov ah, 11h ; BIOS call to check for key
|
||||||
@@ -27,12 +28,13 @@ keyboard_check_key:
|
|||||||
; IN:
|
; IN:
|
||||||
; AX = output address
|
; AX = output address
|
||||||
; BX = max length
|
; BX = max length
|
||||||
|
; OUT:
|
||||||
|
; BX = 1 if escape is pressed
|
||||||
keyboard_display_input:
|
keyboard_display_input:
|
||||||
pusha
|
pusha
|
||||||
mov di, ax
|
mov di, ax
|
||||||
mov ax, bx
|
xor ax,ax
|
||||||
mov bx,20
|
mov [prompt_length], bx
|
||||||
|
|
||||||
.check_key_pressed:
|
.check_key_pressed:
|
||||||
call os_read_input
|
call os_read_input
|
||||||
@@ -55,16 +57,19 @@ keyboard_display_input:
|
|||||||
jmp .check_key_pressed
|
jmp .check_key_pressed
|
||||||
|
|
||||||
.esc_key:
|
.esc_key:
|
||||||
call power_reboot
|
popa
|
||||||
|
mov bx, 1
|
||||||
|
ret
|
||||||
|
|
||||||
.enter_key:
|
.enter_key:
|
||||||
mov al, 0
|
mov al, 0
|
||||||
stosb
|
stosb
|
||||||
popa
|
popa
|
||||||
|
xor bx,bx
|
||||||
ret ; Return to the parent function (whatever that may be)
|
ret ; Return to the parent function (whatever that may be)
|
||||||
|
|
||||||
.backspace:
|
.backspace:
|
||||||
cmp bx, 20 ; Cannot backspace if the cursor is at the start
|
cmp bx, [prompt_length] ; Cannot backspace if the cursor is at the start
|
||||||
jb .move_cursor_back ; then .move_cursor_back
|
jb .move_cursor_back ; then .move_cursor_back
|
||||||
jmp .check_key_pressed ; Else check the next key
|
jmp .check_key_pressed ; Else check the next key
|
||||||
|
|
||||||
@@ -87,6 +92,7 @@ keyboard_display_input:
|
|||||||
mov ah, 0Eh
|
mov ah, 0Eh
|
||||||
int 10h
|
int 10h
|
||||||
jmp .check_key_pressed
|
jmp .check_key_pressed
|
||||||
|
.input_length db 0
|
||||||
|
|
||||||
keyboard_get_cursor_pos:
|
keyboard_get_cursor_pos:
|
||||||
ret
|
ret
|
||||||
|
|||||||
@@ -106,35 +106,42 @@ string_join:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
; ------------------------------------------------------------------------
|
; ------------------------------------------------------------------------
|
||||||
; TODO
|
; Converts a string to an integer
|
||||||
; Converts a null terminated string to an integer
|
|
||||||
; IN: SI = string location (max 5 chars, up to '65536')
|
; IN: SI = string location (max 5 chars, up to '65536')
|
||||||
; OUT: AX = number
|
; OUT: AX = number, DX = length of int string
|
||||||
string_cast_to_int:
|
string_cast_to_int:
|
||||||
pusha
|
push cx
|
||||||
|
push bx
|
||||||
|
push dx
|
||||||
xor cx,cx
|
xor cx,cx
|
||||||
.loop:
|
.loop:
|
||||||
xor ax,ax
|
xor ax,ax
|
||||||
lodsb
|
lodsb
|
||||||
cmp al, 0
|
|
||||||
je .finish
|
; Exit if the character is not a number
|
||||||
sub al, 30h
|
cmp al,'0'
|
||||||
|
jl .finish
|
||||||
|
cmp al,'9'
|
||||||
|
jg .finish
|
||||||
|
|
||||||
|
sub al, '0'
|
||||||
mov bx, ax
|
mov bx, ax
|
||||||
|
|
||||||
mov ax, 10
|
mov ax, 10
|
||||||
mul cx ; Multiple the current value by 10
|
mul cx ; Multiple the current value by 10
|
||||||
add ax, bx ; Then add the new digit
|
add ax, bx ; Then add the new digit
|
||||||
mov cx, ax
|
mov cx, ax
|
||||||
jmp .loop
|
jmp .loop
|
||||||
.finish:
|
.finish:
|
||||||
mov [int_tmp], cx
|
mov ax,cx
|
||||||
popa
|
pop dx
|
||||||
mov ax, [int_tmp]
|
pop bx
|
||||||
|
pop cx
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; ------------------------------------------------------------------------
|
; ------------------------------------------------------------------------
|
||||||
; IN: AX = integer (unsigned)
|
; IN: AX = integer (unsigned)
|
||||||
; OUT: AX -> null-terminated string
|
; OUT: AX -> null-terminated string
|
||||||
|
|
||||||
string_cast_from_int:
|
string_cast_from_int:
|
||||||
pusha
|
pusha
|
||||||
cld ; Write backwards
|
cld ; Write backwards
|
||||||
|
|||||||
@@ -55,10 +55,16 @@ text_print_raw:
|
|||||||
je .space
|
je .space
|
||||||
cmp al, 0Ah ; When there's an NL or CR, do both, linux encodes files only with NL
|
cmp al, 0Ah ; When there's an NL or CR, do both, linux encodes files only with NL
|
||||||
je .new_line
|
je .new_line
|
||||||
|
cmp al, 09h ; TAB
|
||||||
|
je .tab
|
||||||
cmp al, 0Dh
|
cmp al, 0Dh
|
||||||
je .repeat
|
je .repeat
|
||||||
int 10h
|
int 10h
|
||||||
jmp .repeat
|
jmp .repeat
|
||||||
|
.tab:
|
||||||
|
mov al, ' '
|
||||||
|
int 10h
|
||||||
|
jmp .repeat
|
||||||
.space:
|
.space:
|
||||||
mov al, 20h
|
mov al, 20h
|
||||||
int 10h
|
int 10h
|
||||||
@@ -130,6 +136,15 @@ os_set_text_mode:
|
|||||||
mov dl, 0
|
mov dl, 0
|
||||||
int 10h
|
int 10h
|
||||||
|
|
||||||
|
text_newline:
|
||||||
|
pusha
|
||||||
|
mov ax,0E0Ah
|
||||||
|
int 10h
|
||||||
|
mov al,0Dh
|
||||||
|
int 10h
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
popa
|
popa
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,33 @@
|
|||||||
util_cat:
|
util_cat:
|
||||||
pusha
|
pusha
|
||||||
|
|
||||||
call disk_clear_file_buffer
|
call disk_clear_file_buffer
|
||||||
mov si, user_input
|
mov si, user_input
|
||||||
; TODO make this more consistent to account for double spaces
|
; TODO make this more consistent to account for double spaces
|
||||||
add si, 4 ; Move si to after 'CAT'
|
add si, 4 ; Move si to after 'CAT'
|
||||||
|
|
||||||
call disk_load_file
|
call disk_load_file
|
||||||
mov si, file_buffer
|
cmp bx, 1
|
||||||
mov cx, [file_length]
|
je .done
|
||||||
call text_print_raw
|
|
||||||
|
|
||||||
popa
|
mov si, file_buffer
|
||||||
ret
|
mov cx, [file_length]
|
||||||
|
call text_print_raw
|
||||||
|
.done
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
util_ls:
|
util_ls:
|
||||||
pusha
|
pusha
|
||||||
|
|
||||||
call disk_list_contents
|
call disk_list_contents
|
||||||
|
|
||||||
mov si, output_buffer
|
mov si, output_buffer
|
||||||
call os_print_string
|
call os_print_string
|
||||||
call disk_clear_output_buffer
|
call disk_clear_output_buffer
|
||||||
|
|
||||||
popa
|
popa
|
||||||
ret
|
ret
|
||||||
|
|
||||||
util_basic:
|
util_basic:
|
||||||
pusha
|
pusha
|
||||||
@@ -34,6 +37,8 @@ util_basic:
|
|||||||
; TODO make this more consistent to account for double spaces
|
; TODO make this more consistent to account for double spaces
|
||||||
;add si, 3 ; Move si to after 'BAS'
|
;add si, 3 ; Move si to after 'BAS'
|
||||||
call disk_load_file
|
call disk_load_file
|
||||||
|
cmp bx, 1
|
||||||
|
je .done
|
||||||
|
|
||||||
mov si, file_buffer
|
mov si, file_buffer
|
||||||
|
|
||||||
@@ -41,5 +46,16 @@ util_basic:
|
|||||||
mov si, 0
|
mov si, 0
|
||||||
call basic_run_basic
|
call basic_run_basic
|
||||||
|
|
||||||
|
.done
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
util_ed:
|
||||||
|
pusha
|
||||||
|
call disk_load_root
|
||||||
|
call disk_load_file
|
||||||
|
|
||||||
|
call ed
|
||||||
|
|
||||||
popa
|
popa
|
||||||
ret
|
ret
|
||||||
|
|||||||
@@ -33,13 +33,19 @@ halt:
|
|||||||
%INCLUDE "source/kernel/features/sound.asm"
|
%INCLUDE "source/kernel/features/sound.asm"
|
||||||
%INCLUDE "source/kernel/features/disk.asm"
|
%INCLUDE "source/kernel/features/disk.asm"
|
||||||
%INCLUDE "source/kernel/features/math.asm"
|
%INCLUDE "source/kernel/features/math.asm"
|
||||||
|
%INCLUDE "source/kernel/features/check.asm"
|
||||||
%INCLUDE "source/kernel/features/time.asm"
|
%INCLUDE "source/kernel/features/time.asm"
|
||||||
%INCLUDE "source/kernel/features/utils.asm"
|
%INCLUDE "source/kernel/features/utils.asm"
|
||||||
%INCLUDE "source/kernel/features/cli.asm"
|
%INCLUDE "source/kernel/features/cli.asm"
|
||||||
%INCLUDE "source/kernel/features/misc.asm"
|
%INCLUDE "source/kernel/features/misc.asm"
|
||||||
%INCLUDE "source/kernel/features/basic.asm"
|
%INCLUDE "source/kernel/features/basic.asm"
|
||||||
|
|
||||||
|
; PROGRAMS
|
||||||
|
%INCLUDE "source/kernel/programs/ed.asm"
|
||||||
|
|
||||||
; DATA/VARIABLES
|
; DATA/VARIABLES
|
||||||
%INCLUDE "source/kernel/data.asm"
|
%INCLUDE "source/kernel/data.asm"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,279 @@
|
|||||||
|
; Planned commands:
|
||||||
|
; [ ] i insert
|
||||||
|
; [ ] a append
|
||||||
|
; [-] d delete
|
||||||
|
; [x] l prints lines
|
||||||
|
; [ ] w save to disk
|
||||||
|
; [x] q quit
|
||||||
|
ed:
|
||||||
|
pusha
|
||||||
|
call determine_line_count
|
||||||
|
.main_loop:
|
||||||
|
; CLEAR VARIABLES
|
||||||
|
mov [ed_start_int], 0
|
||||||
|
mov [ed_end_int], 0
|
||||||
|
mov [ed_operation_from], 0
|
||||||
|
mov [ed_operation_by], 0
|
||||||
|
|
||||||
|
; Setup prompt
|
||||||
|
mov ax, ed_prompt
|
||||||
|
mov bx, 40
|
||||||
|
call keyboard_display_input ; AX = string location, BX = max prompt length
|
||||||
|
cmp bx, 1 ; I user pressed escape
|
||||||
|
je .quit
|
||||||
|
mov si, ed_prompt
|
||||||
|
mov bx, 0 ; Keeps track of whether comma has passed
|
||||||
|
jmp .get_token
|
||||||
|
|
||||||
|
.error:
|
||||||
|
call ed_error
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
; Types of tokens:
|
||||||
|
; Number: eg 123
|
||||||
|
; Doller (refers to the last line) $
|
||||||
|
; Comma ,
|
||||||
|
; Command: eg i
|
||||||
|
; eg 123,127i
|
||||||
|
.get_token:
|
||||||
|
lodsb
|
||||||
|
|
||||||
|
; COMMA
|
||||||
|
cmp al, ','
|
||||||
|
je .comma
|
||||||
|
|
||||||
|
; DOLLAR SIGN
|
||||||
|
cmp al, '$'
|
||||||
|
je .dollar
|
||||||
|
|
||||||
|
; NUMBER
|
||||||
|
call check_is_number
|
||||||
|
jc .get_number_token
|
||||||
|
|
||||||
|
; COMMAND
|
||||||
|
call check_is_letter
|
||||||
|
jc .get_letter_token
|
||||||
|
jmp .error
|
||||||
|
|
||||||
|
; Assign a number to either the start or end int (start,end)
|
||||||
|
.dollar:
|
||||||
|
mov ax, [ed_line_count]
|
||||||
|
inc si ; Cancel out the last dec si
|
||||||
|
jmp .after_int_cast
|
||||||
|
.get_number_token:
|
||||||
|
dec si
|
||||||
|
call string_cast_to_int ; AX = integer, DX = length of int string
|
||||||
|
.after_int_cast:
|
||||||
|
cmp bx, 0
|
||||||
|
je .assign_start_int
|
||||||
|
jg .assign_end_int
|
||||||
|
.assign_start_int:
|
||||||
|
mov [ed_start_int], ax
|
||||||
|
jmp .after_int_assign
|
||||||
|
.assign_end_int:
|
||||||
|
mov [ed_end_int], ax
|
||||||
|
|
||||||
|
; Check it's not after the end of the file
|
||||||
|
cmp ax, [ed_line_count]
|
||||||
|
jg .error
|
||||||
|
; Check it's not less than the start int
|
||||||
|
cmp ax, [ed_start_int]
|
||||||
|
jl .error
|
||||||
|
.after_int_assign:
|
||||||
|
dec si
|
||||||
|
jmp .get_token
|
||||||
|
|
||||||
|
|
||||||
|
; Determines a command
|
||||||
|
.get_letter_token:
|
||||||
|
; If ed int
|
||||||
|
cmp [ed_end_int], 0
|
||||||
|
je .set_end_int
|
||||||
|
.after_end_int_check:
|
||||||
|
cmp al, 'l'
|
||||||
|
je .list
|
||||||
|
cmp al, 'd'
|
||||||
|
je .delete
|
||||||
|
cmp al, 'q'
|
||||||
|
je .quit
|
||||||
|
call ed_error
|
||||||
|
jmp .main_loop
|
||||||
|
; If no end int is assigned, set it to the start int
|
||||||
|
.set_end_int:
|
||||||
|
cmp bx,0
|
||||||
|
push ax
|
||||||
|
jne .end_int_to_end ; If , has been passed
|
||||||
|
.end_int_to_start_int:
|
||||||
|
mov ax, [ed_start_int]
|
||||||
|
mov [ed_end_int], ax
|
||||||
|
pop ax
|
||||||
|
jmp .after_end_int_check
|
||||||
|
.end_int_to_end:
|
||||||
|
mov ax, [ed_line_count]
|
||||||
|
mov [ed_end_int], ax
|
||||||
|
pop ax
|
||||||
|
jmp .after_end_int_check
|
||||||
|
|
||||||
|
|
||||||
|
; Changes the value from start int to end int
|
||||||
|
.comma:
|
||||||
|
mov bx, 1
|
||||||
|
jmp .get_token
|
||||||
|
|
||||||
|
|
||||||
|
; COMMANDS
|
||||||
|
; DELETE ;
|
||||||
|
.delete:
|
||||||
|
; Adjust the ed line count
|
||||||
|
mov ax,[ed_end_int]
|
||||||
|
sub ax,[ed_start_int] ; difference in the lines
|
||||||
|
inc ax
|
||||||
|
sub [ed_line_count], ax
|
||||||
|
|
||||||
|
; set up registers to shift data left
|
||||||
|
; Get the byte of where the left shift will start
|
||||||
|
mov bx, [ed_end_int]
|
||||||
|
inc bx
|
||||||
|
call get_byte_of_line ; CX = byte of start of new line (relative to file buffer)
|
||||||
|
mov [ed_operation_from], cx
|
||||||
|
|
||||||
|
; Get the number of bytes to shift left by
|
||||||
|
mov bx, [ed_start_int]
|
||||||
|
call get_byte_of_line
|
||||||
|
mov ax, [ed_operation_from]
|
||||||
|
sub ax, cx
|
||||||
|
mov [ed_operation_by], ax
|
||||||
|
|
||||||
|
; Perform the shift
|
||||||
|
call shift_data_left
|
||||||
|
|
||||||
|
; Adjust the file metadata byte count
|
||||||
|
mov ax, [file_length]
|
||||||
|
sub ax, [ed_operation_by]
|
||||||
|
mov [file_length], ax
|
||||||
|
|
||||||
|
; Exit
|
||||||
|
call text_newline
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
|
||||||
|
; LIST ;
|
||||||
|
.list:
|
||||||
|
; set up registers to print the data
|
||||||
|
; Get the byte of where the printing will start
|
||||||
|
mov bx, [ed_start_int]
|
||||||
|
call get_byte_of_line ; CX = byte of start of new line (relative to file buffer)
|
||||||
|
mov si, cx
|
||||||
|
|
||||||
|
; Get the number of bytes to print
|
||||||
|
mov bx,[ed_end_int]
|
||||||
|
inc bx
|
||||||
|
call get_byte_of_line
|
||||||
|
sub cx,si
|
||||||
|
|
||||||
|
call text_newline
|
||||||
|
add si, file_buffer
|
||||||
|
call text_print_raw
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.quit:
|
||||||
|
popa
|
||||||
|
jmp os_start_cli
|
||||||
|
|
||||||
|
; This could probably go in disk_?
|
||||||
|
shift_data_left:
|
||||||
|
; Calculate source pointer
|
||||||
|
mov si, [ed_operation_by]
|
||||||
|
add si, file_buffer
|
||||||
|
|
||||||
|
; Calculate destination pointer
|
||||||
|
mov di, si
|
||||||
|
sub di, [ed_operation_by]
|
||||||
|
|
||||||
|
; Loop count
|
||||||
|
mov cx, file_length ; STORES THE LENGTH OF THE FILE IN BYTES
|
||||||
|
sub cx, ed_operation_by
|
||||||
|
|
||||||
|
; Perform the actual left shift
|
||||||
|
rep movsb
|
||||||
|
|
||||||
|
; Override the rest with zeroes
|
||||||
|
mov cx, [ed_operation_by]
|
||||||
|
mov al, 0
|
||||||
|
rep stosb
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
ed_error:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
call text_newline
|
||||||
|
mov ah, 0Eh
|
||||||
|
mov al, '?'
|
||||||
|
int 10h
|
||||||
|
call text_newline
|
||||||
|
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
; IN: BX = target line
|
||||||
|
; OUT: CX = relative byte
|
||||||
|
; TODO fix
|
||||||
|
get_byte_of_line:
|
||||||
|
push dx
|
||||||
|
push si
|
||||||
|
push ax
|
||||||
|
|
||||||
|
mov si, file_buffer
|
||||||
|
|
||||||
|
xor dx,dx
|
||||||
|
xor cx,cx
|
||||||
|
|
||||||
|
jmp .increment_line_count
|
||||||
|
.line_loop:
|
||||||
|
xor ax,ax
|
||||||
|
lodsb
|
||||||
|
inc cx
|
||||||
|
|
||||||
|
cmp al, 0Ah
|
||||||
|
je .increment_line_count
|
||||||
|
|
||||||
|
jmp .line_loop
|
||||||
|
.increment_line_count:
|
||||||
|
inc dx
|
||||||
|
cmp dx, bx
|
||||||
|
jl .line_loop
|
||||||
|
jmp .exit
|
||||||
|
.exit:
|
||||||
|
pop ax
|
||||||
|
pop si
|
||||||
|
pop dx
|
||||||
|
ret
|
||||||
|
|
||||||
|
determine_line_count:
|
||||||
|
mov si, file_buffer
|
||||||
|
mov dx, file_length ; STORES THE LENGTH OF THE FILE IN BYTES
|
||||||
|
xor cx,cx
|
||||||
|
.line_count_loop:
|
||||||
|
lodsb
|
||||||
|
cmp al, 0Ah
|
||||||
|
je .increment_line_count
|
||||||
|
dec dx
|
||||||
|
cmp dx, 0
|
||||||
|
jg .line_count_loop
|
||||||
|
mov [ed_line_count], cx
|
||||||
|
ret
|
||||||
|
.increment_line_count:
|
||||||
|
inc cx
|
||||||
|
jmp .line_count_loop
|
||||||
|
|
||||||
|
ed_data_start: db "ED IS COOL"
|
||||||
|
ed_prompt: times 40 db 0
|
||||||
|
ed_start_int: dw 1
|
||||||
|
ed_end_int: dw 0
|
||||||
|
|
||||||
|
ed_line_count: dw 0
|
||||||
|
|
||||||
|
ed_operation_from: dw 0
|
||||||
|
ed_operation_by: dw 0
|
||||||
|
ed_tmp: dd 0
|
||||||
|
|||||||
Reference in New Issue
Block a user