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

View File

@@ -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