idk what i added

This commit is contained in:
2025-12-30 22:52:30 +00:00
parent 0222a7adb9
commit e0809f84dc
10 changed files with 491 additions and 112 deletions

58
source/kernel/data.asm Normal file
View File

@@ -0,0 +1,58 @@
; Define Fat12 header
bdb_oem: db 'MSWIN4.1' ; ignore
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_total_sectors: dw 0B40h ; = 2880d
bdb_media_descriptor_type: db 0F0h ; ignore
bdb_sectors_per_fat: dw 09h
bdb_sectors_per_track: dw 12h ; = 18d
bdb_number_of_heads: dw 02h ; top and bottom of the floppy disk
bdb_hidden_sectors: dd 0 ; ignore
bdb_large_sector_count: dd 0 ; total sector count for fat32 (0 for fat12 or fat16)
; extended boot record
ebr_drive_number: db 0 ; ignore
db 0 ; ignore
ebr_signature: db 29h ; boot signature, indicates that the next three fields are present (0x29)
ebr_volume_id: db 12h, 34h, 56h, 78h ; unique id for volume tracking
ebr_volume_label: db 'CRAWOS0.0.6' ; must be 11 bytes
ebr_system_id: db 'FAT12 ' ; must be 8 bytes
fat12_file_name: db ' ' ; 11 free bytes to store a filename in
boot_message: db 'OK] Kernel successfully loaded!\n\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
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
command_result_text: db 'You typed: ', 0
unknown_command: db 'Error: Unkown Command..\n ', 0
; Disk operations
disk_read_fail: db 'Error: Could not read disk\n', 0
file_not_found: db 'File not found\n', 0
too_long_filename: db 'Filename too long for Fat12\n', 0
file_found: db 'File found\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_cluster: dw 0
file_length: dd 0
read_write_flag: db 02
empty_byte: db 0
empty_word: dw 0
empty_dword: dd 0

View File

@@ -44,6 +44,20 @@ os_read_cli:
call os_compare_strings
cmp cl, 1
je power_reboot
; Cat
mov si, user_input
mov di, cat_string
call os_compare_strings
cmp cl, 1
je cat
; LS
mov si, user_input
mov di, ls_string
call os_compare_strings
cmp cl, 1
je ls
; Pong
mov si, user_input
@@ -78,16 +92,9 @@ pong:
call game_pong
call os_read_cli.finish
section .data
welcome_text db 'Welcome to CrawOS, the Cwick, Real and AWsome Operating System\n', 0
user_input times 20 db 0
prompt_length db 20
prompt db 'CrawOS sh> ', 0
help_string db 'HELP', 0
clear_string db 'CLEAR', 0
reboot_string db 'REBOOT', 0
cat_string db 'CAT', 0
pong_string db 'PONG', 0
help_text db 'This is for Cowards:\n"HELP" for this helpful text,\n"CLEAR" to clear the screen,\n"REBOOT" or esc to reboot\n', 0
command_result_text db 'You typed: ', 0
unknown_command db 'Error: Unkown Command.. \n', 0
cat:
call util_cat
call os_read_cli.finish
ls:
call util_ls
call os_read_cli.finish

View File

@@ -14,7 +14,7 @@ disk_load_root:
pusha
mov ax, 19 ; First sector of root entry
call math_lba_to_chs ; Assigns ch, cl and dh the correct values
xor ax,ax
xor ax,ax ; clear ax so I can use it on next line
mov dl, [ebr_drive_number] ; Drive number
mov ah, 02h ; BIOS ah code for read disk sectors to memory
mov al, 0Ch ; Root directory has 12 sectors
@@ -53,28 +53,34 @@ disk_load_root:
; ---------------------------------------------
; Reads a certain number of sectors into memory
; int 13h/ah = 02h read disk sectors into memory
; IN
; ax = LBA
; es:bx = area to read to/write from
; [read_write_flag] = 02 or 03 for read or write
; dl = ebr drive number
; int 13h/ah = 02h/03h read/write disk sectors into memory
; al = number of sectors to read
; ah = read/write 02=read, 03=write IMPORTANT
; ch = cylinder number
; cl = sector number
; dh = head number
; dl = drive number
; es:bx = points to data buffer
disk_read:
disk_read_or_write:
push ax
push bx
push cx
push dx
push di
; cl = sector
; ch = cylinder
; dh = head
; dl = drive
call math_lba_to_chs ; Get the chs address
mov ah, 02h ; BIOS ah code for read disk sectors to memory
mov ah, [read_write_flag]
mov al, 1
; repeat drive read 3 times (incase of random error)
mov di, 3 ; counter
@@ -122,10 +128,55 @@ disk_read:
pop ax
ret
; -------------------------------------
; -------------------------------------
; CLEAR DATA
; Uses the metadata buffer to determine the file size in the data buffer and clears it.
disk_clear_file_buffer:
pusha
mov si, metadata_buffer
mov cx, [si+28] ; MOve the filelength into the ax
shr cx, 1 ; Divide by 4 because we'll write over using double words
mov si, empty_word
lodsb ; Load the empty dword
mov di, file_buffer
.loop:
stosb
dec cx
cmp cx, 0
jbe .loop
.finish:
popa
ret
disk_clear_output_buffer:
pusha
mov cx, 0x7f0 ; Length of the output buffer
mov si, empty_word
lodsb ; Load the empty word into ax
mov di, output_buffer
.loop:
stosb ; Store empty dword in di
dec cx
cmp cx, 0
ja .loop
.finish:
popa
ret
; -------------------------------------
; IN
; si: filename
; OUT
; data_buffer: file contents
; TODO use predefined data for calculations
disk_load_file:
pusha
call os_string_length ; cl = string length
cmp cl, 11
ja .filename_too_long
mov di, fat12_file_name
call os_format_fat_filename
@@ -134,7 +185,7 @@ disk_load_file:
xor bx,bx
.search_root:
mov di, fat12_file_name ; Move the name of the kernel into di
mov cx, 11 ; length of 'KERNEL BIN'
mov cx, 11 ; length of filenames in fat12
push si ; Preserve si
repe cmpsb ; Repeat a comparison of bytes between file name and current bytes until it finds a match
pop si ; Retrieve si
@@ -147,29 +198,179 @@ disk_load_file:
jmp .file_not_found ; If the last dir has been searched, then there is no kernel
.found_file:
call disk_clear_file_buffer
mov di, metadata_buffer
mov cx, 32
.write_metadata:
; Write data to metadata buffer
lodsb
stosb
sub cx, 1
cmp cx, 0
jne .write_metadata
.read_kernel:
sub si, 32
mov ax, [si+28] ; File length
mov [file_length], ax
mov ax, [si+26] ; ax is now a pointer to the pointer to the file relative to the data segments :D
add ax, 20h
add ax, 1Fh
mov [file_cluster], ax
; Setup registers for disk read
mov bx, data_buffer
mov si, file_buffer
mov bx, si
mov dl, [ebr_drive_number]
call disk_read ; Load file from disk into memory
mov ch, 02h
mov [read_write_flag], ch ; READ
call disk_read_or_write ; Load file from disk into memory
jmp .done
.file_not_found:
mov si, file_not_found
call os_print_string
jmp .done
.filename_too_long:
mov si, too_long_filename
call os_print_string
jmp .done
.done:
popa
ret
; Write data to file
; takes the contents in the data buffer for a fixed
; number of characters definied by [file_length]
; and write it to the file that si points to
; It also must edit the fat entry data
disk_write_file:
pusha
; Check if file name is too long
call os_string_length ; cl = string length
cmp cl, 11
ja .filename_too_long
; Convert file name to a fat filename
mov di, fat12_file_name
call os_format_fat_filename
; Locate the file entry in memory
; Prepare values
mov si, root_buffer
xor bx,bx
.search_root:
mov di, fat12_file_name ; Move the name of the kernel into di
mov cx, 11 ; length of filenames in fat12
push si ; Preserve si
repe cmpsb ; Repeat a comparison of bytes between file name and current bytes until it finds a match
pop si ; Retrieve si
je .found_file
section .data:
disk_read_fail: db 'Error: Could not read disk\n', 0
file_not_found: db 'File not found\n', 0
file_found: db 'File found\n', 0
loading_root: db 'Loading root diretory\n', 0
file_cluster: dw 0
fat12_file_name: db ' '
add si, 32 ; increment di to the next directory entry
inc bx
cmp bx, [bdb_dir_entries_count] ; Have we reached the number of directories that exist
jl .search_root ; Repeat search
jmp .file_not_found ; If the last dir has been searched, then there is no kernel
.found_file:
; Find where the file is on the disk
mov ax, [si+28] ; File length entry
mov [file_length], ax
mov ax, [si+26] ; ax is now a pointer to the pointer to the file relative to the data segments :D
add ax, 1Fh
mov [file_cluster], ax
; Setup registers for disk read
mov si, file_buffer
mov bx, si
mov dl, [ebr_drive_number]
mov ch, 03h
mov [read_write_flag], ch ; WRITE
call disk_read_or_write ; Load file from disk into memory
jmp .finish
; DI now points to a fat12 formatted file name
; Write to those sectors
; Update FAT entry
.file_not_found: ; TODO create a file if it's not found
mov si, file_not_found
call os_print_string
jmp .finish
.filename_too_long:
mov si, too_long_filename
call os_print_string
jmp .finish
.finish:
popa
ret
; TODO support long file names
; Store a list of the files in file_buffer
; in a human readable format
; OUT
; output_buffer: the list (string)
disk_list_contents:
pusha
mov si, root_buffer
mov di, output_buffer
.loop:
call string_unformat_fat_filename
mov cx, 000Ch
sub cx, [file_name_length]
add di, [file_name_length]
mov al, 20h
.space_loop:
stosb
dec cx
cmp cx, 0
jne .space_loop
.file_attribute:
add si, 11d
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:
pop si
mov al, 0Ah
stosb
add si, 20d
lodsb ; +1
dec si ; -1
cmp al, 0 ; You've come to the end of the root entries
je .finish
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
mov [file_length], di
stosb
popa
ret

View File

@@ -62,8 +62,7 @@ os_format_fat_filename:
pusha
call os_upper_case
call os_string_length ; Stores the length of the string in cl
mov bl, 11
sub bl, cl ; 11 - string_length
xor ch,ch ; Clear ch to reset it to 0
.character_loop:
lodsb
cmp al, 0
@@ -71,10 +70,18 @@ os_format_fat_filename:
cmp al, 2Eh ; 2Eh
je .add_spaces ; This will end up back at .character_loop
stosb
inc ch
jmp .character_loop
.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)
xor bl, bl
sub bl, ch
add bl, 7
.spaces_loop:
stosb
cmp bl, 0
@@ -85,6 +92,58 @@ os_format_fat_filename:
popa
ret
; Does the inverse of the previous
; Converts a fat filename back to human readable
; eg. 'KERNEL BIN' -> 'KERNEL.BIN'
; input: si points to fat filename (11 bytes)
; output:
; di points to the unformatted filename
; [file_name_length] stores the length of the filename
string_unformat_fat_filename:
pusha
xor ax,ax
xor dx,dx
mov cx, 11 ; Counter
.name_loop:
lodsb
stosb
dec cx
inc dx
cmp cx, 3
jne .name_loop
push si
mov si, di
.space_loop:
dec si
lodsb
dec si
dec dx
cmp al, 20h ; Space
je .space_loop
jmp .insert_stop
.insert_stop:
mov di, si
inc di
inc dx
pop si
mov al, 2Eh
stosb
mov cx, 3
.extension_loop:
lodsb
stosb
dec cx
inc dx
cmp cx, 0
jne .extension_loop
.finish:
inc dx
mov [file_name_length], dx
popa
ret
; 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

View File

@@ -11,68 +11,96 @@ os_print_string:
lodsb ; Get char from si into al
cmp al, 0 ; Compare al to 0
je .done ; If char is zero, end of string
cmp al, 0Ah ; When there's an NL or CR, do both, linux encodes files only with NL
je .new_line
cmp al, 0Dh
je .repeat
cmp al, 5Ch ; backslash
je .backslash
int 10h ; Otherwise, print it
jmp .repeat ; And move on to next char
.backslash: ; If there is a '\', do what it says, \n for newline, \t for tab etc
lodsb
dec si
cmp al, 6Eh ; 'n'
je .newline
cmp al, 74h ; \t
je .tab
cmp al, 5Ch ; '\'
je .another_backslash
jmp .repeat
.newline:
mov al, 0Ah ; new line
int 10h
mov al, 0Dh ; carriage return
int 10h
jmp .finish_backslash
.tab:
mov al, 09h ; tab
int 10h
jmp .finish_backslash
.another_backslash: ; This just prints 1 backslash
mov al, 5Ch
int 10h
jmp .finish_backslash
.finish_backslash:
inc si
.new_line:
mov al, 0Ah
int 10h
mov al, 0Dh
int 10h
jmp .repeat
.backslash:
call text_backslash
jmp .repeat
.done:
popa
ret
; This is similar to the previous, however it prints
; raw output (including null) and prints the number
; of character defined by ax
; of character defined by cx
; IN:
; SI = pointer to start of string to be printed
; AX = Length of string to print
text_raw_output:
; CX = Length of string to print
text_print_raw:
pusha
add cx, 1
mov ah, 0Eh
.repeat:
dec cx
cmp cx, 0
je .finish
lodsb
cmp al, 00h ; Print a space in place of a Null
je .space
cmp al, 0Ah ; When there's an NL or CR, do both, linux encodes files only with NL
je .new_line
cmp al, 0Dh
je .repeat
int 10h
jmp .repeat
.space:
mov al, 20h
int 10h
jmp .repeat
.new_line:
mov al, 0Ah
int 10h
mov al, 0Dh
int 10h
jmp .repeat
.finish:
popa
ret
mov di, ax
mov ah, 0Eh ; int 10h teletype function, we're telling the BIOS we will print something
.repeat:
lodsb ; Get char from si into al
int 10h ; Otherwise, print it
dec di
cmp di, 00h
je .done
jne .repeat
.done:
popa
ret
; NO PUSHING/POPPING!
text_backslash: ; If there is a '\', do what it says, \n for newline, \t for tab etc
lodsb
dec si
cmp al, 6Eh ; 'n'
je .newline
cmp al, 74h ; \t
je .tab
cmp al, 5Ch ; '\'
je .another_backslash
ret
.newline:
mov al, 0Ah ; new line
int 10h
mov al, 0Dh ; carriage return
int 10h
jmp .finish_backslash
.tab:
mov al, 09h ; tab
int 10h
jmp .finish_backslash
.another_backslash: ; This just prints 1 backslash
mov al, 5Ch
int 10h
jmp .finish_backslash
.finish_backslash:
inc si
ret
; --------------------------------------------
os_print_newline:

View File

@@ -0,0 +1,8 @@
time_get_time:
pusha
mov ah, 00h
int 1Ah
popa
ret

View File

@@ -0,0 +1,28 @@
util_cat:
pusha
call disk_clear_file_buffer
mov si, user_input
; TODO make this more consistent to account for double spaces
add si, 4 ; Move si to after 'CAT'
call disk_load_file
mov si, file_buffer
mov cx, [file_length]
call text_print_raw
popa
ret
util_ls:
pusha
call disk_clear_output_buffer
call disk_list_contents
mov si, output_buffer
call os_print_string
popa
ret

View File

@@ -1,17 +1,17 @@
ORG 00h
BITS 16
root_buffer equ 24000h
data_buffer equ 26000h
root_buffer: equ 24000h ; Stores a dump of the root directory
metadata_buffer: equ 27000h ; Stores metadata about whatever's in the data buffer
output_buffer: equ 27020h ; Buffer storing stuff you'll output
file_buffer: equ 28000h ; Stores actual data to be read
start:
call disk_load_root ; Loads the root directory into disk_buffer for future use
mov si, boot_message
call os_print_string
call disk_load_root ; Loads the root directory into disk_buffer
; Physical address = (segment * 16) + offset
mov si, file_name
call disk_load_file
mov si, help_text
call os_print_string
call os_start_cli
hlt
@@ -19,31 +19,6 @@ start:
halt:
jmp halt
boot_message: db 'OK] Kernel successfully loaded!\n\n', 0
file_name: db 'hello.cws', 0
; Define Fat12 header
bdb_oem: db 'MSWIN4.1' ; ignore
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_total_sectors: dw 0B40h ; = 2880d
bdb_media_descriptor_type: db 0F0h ; ignore
bdb_sectors_per_fat: dw 09h
bdb_sectors_per_track: dw 12h ; = 18d
bdb_number_of_heads: dw 02h ; top and bottom of the floppy disk
bdb_hidden_sectors: dd 0 ; ignore
bdb_large_sector_count: dd 0 ; total sector count for fat32 (0 for fat12 or fat16)
; extended boot record
ebr_drive_number: db 0 ; ignore
db 0 ; ignore
ebr_signature: db 29h ; boot signature, indicates that the next three fields are present (0x29)
ebr_volume_id: db 12h, 34h, 56h, 78h ; unique id for volume tracking
ebr_volume_label: db 'CrawShaw OS' ; must be 11 bytes
ebr_system_id: db 'FAT12 ' ; must be 8 bytes
; ------------------------------------------------------------------
; FEATURES -- Code to pull into the kernel
@@ -53,9 +28,14 @@ ebr_system_id: db 'FAT12 ' ; must be 8 bytes
%INCLUDE "source/kernel/features/power.asm"
%INCLUDE "source/kernel/features/strings.asm"
%INCLUDE "source/kernel/features/graphics.asm"
%INCLUDE "source/kernel/features/disk.asm"
%INCLUDE "source/kernel/features/math.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"
; DATA/VARIABLES
%INCLUDE "source/kernel/data.asm"