BASIC Interpreter from MikeOS is functioning

This commit is contained in:
2026-01-20 18:38:51 +00:00
parent e0809f84dc
commit 0f6f8f33f6
22 changed files with 4677 additions and 96 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
*.swp *.swp
disk_images/* disk_images/*
tmp-loop/* tmp-loop/*
detailed.log

View File

@@ -1,2 +1,3 @@
Kernel written in Assmebly<br/> Kernel written in Assmebly<br/>
I'm using a modified JazzOS Bootloader<br/> I'm using a modified JazzOS Bootloader<br/>
And the MikeOS BASIC Interpreter<br/>

2
data/hello.bas Normal file
View File

@@ -0,0 +1,2 @@
PRINT "Hello World!"
END

View File

@@ -1 +0,0 @@
output 'Hello World'

0
log.txt Normal file
View File

View File

@@ -10,7 +10,7 @@ bdb_bytes_per_sector: dw 200h ; = 512d
bdb_sectors_per_cluster: db 01h ; sector = cluster bdb_sectors_per_cluster: db 01h ; sector = cluster
bdb_reserved_sectors: dw 01h bdb_reserved_sectors: dw 01h
bdb_fat_count: db 02h ; We've got a fat1 and fat2 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_total_sectors: dw 0B40h ; = 2880d
bdb_media_descriptor_type: db 0F0h ; ignore bdb_media_descriptor_type: db 0F0h ; ignore
bdb_sectors_per_fat: dw 09h bdb_sectors_per_fat: dw 09h
@@ -68,7 +68,7 @@ main:
shl ax,5 ; ax *= 32 (shifting 5 times) shl ax,5 ; ax *= 32 (shifting 5 times)
xor dx,dx ; Clear dx (remainder) 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 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 jz root_dir_after
inc ax ; Add one if there's a remainder (this is like rounding up) inc ax ; Add one if there's a remainder (this is like rounding up)

View File

@@ -22,20 +22,23 @@ ebr_volume_label: db 'CRAWOS0.0.6' ; must be 11 bytes
ebr_system_id: db 'FAT12 ' ; must be 8 bytes ebr_system_id: db 'FAT12 ' ; must be 8 bytes
; String operations
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\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: db 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
reboot_string: db 'REBOOT', 0 reboot_string: db 'REBOOT', 0
pong_string: db 'PONG', 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"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 command_result_text: db 'You typed: ', 0
unknown_command: db 'Error: Unkown Command..\n ', 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 operations
disk_read_fail: db 'Error: Could not read disk\n', 0 disk_read_fail: db 'Error: Could not read disk\n', 0

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@ os_start_cli:
os_read_cli: os_read_cli:
pusha pusha
mov si, user_input 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: .output_the_user_input:
call os_print_newline call os_print_newline
@@ -45,6 +45,13 @@ os_read_cli:
cmp cl, 1 cmp cl, 1
je power_reboot je power_reboot
; Basic
mov si, user_input
mov di, basic_string
call os_compare_strings
cmp cl, 1
je basic
; Cat ; Cat
mov si, user_input mov si, user_input
mov di, cat_string mov di, cat_string
@@ -59,13 +66,6 @@ os_read_cli:
cmp cl, 1 cmp cl, 1
je ls je ls
; Pong
mov si, user_input
mov di, pong_string
call os_compare_strings
cmp cl, 1
je pong
jmp .unkown jmp .unkown
.unkown: .unkown:
@@ -88,10 +88,9 @@ help:
call os_print_string call os_print_string
call os_read_cli.finish call os_read_cli.finish
pong: basic:
call game_pong 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

View File

@@ -173,7 +173,7 @@ disk_clear_output_buffer:
; TODO use predefined data for calculations ; TODO use predefined data for calculations
disk_load_file: disk_load_file:
pusha pusha
call os_string_length ; cl = string length call string_length ; cl = string length
cmp cl, 11 cmp cl, 11
ja .filename_too_long ja .filename_too_long
@@ -244,7 +244,7 @@ disk_load_file:
disk_write_file: disk_write_file:
pusha pusha
; Check if file name is too long ; Check if file name is too long
call os_string_length ; cl = string length call string_length ; cl = string length
cmp cl, 11 cmp cl, 11
ja .filename_too_long ja .filename_too_long
; Convert file name to a fat filename ; Convert file name to a fat filename
@@ -302,6 +302,7 @@ disk_write_file:
ret ret
; TODO support long file names ; TODO support long file names
; TODO don't work twice
; Store a list of the files in file_buffer ; Store a list of the files in file_buffer
; in a human readable format ; in a human readable format
; OUT ; OUT
@@ -374,3 +375,14 @@ disk_list_contents:
stosb stosb
popa popa
ret ret
disk_file_exists:
ret
disk_file_size:
ret
disk_file_list:
ret
disk_remove_file:
ret
disk_rename_file:
ret

View File

@@ -51,3 +51,10 @@ section .data
y_end dw 0 y_end dw 0
colour db 1111b colour db 1111b
graphics_dialogue_box:
ret
graphics_file_selector:
ret
graphics_list_dialogue:
ret

View File

@@ -7,10 +7,10 @@ os_read_input:
hlt hlt
jmp os_read_input jmp os_read_input
.key_pressed: .key_pressed:
mov ah, 10h mov ah, 10h
int 16h int 16h
ret ret
; ------------------------------------------- ; -------------------------------------------
@@ -18,60 +18,73 @@ os_display_input:
pusha pusha
mov cx, [prompt_length] mov cx, [prompt_length]
.loop: .loop:
call .check_key_pressed call .check_key_pressed
jmp .loop jmp .loop
.check_key_pressed: .check_key_pressed:
call os_read_input call os_read_input
cmp al, 08h cmp al, 08h
je .backspace je .backspace
cmp al, 0Dh cmp al, 0Dh
je .enter_key je .enter_key
cmp al, 1Bh cmp al, 1Bh
je .esc_key je .esc_key
cmp cx, 0 cmp cx, 0
jb .check_key_pressed jb .check_key_pressed
call .print_current_input call .print_current_input
dec cx dec cx
jmp .check_key_pressed jmp .check_key_pressed
.esc_key: .esc_key:
call power_reboot call power_reboot
.enter_key: .enter_key:
mov al, 0 mov al, 0
stosb stosb
popa popa
call os_read_cli call os_read_cli
.backspace: .backspace:
call .move_cursor_back ; then .move_cursor_back call .move_cursor_back ; then .move_cursor_back
call .loop ; Else .loop call .loop ; Else .loop
.move_cursor_back: .move_cursor_back:
mov ah, 0Eh mov ah, 0Eh
mov al, 08h mov al, 08h
int 10h int 10h
mov al, 20h mov al, 20h
int 10h int 10h
mov al, 08h mov al, 08h
int 10h int 10h
dec di dec di
jmp os_display_input jmp os_display_input
.print_current_input: .print_current_input:
stosb stosb
mov ah, 0Eh mov ah, 0Eh
int 10h 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 ret

View File

@@ -52,3 +52,5 @@ math_lba_to_chs:
pop ax pop ax
ret ret
math_get_random:
ret

View File

@@ -0,0 +1,4 @@
misc_pause:
ret
misc_get_api_version:
ret

View 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

View File

@@ -0,0 +1,4 @@
sound_speaker_tone:
ret
sound_speaker_off:
ret

View File

@@ -11,35 +11,176 @@
os_compare_strings: os_compare_strings:
cld cld
.compare: .compare:
mov al, 0 mov al, 0
scasb scasb
je .di_ended je .di_ended
dec di dec di
lodsb lodsb
scasb ; Compare di to si scasb ; Compare di to si
jne .unequal ; If they are not equal, jump to .unequal jne .unequal ; If they are not equal, jump to .unequal
jmp .compare ; Finally, repeat jmp .compare ; Finally, repeat
.unequal: .unequal:
mov cl, 0 ; Change to 0 if unquality is proven mov cl, 0 ; Change to 0 if unquality is proven
ret ret
.di_ended: .di_ended:
lodsb lodsb
cmp al, 20h ; 20h = space cmp al, 20h ; 20h = space
je .equal je .equal
cmp al, 0 cmp al, 0
je .equal je .equal
jmp .unequal jmp .unequal
.equal: .equal:
mov cl, 1 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 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 ; Get the length of a string
; 'hello world', 0 is 11 characters long (excluding the terminator) ; 'hello world', 0 is 11 characters long (excluding the terminator)
; input: si points to the string to be counted ; input: si points to the string to be counted
; output: cl holds the length ; output: cl holds the length
os_string_length: string_length:
push si push si
xor cl,cl ; Clear the al register xor cl,cl ; Clear the al register
.loop: .loop:
@@ -52,6 +193,8 @@ os_string_length:
pop si pop si
ret ret
; convert a string to fat's filename format ; convert a string to fat's filename format
; It will be capitalised and 11 characters long, ; It will be capitalised and 11 characters long,
; 8 for the filename, 3 for the extension ; 8 for the filename, 3 for the extension
@@ -60,8 +203,8 @@ os_string_length:
; output: di points to the fat formatted filename ; output: di points to the fat formatted filename
os_format_fat_filename: os_format_fat_filename:
pusha pusha
call os_upper_case call string_upper_case
call os_string_length ; Stores the length of the string in cl call string_length ; Stores the length of the string in cl
xor ch,ch ; Clear ch to reset it to 0 xor ch,ch ; Clear ch to reset it to 0
.character_loop: .character_loop:
lodsb lodsb
@@ -147,7 +290,7 @@ string_unformat_fat_filename:
; Convert a string to all upper/lower case ; Convert a string to all upper/lower case
; INPUT: si pointing to a string ; INPUT: si pointing to a string
; OUPUT: the same string in memory will now be capitalised/decapitalised ; OUPUT: the same string in memory will now be capitalised/decapitalised
os_upper_case: ; to upper case string_upper_case: ; to upper case
pusha pusha
mov di, si mov di, si
.loop: .loop:
@@ -187,3 +330,9 @@ os_lower_case: ; to lower case
popa popa
ret ret
string_lower_case:
ret
string_input:
ret
string_print_2hex:
ret

View File

@@ -17,12 +17,30 @@ util_cat:
util_ls: util_ls:
pusha pusha
call disk_clear_output_buffer call disk_load_root
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
popa popa
ret 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

View File

@@ -10,8 +10,12 @@ start:
mov si, boot_message mov si, boot_message
call os_print_string 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 call os_start_cli
hlt hlt
@@ -24,16 +28,18 @@ halt:
; FEATURES -- Code to pull into the kernel ; FEATURES -- Code to pull into the kernel
%INCLUDE "source/kernel/features/text.asm" %INCLUDE "source/kernel/features/text.asm"
%INCLUDE "source/kernel/features/keyboard.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/power.asm"
%INCLUDE "source/kernel/features/strings.asm" %INCLUDE "source/kernel/features/strings.asm"
%INCLUDE "source/kernel/features/graphics.asm" %INCLUDE "source/kernel/features/graphics.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/time.asm" %INCLUDE "source/kernel/features/time.asm"
%INCLUDE "source/kernel/features/utils.asm" %INCLUDE "source/kernel/features/utils.asm"
; GAMES -- Games that I wrote for it %INCLUDE "source/kernel/features/cli.asm"
%INCLUDE "source/kernel/games/pong.asm" %INCLUDE "source/kernel/features/misc.asm"
%INCLUDE "source/kernel/features/basic.asm"
; DATA/VARIABLES ; DATA/VARIABLES
%INCLUDE "source/kernel/data.asm" %INCLUDE "source/kernel/data.asm"

View File

View File

@@ -5,5 +5,7 @@ sudo chown $(whoami) disk_images/*
qemu-system-i386\ qemu-system-i386\
-drive file=disk_images/crawos.img,if=floppy,format=raw\ -drive file=disk_images/crawos.img,if=floppy,format=raw\
-m 512m\ -m 512m\
-object memory-backend-file,id=pc.ram,size=512m,mem-path=/dev/shm/qemu-ram,share=on -machine memory-backend=pc.ram\ -object memory-backend-file,id=pc.ram,size=512m,mem-path=/dev/shm/qemu-ram,share=on\
$1 $2 -machine memory-backend=pc.ram\
-d in_asm,int -D ./detailed.log\
$1 $2

0
to_implement Normal file
View File