idk what i added
This commit is contained in:
9
data/README.md
Executable file
9
data/README.md
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
Kernel written in Assmebly
|
||||||
|
I'm using a modified JazzOS Bootloader
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
CAT
|
||||||
|
HELP
|
||||||
|
CLEAR
|
||||||
|
REBOOT
|
||||||
|
PONG
|
||||||
1
data/var.cws
Normal file
1
data/var.cws
Normal file
@@ -0,0 +1 @@
|
|||||||
|
x = 5
|
||||||
58
source/kernel/data.asm
Normal file
58
source/kernel/data.asm
Normal 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
|
||||||
@@ -45,6 +45,20 @@ os_read_cli:
|
|||||||
cmp cl, 1
|
cmp cl, 1
|
||||||
je power_reboot
|
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
|
; Pong
|
||||||
mov si, user_input
|
mov si, user_input
|
||||||
mov di, pong_string
|
mov di, pong_string
|
||||||
@@ -78,16 +92,9 @@ pong:
|
|||||||
call game_pong
|
call game_pong
|
||||||
call os_read_cli.finish
|
call os_read_cli.finish
|
||||||
|
|
||||||
section .data
|
cat:
|
||||||
welcome_text db 'Welcome to CrawOS, the Cwick, Real and AWsome Operating System\n', 0
|
call util_cat
|
||||||
user_input times 20 db 0
|
call os_read_cli.finish
|
||||||
prompt_length db 20
|
ls:
|
||||||
prompt db 'CrawOS sh> ', 0
|
call util_ls
|
||||||
help_string db 'HELP', 0
|
call os_read_cli.finish
|
||||||
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
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ disk_load_root:
|
|||||||
pusha
|
pusha
|
||||||
mov ax, 19 ; First sector of root entry
|
mov ax, 19 ; First sector of root entry
|
||||||
call math_lba_to_chs ; Assigns ch, cl and dh the correct values
|
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 dl, [ebr_drive_number] ; Drive number
|
||||||
mov ah, 02h ; BIOS ah code for read disk sectors to memory
|
mov ah, 02h ; BIOS ah code for read disk sectors to memory
|
||||||
mov al, 0Ch ; Root directory has 12 sectors
|
mov al, 0Ch ; Root directory has 12 sectors
|
||||||
@@ -53,28 +53,34 @@ disk_load_root:
|
|||||||
; ---------------------------------------------
|
; ---------------------------------------------
|
||||||
|
|
||||||
; Reads a certain number of sectors into memory
|
; 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
|
; al = number of sectors to read
|
||||||
|
; ah = read/write 02=read, 03=write IMPORTANT
|
||||||
; ch = cylinder number
|
; ch = cylinder number
|
||||||
; cl = sector number
|
; cl = sector number
|
||||||
; dh = head number
|
; dh = head number
|
||||||
; dl = drive number
|
; dl = drive number
|
||||||
; es:bx = points to data buffer
|
; es:bx = points to data buffer
|
||||||
disk_read:
|
disk_read_or_write:
|
||||||
push ax
|
push ax
|
||||||
push bx
|
push bx
|
||||||
push cx
|
push cx
|
||||||
push dx
|
push dx
|
||||||
push di
|
push di
|
||||||
|
|
||||||
|
|
||||||
; cl = sector
|
; cl = sector
|
||||||
; ch = cylinder
|
; ch = cylinder
|
||||||
; dh = head
|
; dh = head
|
||||||
; dl = drive
|
; dl = drive
|
||||||
call math_lba_to_chs ; Get the chs address
|
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)
|
; repeat drive read 3 times (incase of random error)
|
||||||
mov di, 3 ; counter
|
mov di, 3 ; counter
|
||||||
@@ -122,10 +128,55 @@ disk_read:
|
|||||||
pop ax
|
pop ax
|
||||||
ret
|
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:
|
disk_load_file:
|
||||||
pusha
|
pusha
|
||||||
|
call os_string_length ; cl = string length
|
||||||
|
cmp cl, 11
|
||||||
|
ja .filename_too_long
|
||||||
|
|
||||||
mov di, fat12_file_name
|
mov di, fat12_file_name
|
||||||
call os_format_fat_filename
|
call os_format_fat_filename
|
||||||
|
|
||||||
@@ -134,7 +185,7 @@ disk_load_file:
|
|||||||
xor bx,bx
|
xor bx,bx
|
||||||
.search_root:
|
.search_root:
|
||||||
mov di, fat12_file_name ; Move the name of the kernel into di
|
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
|
push si ; Preserve si
|
||||||
repe cmpsb ; Repeat a comparison of bytes between file name and current bytes until it finds a match
|
repe cmpsb ; Repeat a comparison of bytes between file name and current bytes until it finds a match
|
||||||
pop si ; Retrieve si
|
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
|
jmp .file_not_found ; If the last dir has been searched, then there is no kernel
|
||||||
.found_file:
|
.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
|
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
|
mov [file_cluster], ax
|
||||||
; Setup registers for disk read
|
; Setup registers for disk read
|
||||||
mov bx, data_buffer
|
mov si, file_buffer
|
||||||
|
mov bx, si
|
||||||
mov dl, [ebr_drive_number]
|
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
|
jmp .done
|
||||||
.file_not_found:
|
.file_not_found:
|
||||||
mov si, file_not_found
|
mov si, file_not_found
|
||||||
call os_print_string
|
call os_print_string
|
||||||
jmp .done
|
jmp .done
|
||||||
|
.filename_too_long:
|
||||||
|
mov si, too_long_filename
|
||||||
|
call os_print_string
|
||||||
|
jmp .done
|
||||||
.done:
|
.done:
|
||||||
popa
|
popa
|
||||||
ret
|
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:
|
add si, 32 ; increment di to the next directory entry
|
||||||
disk_read_fail: db 'Error: Could not read disk\n', 0
|
inc bx
|
||||||
file_not_found: db 'File not found\n', 0
|
cmp bx, [bdb_dir_entries_count] ; Have we reached the number of directories that exist
|
||||||
file_found: db 'File found\n', 0
|
jl .search_root ; Repeat search
|
||||||
loading_root: db 'Loading root diretory\n', 0
|
|
||||||
file_cluster: dw 0
|
jmp .file_not_found ; If the last dir has been searched, then there is no kernel
|
||||||
fat12_file_name: db ' '
|
.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
|
||||||
|
|||||||
@@ -62,8 +62,7 @@ os_format_fat_filename:
|
|||||||
pusha
|
pusha
|
||||||
call os_upper_case
|
call os_upper_case
|
||||||
call os_string_length ; Stores the length of the string in cl
|
call os_string_length ; Stores the length of the string in cl
|
||||||
mov bl, 11
|
xor ch,ch ; Clear ch to reset it to 0
|
||||||
sub bl, cl ; 11 - string_length
|
|
||||||
.character_loop:
|
.character_loop:
|
||||||
lodsb
|
lodsb
|
||||||
cmp al, 0
|
cmp al, 0
|
||||||
@@ -71,10 +70,18 @@ os_format_fat_filename:
|
|||||||
cmp al, 2Eh ; 2Eh
|
cmp al, 2Eh ; 2Eh
|
||||||
je .add_spaces ; This will end up back at .character_loop
|
je .add_spaces ; This will end up back at .character_loop
|
||||||
stosb
|
stosb
|
||||||
|
inc ch
|
||||||
jmp .character_loop
|
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
|
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:
|
.spaces_loop:
|
||||||
stosb
|
stosb
|
||||||
cmp bl, 0
|
cmp bl, 0
|
||||||
@@ -85,6 +92,58 @@ os_format_fat_filename:
|
|||||||
popa
|
popa
|
||||||
ret
|
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
|
; 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
|
||||||
|
|||||||
@@ -11,13 +11,70 @@ os_print_string:
|
|||||||
lodsb ; Get char from si into al
|
lodsb ; Get char from si into al
|
||||||
cmp al, 0 ; Compare al to 0
|
cmp al, 0 ; Compare al to 0
|
||||||
je .done ; If char is zero, end of string
|
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
|
cmp al, 5Ch ; backslash
|
||||||
je .backslash
|
je .backslash
|
||||||
|
|
||||||
int 10h ; Otherwise, print it
|
int 10h ; Otherwise, print it
|
||||||
jmp .repeat ; And move on to next char
|
jmp .repeat ; And move on to next char
|
||||||
|
|
||||||
.backslash: ; If there is a '\', do what it says, \n for newline, \t for tab etc
|
.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 cx
|
||||||
|
; IN:
|
||||||
|
; SI = pointer to start of string to be printed
|
||||||
|
; 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
|
||||||
|
|
||||||
|
; NO PUSHING/POPPING!
|
||||||
|
text_backslash: ; If there is a '\', do what it says, \n for newline, \t for tab etc
|
||||||
lodsb
|
lodsb
|
||||||
dec si
|
dec si
|
||||||
cmp al, 6Eh ; 'n'
|
cmp al, 6Eh ; 'n'
|
||||||
@@ -26,7 +83,7 @@ os_print_string:
|
|||||||
je .tab
|
je .tab
|
||||||
cmp al, 5Ch ; '\'
|
cmp al, 5Ch ; '\'
|
||||||
je .another_backslash
|
je .another_backslash
|
||||||
jmp .repeat
|
ret
|
||||||
.newline:
|
.newline:
|
||||||
mov al, 0Ah ; new line
|
mov al, 0Ah ; new line
|
||||||
int 10h
|
int 10h
|
||||||
@@ -43,36 +100,7 @@ os_print_string:
|
|||||||
jmp .finish_backslash
|
jmp .finish_backslash
|
||||||
.finish_backslash:
|
.finish_backslash:
|
||||||
inc si
|
inc si
|
||||||
jmp .repeat
|
|
||||||
.done:
|
|
||||||
popa
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; This is similar to the previous, however it prints
|
|
||||||
; raw output (including null) and prints the number
|
|
||||||
; of character defined by ax
|
|
||||||
; IN:
|
|
||||||
; SI = pointer to start of string to be printed
|
|
||||||
; AX = Length of string to print
|
|
||||||
text_raw_output:
|
|
||||||
pusha
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
; --------------------------------------------
|
; --------------------------------------------
|
||||||
|
|
||||||
os_print_newline:
|
os_print_newline:
|
||||||
|
|||||||
8
source/kernel/features/time.asm
Normal file
8
source/kernel/features/time.asm
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
time_get_time:
|
||||||
|
pusha
|
||||||
|
|
||||||
|
mov ah, 00h
|
||||||
|
int 1Ah
|
||||||
|
|
||||||
|
popa
|
||||||
|
ret
|
||||||
28
source/kernel/features/utils.asm
Normal file
28
source/kernel/features/utils.asm
Normal 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
|
||||||
|
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
ORG 00h
|
ORG 00h
|
||||||
BITS 16
|
BITS 16
|
||||||
root_buffer equ 24000h
|
root_buffer: equ 24000h ; Stores a dump of the root directory
|
||||||
data_buffer equ 26000h
|
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:
|
start:
|
||||||
|
call disk_load_root ; Loads the root directory into disk_buffer for future use
|
||||||
|
|
||||||
mov si, boot_message
|
mov si, boot_message
|
||||||
call os_print_string
|
call os_print_string
|
||||||
|
mov si, help_text
|
||||||
call disk_load_root ; Loads the root directory into disk_buffer
|
call os_print_string
|
||||||
|
|
||||||
; Physical address = (segment * 16) + offset
|
|
||||||
mov si, file_name
|
|
||||||
call disk_load_file
|
|
||||||
|
|
||||||
call os_start_cli
|
call os_start_cli
|
||||||
hlt
|
hlt
|
||||||
@@ -19,31 +19,6 @@ start:
|
|||||||
halt:
|
halt:
|
||||||
jmp 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
|
; FEATURES -- Code to pull into the kernel
|
||||||
@@ -55,7 +30,12 @@ ebr_system_id: db 'FAT12 ' ; must be 8 bytes
|
|||||||
%INCLUDE "source/kernel/features/graphics.asm"
|
%INCLUDE "source/kernel/features/graphics.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/utils.asm"
|
||||||
; GAMES -- Games that I wrote for it
|
; GAMES -- Games that I wrote for it
|
||||||
%INCLUDE "source/kernel/games/pong.asm"
|
%INCLUDE "source/kernel/games/pong.asm"
|
||||||
|
|
||||||
|
; DATA/VARIABLES
|
||||||
|
%INCLUDE "source/kernel/data.asm"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user