BASIC Interpreter from MikeOS is functioning
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
*.swp
|
||||
disk_images/*
|
||||
tmp-loop/*
|
||||
detailed.log
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
Kernel written in Assmebly<br/>
|
||||
I'm using a modified JazzOS Bootloader<br/>
|
||||
And the MikeOS BASIC Interpreter<br/>
|
||||
|
||||
2
data/hello.bas
Normal file
2
data/hello.bas
Normal file
@@ -0,0 +1,2 @@
|
||||
PRINT "Hello World!"
|
||||
END
|
||||
@@ -1 +0,0 @@
|
||||
output 'Hello World'
|
||||
@@ -10,7 +10,7 @@ bdb_bytes_per_sector: dw 200h ; = 512d
|
||||
bdb_sectors_per_cluster: db 01h ; sector = cluster
|
||||
bdb_reserved_sectors: dw 01h
|
||||
bdb_fat_count: db 02h ; We've got a fat1 and fat2
|
||||
bdb_dir_entries_count: dw 0E0h ; Maximum number of root directory entries
|
||||
bdb_dir_entries_count: dw 0E0h ; = 224d Maximum number of root directory entries
|
||||
bdb_total_sectors: dw 0B40h ; = 2880d
|
||||
bdb_media_descriptor_type: db 0F0h ; ignore
|
||||
bdb_sectors_per_fat: dw 09h
|
||||
@@ -68,7 +68,7 @@ main:
|
||||
shl ax,5 ; ax *= 32 (shifting 5 times)
|
||||
xor dx,dx ; Clear dx (remainder)
|
||||
div word [bdb_bytes_per_sector] ;(32*num of entries)/bytes per sector = total number of sectors we need to read
|
||||
test dx,dx ; See if there's a remainder
|
||||
test dx,dx ; See if there's a remainder, ie the root directory doesn't take up a whole number of sectors
|
||||
jz root_dir_after
|
||||
inc ax ; Add one if there's a remainder (this is like rounding up)
|
||||
|
||||
|
||||
@@ -22,20 +22,23 @@ ebr_volume_label: db 'CRAWOS0.0.6' ; must be 11 bytes
|
||||
ebr_system_id: db 'FAT12 ' ; must be 8 bytes
|
||||
|
||||
|
||||
; String operations
|
||||
fat12_file_name: db ' ' ; 11 free bytes to store a filename in
|
||||
boot_message: db 'OK] Kernel successfully loaded!\n\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
|
||||
prompt_length: db 20
|
||||
prompt: db 'sh > ', 0
|
||||
help_string: db 'HELP', 0
|
||||
clear_string: db 'CLEAR', 0
|
||||
reboot_string: db 'REBOOT', 0
|
||||
pong_string: db 'PONG', 0
|
||||
basic_string: db 'BAS', 0
|
||||
cat_string: db 'CAT', 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"HELP" for this helpful text,\n"CLEAR" to clear the screen,\n"REBOOT" or esc to reboot\n', 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
|
||||
basic_text: db 'BASIC PROGRAM BEGUN:\n', 0
|
||||
command_result_text: db 'You typed: ', 0
|
||||
unknown_command: db 'Error: Unkown Command..\n ', 0
|
||||
stringified_int: db 0,0,0,0,0,0 ; Can store up to 6 digits
|
||||
|
||||
; Disk operations
|
||||
disk_read_fail: db 'Error: Could not read disk\n', 0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ os_start_cli:
|
||||
os_read_cli:
|
||||
pusha
|
||||
mov si, user_input
|
||||
call os_upper_case ; Make the input uppercase so it's case insensitive
|
||||
call string_upper_case ; Make the input uppercase so it's case insensitive
|
||||
|
||||
.output_the_user_input:
|
||||
call os_print_newline
|
||||
@@ -45,6 +45,13 @@ os_read_cli:
|
||||
cmp cl, 1
|
||||
je power_reboot
|
||||
|
||||
; Basic
|
||||
mov si, user_input
|
||||
mov di, basic_string
|
||||
call os_compare_strings
|
||||
cmp cl, 1
|
||||
je basic
|
||||
|
||||
; Cat
|
||||
mov si, user_input
|
||||
mov di, cat_string
|
||||
@@ -59,13 +66,6 @@ os_read_cli:
|
||||
cmp cl, 1
|
||||
je ls
|
||||
|
||||
; Pong
|
||||
mov si, user_input
|
||||
mov di, pong_string
|
||||
call os_compare_strings
|
||||
cmp cl, 1
|
||||
je pong
|
||||
|
||||
jmp .unkown
|
||||
|
||||
.unkown:
|
||||
@@ -88,10 +88,9 @@ help:
|
||||
call os_print_string
|
||||
call os_read_cli.finish
|
||||
|
||||
pong:
|
||||
call game_pong
|
||||
basic:
|
||||
call util_basic
|
||||
call os_read_cli.finish
|
||||
|
||||
cat:
|
||||
call util_cat
|
||||
call os_read_cli.finish
|
||||
|
||||
@@ -173,7 +173,7 @@ disk_clear_output_buffer:
|
||||
; TODO use predefined data for calculations
|
||||
disk_load_file:
|
||||
pusha
|
||||
call os_string_length ; cl = string length
|
||||
call string_length ; cl = string length
|
||||
cmp cl, 11
|
||||
ja .filename_too_long
|
||||
|
||||
@@ -244,7 +244,7 @@ disk_load_file:
|
||||
disk_write_file:
|
||||
pusha
|
||||
; Check if file name is too long
|
||||
call os_string_length ; cl = string length
|
||||
call string_length ; cl = string length
|
||||
cmp cl, 11
|
||||
ja .filename_too_long
|
||||
; Convert file name to a fat filename
|
||||
@@ -302,6 +302,7 @@ disk_write_file:
|
||||
ret
|
||||
|
||||
; TODO support long file names
|
||||
; TODO don't work twice
|
||||
; Store a list of the files in file_buffer
|
||||
; in a human readable format
|
||||
; OUT
|
||||
@@ -374,3 +375,14 @@ disk_list_contents:
|
||||
stosb
|
||||
popa
|
||||
ret
|
||||
|
||||
disk_file_exists:
|
||||
ret
|
||||
disk_file_size:
|
||||
ret
|
||||
disk_file_list:
|
||||
ret
|
||||
disk_remove_file:
|
||||
ret
|
||||
disk_rename_file:
|
||||
ret
|
||||
|
||||
@@ -51,3 +51,10 @@ section .data
|
||||
y_end dw 0
|
||||
colour db 1111b
|
||||
|
||||
graphics_dialogue_box:
|
||||
ret
|
||||
|
||||
graphics_file_selector:
|
||||
ret
|
||||
graphics_list_dialogue:
|
||||
ret
|
||||
|
||||
@@ -7,10 +7,10 @@ os_read_input:
|
||||
hlt
|
||||
jmp os_read_input
|
||||
|
||||
.key_pressed:
|
||||
mov ah, 10h
|
||||
int 16h
|
||||
ret
|
||||
.key_pressed:
|
||||
mov ah, 10h
|
||||
int 16h
|
||||
ret
|
||||
|
||||
; -------------------------------------------
|
||||
|
||||
@@ -18,60 +18,73 @@ os_display_input:
|
||||
pusha
|
||||
mov cx, [prompt_length]
|
||||
|
||||
.loop:
|
||||
call .check_key_pressed
|
||||
.loop:
|
||||
call .check_key_pressed
|
||||
|
||||
jmp .loop
|
||||
jmp .loop
|
||||
|
||||
.check_key_pressed:
|
||||
call os_read_input
|
||||
.check_key_pressed:
|
||||
call os_read_input
|
||||
|
||||
cmp al, 08h
|
||||
je .backspace
|
||||
cmp al, 08h
|
||||
je .backspace
|
||||
|
||||
cmp al, 0Dh
|
||||
je .enter_key
|
||||
cmp al, 0Dh
|
||||
je .enter_key
|
||||
|
||||
cmp al, 1Bh
|
||||
je .esc_key
|
||||
cmp al, 1Bh
|
||||
je .esc_key
|
||||
|
||||
cmp cx, 0
|
||||
jb .check_key_pressed
|
||||
cmp cx, 0
|
||||
jb .check_key_pressed
|
||||
|
||||
call .print_current_input
|
||||
dec cx
|
||||
jmp .check_key_pressed
|
||||
call .print_current_input
|
||||
dec cx
|
||||
jmp .check_key_pressed
|
||||
|
||||
.esc_key:
|
||||
call power_reboot
|
||||
.esc_key:
|
||||
call power_reboot
|
||||
|
||||
.enter_key:
|
||||
mov al, 0
|
||||
stosb
|
||||
popa
|
||||
call os_read_cli
|
||||
.enter_key:
|
||||
mov al, 0
|
||||
stosb
|
||||
popa
|
||||
call os_read_cli
|
||||
|
||||
.backspace:
|
||||
call .move_cursor_back ; then .move_cursor_back
|
||||
call .loop ; Else .loop
|
||||
.backspace:
|
||||
call .move_cursor_back ; then .move_cursor_back
|
||||
call .loop ; Else .loop
|
||||
|
||||
.move_cursor_back:
|
||||
mov ah, 0Eh
|
||||
.move_cursor_back:
|
||||
mov ah, 0Eh
|
||||
|
||||
mov al, 08h
|
||||
int 10h
|
||||
mov al, 20h
|
||||
int 10h
|
||||
mov al, 08h
|
||||
int 10h
|
||||
mov al, 08h
|
||||
int 10h
|
||||
mov al, 20h
|
||||
int 10h
|
||||
mov al, 08h
|
||||
int 10h
|
||||
|
||||
dec di
|
||||
jmp os_display_input
|
||||
dec di
|
||||
jmp os_display_input
|
||||
|
||||
.print_current_input:
|
||||
stosb
|
||||
.print_current_input:
|
||||
stosb
|
||||
|
||||
mov ah, 0Eh
|
||||
int 10h
|
||||
mov ah, 0Eh
|
||||
int 10h
|
||||
|
||||
ret
|
||||
|
||||
keyboard_get_cursor_pos: ;TODO
|
||||
ret
|
||||
keyboard_wait_for_key: ;TODO
|
||||
ret
|
||||
keyboard_show_cursor:
|
||||
ret
|
||||
keyboard_hide_cursor:
|
||||
ret
|
||||
keyboard_move_cursor:
|
||||
ret
|
||||
keyboard_check_key:
|
||||
ret
|
||||
|
||||
@@ -52,3 +52,5 @@ math_lba_to_chs:
|
||||
pop ax
|
||||
|
||||
ret
|
||||
math_get_random:
|
||||
ret
|
||||
|
||||
4
source/kernel/features/misc.asm
Normal file
4
source/kernel/features/misc.asm
Normal file
@@ -0,0 +1,4 @@
|
||||
misc_pause:
|
||||
ret
|
||||
misc_get_api_version:
|
||||
ret
|
||||
10
source/kernel/features/ports.asm
Normal file
10
source/kernel/features/ports.asm
Normal file
@@ -0,0 +1,10 @@
|
||||
port_byte_out:
|
||||
ret
|
||||
port_byte_in:
|
||||
ret
|
||||
port_serial_enable:
|
||||
ret
|
||||
port_send_via_serial:
|
||||
ret
|
||||
port_get_via_serial:
|
||||
ret
|
||||
@@ -0,0 +1,4 @@
|
||||
sound_speaker_tone:
|
||||
ret
|
||||
sound_speaker_off:
|
||||
ret
|
||||
|
||||
@@ -11,35 +11,176 @@
|
||||
os_compare_strings:
|
||||
cld
|
||||
|
||||
.compare:
|
||||
mov al, 0
|
||||
scasb
|
||||
je .di_ended
|
||||
dec di
|
||||
lodsb
|
||||
scasb ; Compare di to si
|
||||
jne .unequal ; If they are not equal, jump to .unequal
|
||||
jmp .compare ; Finally, repeat
|
||||
.compare:
|
||||
mov al, 0
|
||||
scasb
|
||||
je .di_ended
|
||||
dec di
|
||||
lodsb
|
||||
scasb ; Compare di to si
|
||||
jne .unequal ; If they are not equal, jump to .unequal
|
||||
jmp .compare ; Finally, repeat
|
||||
|
||||
.unequal:
|
||||
mov cl, 0 ; Change to 0 if unquality is proven
|
||||
ret
|
||||
.di_ended:
|
||||
lodsb
|
||||
cmp al, 20h ; 20h = space
|
||||
je .equal
|
||||
cmp al, 0
|
||||
je .equal
|
||||
jmp .unequal
|
||||
.equal:
|
||||
mov cl, 1
|
||||
.unequal:
|
||||
mov cl, 0 ; Change to 0 if unquality is proven
|
||||
ret
|
||||
.di_ended:
|
||||
lodsb
|
||||
cmp al, 20h ; 20h = space
|
||||
je .equal
|
||||
cmp al, 0
|
||||
je .equal
|
||||
jmp .unequal
|
||||
.equal:
|
||||
mov cl, 1
|
||||
ret
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; os_string_compare -- See if two strings match
|
||||
; IN: SI = string one, DI = string two
|
||||
; OUT: carry set if same, clear if different
|
||||
; from MikeOS kernel
|
||||
|
||||
string_direct_compare:
|
||||
pusha
|
||||
.more:
|
||||
mov al, [si] ; Retrieve string contents
|
||||
mov bl, [di]
|
||||
cmp al, bl ; Compare characters at current location
|
||||
jne .not_same
|
||||
cmp al, 0 ; End of first string? Must also be end of second
|
||||
je .end
|
||||
inc si
|
||||
inc di
|
||||
jmp .more
|
||||
.not_same: ; If unequal lengths with same beginning, the byte
|
||||
popa ; comparison fails at shortest string terminator
|
||||
clc ; Clear carry flag
|
||||
ret
|
||||
.end: ; Both strings terminated at the same position
|
||||
popa
|
||||
stc ; Set carry flag
|
||||
ret
|
||||
|
||||
|
||||
; --------------------------------------------------------------------
|
||||
; Copies a string from si to di
|
||||
; IN:
|
||||
; si: points to first character of source string
|
||||
; OUT:
|
||||
; di: points to first character of destination string
|
||||
string_copy:
|
||||
pusha
|
||||
.loop:
|
||||
; TODO could this cause issue when a character is > 1 byte?
|
||||
lodsb ; Load si character into ax and increment si by 1
|
||||
stosb ; Store ax in di location and increment di by 1
|
||||
cmp ax, 0 ; if ax is a 0, quit
|
||||
jne .loop
|
||||
.done:
|
||||
popa
|
||||
ret
|
||||
|
||||
; --------------------------------------------------------------------
|
||||
; Joins two strings together into a new string
|
||||
; IN/OUT:
|
||||
; ax: string1
|
||||
; bx: string2
|
||||
; cx: result string
|
||||
|
||||
string_join:
|
||||
pusha
|
||||
.copy_string1:
|
||||
mov si, ax
|
||||
mov di, cx
|
||||
call string_copy
|
||||
mov ax, cx ; TODO check this bit
|
||||
call string_length
|
||||
add cx, ax
|
||||
.copy_string2:
|
||||
mov si, bx
|
||||
mov di, dx
|
||||
call string_copy
|
||||
.done:
|
||||
popa
|
||||
ret
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; TODO
|
||||
string_cast_to_int:
|
||||
ret
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
; IN: AX = int
|
||||
; OUT: AX = string location (output buffer)
|
||||
string_cast_from_int: ; TODO I think this algorithm could be optimised
|
||||
pusha
|
||||
; Initialise base to decimal (base 10)
|
||||
mov bx, 10
|
||||
; clear the strigified int location
|
||||
mov cx, 6
|
||||
push ax
|
||||
xor ax,ax
|
||||
.clear_loop:
|
||||
stosb
|
||||
dec cx
|
||||
cmp cx, 0
|
||||
ja .clear_loop
|
||||
; setup
|
||||
pop ax
|
||||
push ax
|
||||
mov cx, -1
|
||||
; loop over number to get the value of count (cx)
|
||||
.count_loop:
|
||||
xor dx,dx
|
||||
div bx ; ax = ax // bx
|
||||
inc cx
|
||||
cmp ax, 0
|
||||
ja .count_loop ; Jump if greater
|
||||
pop ax
|
||||
; loop over count downwards until count is 0
|
||||
mov di, stringified_int
|
||||
.stringify_loop:
|
||||
mov cx,1 ;DEL
|
||||
push cx
|
||||
push bx
|
||||
push ax
|
||||
; Generate power of 10
|
||||
mov ax, 1
|
||||
mov cx,0 ;DEL
|
||||
cmp cx, 1
|
||||
jl .after_power_loop
|
||||
.power_loop:
|
||||
mul bx
|
||||
dec cx
|
||||
cmp cx, 0
|
||||
ja .power_loop
|
||||
.after_power_loop:
|
||||
mov bx,ax
|
||||
pop ax
|
||||
pop cx
|
||||
; ax = ax DIV bx
|
||||
; dx = ax MOD bx
|
||||
xor dx,dx
|
||||
div bx
|
||||
pop bx
|
||||
add ax, 30h
|
||||
stosb
|
||||
mov ax, dx
|
||||
dec cx
|
||||
cmp cx, 0
|
||||
ja .stringify_loop
|
||||
.finish:
|
||||
popa
|
||||
;mov ax, stringified_int
|
||||
ret
|
||||
|
||||
; Get the length of a string
|
||||
; 'hello world', 0 is 11 characters long (excluding the terminator)
|
||||
; input: si points to the string to be counted
|
||||
; output: cl holds the length
|
||||
os_string_length:
|
||||
string_length:
|
||||
push si
|
||||
xor cl,cl ; Clear the al register
|
||||
.loop:
|
||||
@@ -52,6 +193,8 @@ os_string_length:
|
||||
pop si
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; convert a string to fat's filename format
|
||||
; It will be capitalised and 11 characters long,
|
||||
; 8 for the filename, 3 for the extension
|
||||
@@ -60,8 +203,8 @@ os_string_length:
|
||||
; output: di points to the fat formatted filename
|
||||
os_format_fat_filename:
|
||||
pusha
|
||||
call os_upper_case
|
||||
call os_string_length ; Stores the length of the string in cl
|
||||
call string_upper_case
|
||||
call string_length ; Stores the length of the string in cl
|
||||
xor ch,ch ; Clear ch to reset it to 0
|
||||
.character_loop:
|
||||
lodsb
|
||||
@@ -147,7 +290,7 @@ string_unformat_fat_filename:
|
||||
; Convert a string to all upper/lower case
|
||||
; INPUT: si pointing to a string
|
||||
; OUPUT: the same string in memory will now be capitalised/decapitalised
|
||||
os_upper_case: ; to upper case
|
||||
string_upper_case: ; to upper case
|
||||
pusha
|
||||
mov di, si
|
||||
.loop:
|
||||
@@ -187,3 +330,9 @@ os_lower_case: ; to lower case
|
||||
popa
|
||||
ret
|
||||
|
||||
string_lower_case:
|
||||
ret
|
||||
string_input:
|
||||
ret
|
||||
string_print_2hex:
|
||||
ret
|
||||
|
||||
@@ -17,12 +17,30 @@ util_cat:
|
||||
util_ls:
|
||||
pusha
|
||||
|
||||
call disk_clear_output_buffer
|
||||
call disk_load_root
|
||||
call disk_list_contents
|
||||
|
||||
mov si, output_buffer
|
||||
call os_print_string
|
||||
call disk_clear_output_buffer
|
||||
|
||||
popa
|
||||
ret
|
||||
|
||||
util_basic:
|
||||
pusha
|
||||
|
||||
call disk_load_root
|
||||
|
||||
; TODO make this more consistent to account for double spaces
|
||||
;add si, 3 ; Move si to after 'BAS'
|
||||
call disk_load_file
|
||||
|
||||
mov si, file_buffer
|
||||
|
||||
mov ax, si
|
||||
mov si, 0
|
||||
call basic_run_basic
|
||||
|
||||
popa
|
||||
ret
|
||||
|
||||
@@ -10,8 +10,12 @@ start:
|
||||
|
||||
mov si, boot_message
|
||||
call os_print_string
|
||||
mov si, help_text
|
||||
call os_print_string
|
||||
|
||||
; TESTING
|
||||
;mov ax, 3
|
||||
;call string_cast_from_int
|
||||
;mov si, stringified_int
|
||||
;call os_print_string
|
||||
|
||||
call os_start_cli
|
||||
hlt
|
||||
@@ -24,16 +28,18 @@ halt:
|
||||
; FEATURES -- Code to pull into the kernel
|
||||
%INCLUDE "source/kernel/features/text.asm"
|
||||
%INCLUDE "source/kernel/features/keyboard.asm"
|
||||
%INCLUDE "source/kernel/features/cli.asm"
|
||||
%INCLUDE "source/kernel/features/ports.asm"
|
||||
%INCLUDE "source/kernel/features/power.asm"
|
||||
%INCLUDE "source/kernel/features/strings.asm"
|
||||
%INCLUDE "source/kernel/features/graphics.asm"
|
||||
%INCLUDE "source/kernel/features/sound.asm"
|
||||
%INCLUDE "source/kernel/features/disk.asm"
|
||||
%INCLUDE "source/kernel/features/math.asm"
|
||||
%INCLUDE "source/kernel/features/time.asm"
|
||||
%INCLUDE "source/kernel/features/utils.asm"
|
||||
; GAMES -- Games that I wrote for it
|
||||
%INCLUDE "source/kernel/games/pong.asm"
|
||||
%INCLUDE "source/kernel/features/cli.asm"
|
||||
%INCLUDE "source/kernel/features/misc.asm"
|
||||
%INCLUDE "source/kernel/features/basic.asm"
|
||||
|
||||
; DATA/VARIABLES
|
||||
%INCLUDE "source/kernel/data.asm"
|
||||
|
||||
0
source/kernel/programs/ed.asm
Normal file
0
source/kernel/programs/ed.asm
Normal file
@@ -5,5 +5,7 @@ sudo chown $(whoami) disk_images/*
|
||||
qemu-system-i386\
|
||||
-drive file=disk_images/crawos.img,if=floppy,format=raw\
|
||||
-m 512m\
|
||||
-object memory-backend-file,id=pc.ram,size=512m,mem-path=/dev/shm/qemu-ram,share=on -machine memory-backend=pc.ram\
|
||||
$1 $2
|
||||
-object memory-backend-file,id=pc.ram,size=512m,mem-path=/dev/shm/qemu-ram,share=on\
|
||||
-machine memory-backend=pc.ram\
|
||||
-d in_asm,int -D ./detailed.log\
|
||||
$1 $2
|
||||
|
||||
0
to_implement
Normal file
0
to_implement
Normal file
Reference in New Issue
Block a user