BASIC interpreter
This commit is contained in:
0
.gitignore
vendored
Executable file → Normal file
0
.gitignore
vendored
Executable file → Normal file
0
build-linux.sh
Executable file → Normal file
0
build-linux.sh
Executable file → Normal file
0
data/README.md
Executable file → Normal file
0
data/README.md
Executable file → Normal file
@@ -1,2 +1,4 @@
|
||||
PRINT "Hello World!"
|
||||
FOR A = 1 TO 10
|
||||
PRINT A
|
||||
NEXT A
|
||||
END
|
||||
|
||||
@@ -40,6 +40,7 @@ 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
|
||||
|
||||
int_tmp: dw 0
|
||||
; Disk operations
|
||||
disk_read_fail: db 'Error: Could not read disk\n', 0
|
||||
file_not_found: db 'File not found\n', 0
|
||||
@@ -59,3 +60,4 @@ read_write_flag: db 02
|
||||
empty_byte: db 0
|
||||
empty_word: dw 0
|
||||
empty_dword: dd 0
|
||||
tmp: db '97', 0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2
source/kernel/features/cli.asm
Executable file → Normal file
2
source/kernel/features/cli.asm
Executable file → Normal file
@@ -17,7 +17,7 @@ os_start_cli:
|
||||
|
||||
os_read_cli:
|
||||
pusha
|
||||
mov si, user_input
|
||||
mov ax, user_input
|
||||
call string_upper_case ; Make the input uppercase so it's case insensitive
|
||||
|
||||
.output_the_user_input:
|
||||
|
||||
@@ -308,6 +308,7 @@ disk_write_file:
|
||||
; OUT
|
||||
; output_buffer: the list (string)
|
||||
disk_list_contents:
|
||||
call disk_load_root
|
||||
pusha
|
||||
mov si, root_buffer
|
||||
mov di, output_buffer
|
||||
@@ -322,38 +323,22 @@ disk_list_contents:
|
||||
dec cx
|
||||
cmp cx, 0
|
||||
jne .space_loop
|
||||
|
||||
.file_attribute:
|
||||
add si, 11d
|
||||
mov ax, [si+28d]
|
||||
call string_cast_from_int
|
||||
push si
|
||||
mov si, stringified_int
|
||||
lodsb
|
||||
.output_file_size_loop:
|
||||
stosb
|
||||
lodsb
|
||||
push si
|
||||
|
||||
mov si, read_only
|
||||
cmp al, 1h
|
||||
je .add_string
|
||||
mov si, hidden
|
||||
cmp al, 2h
|
||||
je .add_string
|
||||
mov si, system
|
||||
cmp al, 4h
|
||||
je .add_string
|
||||
mov si, volume
|
||||
cmp al, 8h
|
||||
je .add_string
|
||||
mov si, directory
|
||||
cmp al, 10h
|
||||
je .add_string
|
||||
mov si, archive
|
||||
cmp al, 20h
|
||||
je .add_string
|
||||
|
||||
.after_file_attributes:
|
||||
cmp al, 0
|
||||
jne .output_file_size_loop
|
||||
.after_fs_loop:
|
||||
pop si
|
||||
|
||||
mov al, 0Ah
|
||||
stosb
|
||||
|
||||
add si, 20d
|
||||
add si, 20h
|
||||
lodsb ; +1
|
||||
dec si ; -1
|
||||
cmp al, 0 ; You've come to the end of the root entries
|
||||
@@ -361,13 +346,6 @@ disk_list_contents:
|
||||
cmp al, 00E5h ; E5h is a marker that the Fat entry is available
|
||||
je .finish
|
||||
jmp .loop
|
||||
.add_string:
|
||||
.add_string_loop:
|
||||
lodsb
|
||||
cmp ax, 00h
|
||||
je .after_file_attributes
|
||||
stosb
|
||||
jmp .add_string_loop
|
||||
.finish:
|
||||
mov cx, output_buffer
|
||||
sub di, cx
|
||||
|
||||
0
source/kernel/features/power.asm
Executable file → Normal file
0
source/kernel/features/power.asm
Executable file → Normal file
259
source/kernel/features/strings.asm
Executable file → Normal file
259
source/kernel/features/strings.asm
Executable file → Normal file
@@ -1,11 +1,11 @@
|
||||
; How string comparison works
|
||||
; DI => scasb compares value stored in DI which is 's' with 's' stored in AX register
|
||||
; and then increments DI if DF is 0
|
||||
; v
|
||||
; memory address 1: |s|n|a|t|0|
|
||||
; memory address 2: |s|n|a|k|e|0|
|
||||
; ^
|
||||
; SI => lodsb loads value stored at SI to AX and then increments SI if DF is 0
|
||||
; DI => scasb compares value stored in DI which is 's' with 's' stored in AX register
|
||||
; and then increments DI if DF is 0
|
||||
; v
|
||||
; memory address 1: |s|n|a|t|0|
|
||||
; memory address 2: |s|n|a|k|e|0|
|
||||
; ^
|
||||
; SI => lodsb loads value stored at SI to AX and then increments SI if DF is 0
|
||||
; Additionaly, if the di string ends and the relevant character in si contains a space, it will still return
|
||||
; the strings as being equal, this is to allow for command line arquments
|
||||
os_compare_strings:
|
||||
@@ -44,22 +44,22 @@ os_compare_strings:
|
||||
string_direct_compare:
|
||||
pusha
|
||||
.more:
|
||||
mov al, [si] ; Retrieve string contents
|
||||
mov al, [si] ; Retrieve string contents
|
||||
mov bl, [di]
|
||||
cmp al, bl ; Compare characters at current location
|
||||
cmp al, bl ; Compare characters at current location
|
||||
jne .not_same
|
||||
cmp al, 0 ; End of first string? Must also be end of second
|
||||
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
|
||||
.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
|
||||
.end: ; Both strings terminated at the same position
|
||||
popa
|
||||
stc ; Set carry flag
|
||||
stc ; Set carry flag
|
||||
ret
|
||||
|
||||
|
||||
@@ -73,8 +73,8 @@ 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
|
||||
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:
|
||||
@@ -107,89 +107,84 @@ string_join:
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; TODO
|
||||
; Converts a null terminated string to an integer
|
||||
; IN: SI = string location (max 5 chars, up to '65536')
|
||||
; OUT: AX = number
|
||||
string_cast_to_int:
|
||||
ret
|
||||
pusha
|
||||
xor cx,cx
|
||||
.loop:
|
||||
xor ax,ax
|
||||
lodsb
|
||||
cmp al, 0
|
||||
je .finish
|
||||
sub al, 30h
|
||||
mov bx, ax
|
||||
mov ax, 10
|
||||
mul cx ; Multiple the current value by 10
|
||||
add ax, bx ; Then add the new digit
|
||||
mov cx, ax
|
||||
jmp .loop
|
||||
.finish:
|
||||
mov [int_tmp], cx
|
||||
popa
|
||||
mov ax, [int_tmp]
|
||||
ret
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; IN: AX = integer (unsigned)
|
||||
; OUT: AX -> null-terminated string
|
||||
|
||||
; IN: AX = int
|
||||
; OUT: AX = string location (output buffer)
|
||||
string_cast_from_int: ; TODO I think this algorithm could be optimised
|
||||
string_cast_from_int:
|
||||
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
|
||||
cld ; Write backwards
|
||||
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
|
||||
|
||||
mov bx, 10 ; base
|
||||
mov cx, 0 ; digit count
|
||||
|
||||
.convert_loop:
|
||||
xor dx, dx
|
||||
div bx ; AX = AX / base, DX = remainder
|
||||
add dl, '0'
|
||||
push dx ; store digit
|
||||
inc cx
|
||||
test ax, ax
|
||||
jnz .convert_loop
|
||||
|
||||
.write_loop:
|
||||
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:
|
||||
loop .write_loop
|
||||
|
||||
mov al, 0
|
||||
stosb ; null terminator
|
||||
|
||||
popa
|
||||
;mov ax, stringified_int
|
||||
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
|
||||
; input: ax points to the string to be counted
|
||||
; output: ax holds the length
|
||||
string_length:
|
||||
push si
|
||||
xor cl,cl ; Clear the al register
|
||||
push cx
|
||||
mov si, ax
|
||||
xor ax,ax ; Clear the cx register
|
||||
xor cx,cx
|
||||
.loop:
|
||||
lodsb
|
||||
cmp al, 0
|
||||
je .finish
|
||||
inc cl
|
||||
inc cx
|
||||
jmp .loop
|
||||
.finish:
|
||||
mov ax, cx
|
||||
pop cx
|
||||
pop si
|
||||
ret
|
||||
|
||||
@@ -198,15 +193,17 @@ string_length:
|
||||
; convert a string to fat's filename format
|
||||
; It will be capitalised and 11 characters long,
|
||||
; 8 for the filename, 3 for the extension
|
||||
; eg: 'file.txt' -> 'FILE TXT'
|
||||
; eg: 'file.txt' -> 'FILE TXT'
|
||||
; input: si points to filename, di points to a free 11 bytes in memory
|
||||
; output: di points to the fat formatted filename
|
||||
os_format_fat_filename:
|
||||
pusha
|
||||
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:
|
||||
pusha
|
||||
call string_upper_case
|
||||
mov ax, si
|
||||
call string_length ; Stores the length of the string in cl
|
||||
mov cl, al
|
||||
xor ch,ch ; Clear ch to reset it to 0
|
||||
.character_loop:
|
||||
lodsb
|
||||
cmp al, 0
|
||||
je .finish
|
||||
@@ -215,10 +212,10 @@ os_format_fat_filename:
|
||||
stosb
|
||||
inc ch
|
||||
jmp .character_loop
|
||||
|
||||
.add_spaces: ; Add the number of spaces as bl holds
|
||||
|
||||
.add_spaces: ; Add the number of spaces as bl holds
|
||||
mov al, ' ' ; 20h = space
|
||||
|
||||
|
||||
; Work out the number of spaces in between
|
||||
; the name and extension.
|
||||
; 8 - name_length(ch)
|
||||
@@ -231,9 +228,9 @@ os_format_fat_filename:
|
||||
je .character_loop
|
||||
dec bl
|
||||
jmp .spaces_loop
|
||||
.finish:
|
||||
popa
|
||||
ret
|
||||
.finish:
|
||||
popa
|
||||
ret
|
||||
|
||||
; Does the inverse of the previous
|
||||
; Converts a fat filename back to human readable
|
||||
@@ -287,51 +284,53 @@ string_unformat_fat_filename:
|
||||
popa
|
||||
ret
|
||||
|
||||
; -------------------------------------------------------------------------------------
|
||||
|
||||
; Convert a string to all upper/lower case
|
||||
; INPUT: si pointing to a string
|
||||
; INPUT: ax pointing to a string
|
||||
; OUPUT: the same string in memory will now be capitalised/decapitalised
|
||||
string_upper_case: ; to upper case
|
||||
pusha
|
||||
mov di, si
|
||||
pusha
|
||||
mov si,ax
|
||||
mov di,si
|
||||
.loop:
|
||||
lodsb ; Load the character into al
|
||||
inc di
|
||||
cmp al, 0
|
||||
je .finish ; If it's null then the string is finished
|
||||
cmp al, 7Ah ; 7Ah = 'z'
|
||||
jns .loop ; Ignore if it's more than 'z'
|
||||
cmp al, 61h ; 61h = 'a'
|
||||
js .loop ; Ignore if it's less than 'a'
|
||||
sub al, 20h ; Otherwise subtract 20h to capitalise it
|
||||
dec di
|
||||
stosb ; Store the new value
|
||||
jmp .loop ; Next character
|
||||
lodsb ; Load the character into al
|
||||
inc di
|
||||
cmp al, 0
|
||||
je .finish ; If it's null then the string is finished
|
||||
cmp al, 7Ah ; 7Ah = 'z'
|
||||
jns .loop ; Ignore if it's more than 'z'
|
||||
cmp al, 61h ; 61h = 'a'
|
||||
js .loop ; Ignore if it's less than 'a'
|
||||
sub al, 20h ; Otherwise subtract 20h to capitalise it
|
||||
dec di
|
||||
stosb ; Store the new value
|
||||
jmp .loop ; Next character
|
||||
.finish:
|
||||
popa
|
||||
ret
|
||||
|
||||
os_lower_case: ; to lower case
|
||||
pusha
|
||||
mov di, si
|
||||
.loop:
|
||||
lodsb ; Load the character into al
|
||||
inc di
|
||||
cmp al, 0
|
||||
je .finish ; If it's null then the string is finished
|
||||
cmp al, 5Ah ; 5Ah = 'Z'
|
||||
jns .loop ; Ignore if it's more than 'Z'
|
||||
cmp al, 41h ; 41h = 'A'
|
||||
js .loop ; Ignore if it's less than 'A'
|
||||
add al, 20h ; Otherwise subtract 20h to capitalise it
|
||||
dec di
|
||||
stosb ; Store the new value
|
||||
jmp .loop ; Next character
|
||||
.finish:
|
||||
popa
|
||||
ret
|
||||
|
||||
string_lower_case:
|
||||
popa
|
||||
ret
|
||||
|
||||
string_lower_case: ; to lower case
|
||||
pusha
|
||||
mov si, ax
|
||||
mov di, si
|
||||
.loop:
|
||||
lodsb ; Load the character into al
|
||||
inc di
|
||||
cmp al, 0
|
||||
je .finish ; If it's null then the string is finished
|
||||
cmp al, 5Ah ; 5Ah = 'Z'
|
||||
jns .loop ; Ignore if it's more than 'Z'
|
||||
cmp al, 41h ; 41h = 'A'
|
||||
js .loop ; Ignore if it's less than 'A'
|
||||
add al, 20h ; Otherwise subtract 20h to capitalise it
|
||||
dec di
|
||||
stosb ; Store the new value
|
||||
jmp .loop ; Next character
|
||||
.finish:
|
||||
popa
|
||||
ret
|
||||
|
||||
string_input:
|
||||
ret
|
||||
string_print_2hex:
|
||||
|
||||
0
source/kernel/features/text.asm
Executable file → Normal file
0
source/kernel/features/text.asm
Executable file → Normal file
@@ -17,7 +17,6 @@ util_cat:
|
||||
util_ls:
|
||||
pusha
|
||||
|
||||
call disk_load_root
|
||||
call disk_list_contents
|
||||
|
||||
mov si, output_buffer
|
||||
|
||||
@@ -10,12 +10,10 @@ start:
|
||||
|
||||
mov si, boot_message
|
||||
call os_print_string
|
||||
|
||||
; TESTING
|
||||
;mov ax, 3
|
||||
;call string_cast_from_int
|
||||
;mov si, stringified_int
|
||||
;call os_print_string
|
||||
|
||||
mov si, tmp
|
||||
mov ah, 0Eh
|
||||
int 10h
|
||||
|
||||
call os_start_cli
|
||||
hlt
|
||||
|
||||
@@ -4,8 +4,8 @@ sudo make
|
||||
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\
|
||||
-m 8m\
|
||||
-object memory-backend-file,id=pc.ram,size=8m,mem-path=/dev/shm/qemu-ram,share=on\
|
||||
-machine memory-backend=pc.ram\
|
||||
-d in_asm,int -D ./detailed.log\
|
||||
$1 $2
|
||||
|
||||
Reference in New Issue
Block a user