Added a os_upper_case function

This commit is contained in:
2025-10-30 22:57:31 +00:00
parent 0b9014d846
commit d83871e161
7 changed files with 193 additions and 83 deletions

View File

@@ -9,6 +9,8 @@ cdrom: $(BUILD_DIR)/crawos.iso
$(BUILD_DIR)/crawos.iso: floppy_image
mkdir -p disk_images
mkisofs -quiet -V 'CRAWOS' -input-charset iso8859-1 -o disk_images/crawos.iso -b crawos.img disk_images/
chmod 755 disk_images/*
chgrp users disk_images/*
# Floppy image
# Fat12
@@ -36,4 +38,4 @@ $(BUILD_DIR)/kernel.bin:
# Clean
clean:
rm -f disk-images/*
rm -f disk_images/*

View File

@@ -5,27 +5,27 @@ jmp short main
nop
; Define Fat12 header
bdb_oem: db 'MSWIN4.1'
bdb_bytes_per_sector: dw 512
bdb_sectors_per_cluster: db 1
bdb_reserved_sectors: dw 1
bdb_fat_count: db 2
bdb_dir_entries_count: dw 0E0h
bdb_total_sectors: dw 2880
bdb_media_descriptor_type: db 0F0h
bdb_sectors_per_fat: dw 9
bdb_sectors_per_track: dw 18
bdb_heads: dw 2
bdb_hidden_sectors: dd 0
bdb_large_sector_count: dd 0
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
db 0
ebr_signature: db 29h
ebr_volume_id: db 12h, 34h, 56h, 78h
ebr_volume_label: db 'CrawShaw OS'
ebr_system_id: db 'FAT12 '
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
main:
; Setup registers
@@ -37,11 +37,11 @@ main:
mov sp, 7C00h
; Read from disk
;mov [ebr_drive_number], dl
;mov ax, 1
;mov cl, 1
;mov bx, 7E00h
;call disk_read
; mov [ebr_drive_number], dl
; mov ax, 1
; mov cl, 1
; mov bx, 7E00h
; call disk_read
; Output boot text
mov si, boot_text
@@ -54,46 +54,54 @@ main:
; root dir: gives location of data
; data: stores the actual data
; Get LBA of root dir
mov ax, [bdb_sectors_per_fat]
mov bl, [bdb_fat_count]
; Get LBA of root dir (sectors per fat * fat count) + number of reserved sectors
mov ax, [bdb_sectors_per_fat] ; ax = 09h
mov bl, [bdb_fat_count] ; bl = 02h
xor bh,bh ; clear bh
mul bx ; 9 * 2 = 18
add ax, [bdb_reserved_sectors] ; The LBA of root dir
mul bx ; ax*bx = sectors per fat * fat count = 09h * 02h = 18
add ax, [bdb_reserved_sectors] ; then add on the reserved sector (1) = The LBA of root dir = 19d = 13h
push ax ; Push to stack
; the top of the ax stack now stores the LBA of the root directory
mov ax, [bdb_dir_entries_count]
; determine the size of the root directory
mov ax, [bdb_dir_entries_count] ; move the number of root directory entries into ax (E0h)
shl ax,5 ; ax *= 32 (shifting 5 times)
xor dx,dx ; Clear dx
div word [bdb_bytes_per_sector] ;32*num of entries)/bytes per sector
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
test dx,dx ; See if there's a remainder
jz root_dir_after
inc ax ; Add one if there's a remainder
inc ax ; Add one if there's a remainder (this is like rounding up)
; read the root directory tree into memory
root_dir_after:
; read the data from the root directory from disk
mov cl, al
pop ax ; LBA of root dir
mov dl, [ebr_drive_number]
mov bx, buffer
call disk_read
call disk_read ; convert the LBA of the root directory to a CHS
xor bx,bx ; clear bx
mov di, buffer ; Loaded root dir into memory
mov di, buffer ; Loaded root dir into memory, now we need to find the kernel
; di points to the start of this memory
; Search for 'KERNEL BIN' in a loop until all root files entries have been checked
search_for_kernel:
mov si, file_kernel_bin ; Move the name of the kernel into si
mov cx, 11
mov si, file_kernel_bin ; Move the name of the kernel into si (string pointer)
mov cx, 11 ; length of 'KERNEL BIN'
push di ; Preserve di
repe cmpsb ; Repeat a comparison of bytes between kernel name and current bytes until it finds a match
pop di ; Retrieve di
je found_kernel
add di, 32 ; Next directory entry
add di, 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_for_kernel ; Repeat search
jmp kernel_not_found ; If the last dir has been searched, then there is no kernel
; The kernel has not been found so output an error and halt
kernel_not_found:
mov si, kernel_load_error
call print_string
@@ -101,11 +109,12 @@ kernel_not_found:
hlt
jmp halt
; The kernel has been found
found_kernel:
mov si, kernel_found_text
call print_string
; Find kernel cluster
mov ax, [di+26]
mov ax, [di+26] ; di is the address of the kernel, 26 is the offset
mov [kernel_cluster], ax
mov ax, [bdb_reserved_sectors]
@@ -160,6 +169,8 @@ next_cluster_after:
jmp load_kernel_loop
read_finish: ; Load kernel
mov si, kernel_loading
call print_string
mov dl, [ebr_drive_number]
mov ax, kernel_load_segment
mov ds, ax
@@ -174,33 +185,65 @@ halt:
; LBA = index of data segment on disk
; CHS = cylinder, header, sector
; T = LBA/sectors per track
; S = (LBA%sectors per track) + 1
; H = T % heads
; C = T / headers
; input, LBA index: ax
; sector number: cx [0-5]
; cylinder: cx [6-15]
; sector number: cl
; cylinder: ch
; head: dh
; Example where LBA = 50h (CHS = 2,0,9)
; ax = 0050h, push this to the stack
; dx = 0000h
; dx = 50h % 12h = 0008h
; ax = 50h / 12h = 0004h
; dx = 0009h
; cx = 0009h
; dx = 0000h
; dx = 04h % 02h = 0000h
; ax = 04h / 02h = 0002h
; dh = 00h (dx = 0000h)
; ch = 02h (cx = 0209h)
; ah = 00h (ax = 0002h)
; cl = 09h OR 00h = 09h (cx = 0209h)
; ax = 0050h
; dl = 50h (dx = 0050h)
; ax = 0050h
; thus:
; cylinder (ch) = 02h
; head (cl) = 00h
; sector (dh) = 09h
lba_to_chs:
push ax
push dx
xor dx,dx ; clear dx
div word [bdb_sectors_per_track] ;(LBA % sectors per track) + 1 = sector
div word [bdb_sectors_per_track] ; (LBA % sectors per track) + 1 = sector
inc dx ; sector, dx stores the remainder so we increment that.
mov cx,dx
xor dx,dx ; clear dx
div word [bdb_heads]
div word [bdb_number_of_heads]
mov dh,dl ; head, dx stores remainder so we move that up 8 bits to dh
mov dh,dl ; head
mov ch,al
shl ah, 6
or CL, AH ; cylinder
shl ah, 6 ; * 32
or cl, ah ; cylinder
pop ax
mov dl,al
pop ax
RET
ret
; int 13h/ah = 02h read disk sectors into memory
; al = number of sectors to read
; ch = cylinder number
; cl = sector number
; dh = head number
; dl = drive number
; es:bx = points to data buffer
disk_read:
push ax
push bx
@@ -209,22 +252,32 @@ disk_read:
push di
call lba_to_chs
; cl = sector
; ch = cylinder
; dh = head
; dl = drive
call lba_to_chs ; Get the chs address
mov ah, 02h
mov ah, 02h ; BIOS ah code for read disk sectors to memory
; repeat drive read 3 times (incase of random error)
mov di, 3 ; counter
; This is basically
; for di in range(3,1,1):
; We test to see if we can read the disk 3 times
retry:
stc
; When the disk is tried to be read, the CF flag will be
; set if there's an error, so we just clear it to return it to
; the default state
stc ; sets the cf flag
int 13h
jnc done_read
jnc done_read ; jump if cf = 0
call disk_reset ; Reset drivers of disk
dec di
test di, di
dec di ; di -= 1
test di, di ; if di = 0
jnz retry
fail_disk_read:
@@ -233,6 +286,7 @@ fail_disk_read:
hlt
jmp halt
; int 13h / ah = 00h reset disk system
disk_reset:
pusha
mov ah, 0 ; Reset drive
@@ -280,14 +334,15 @@ print_string:
pop si
ret
boot_text: db '[OK] Boot sequence begun...', 0
kernel_found_text: db '[OK] Kernel located...', 0
disk_read_fail: db '[ERR] Failed to read disk!', 0
boot_text: db 'OK] Boot sequence begun', 0
kernel_found_text: db 'OK] Kernel located', 0
kernel_loading: db 'OK] Loading kernel', 0
disk_read_fail: db 'ERR] Disk read fail', 0
file_kernel_bin: db 'KERNEL BIN' ; Must have a double space between KERNEL and BIN
kernel_load_error: db '[ERR] Kernel not found!', 0
kernel_load_error: db 'ERR] Kernel not found', 0
kernel_cluster: dw 0
kernel_load_segment: equ 2000h
kernel_load_segment: equ 2000h ; an area in memory we know should be available
kernel_load_offset: equ 0

View File

@@ -22,30 +22,41 @@ os_read_cli:
call os_print_newline
.check_matches: ; Check if the user input matches any internal commands
mov si, user_input
mov di, help_string
; Help
mov di, user_input
mov si, help_string
call os_compare_strings
cmp cl, 1
je help
mov si, user_input
mov di, clear_string
; Clear screen
mov di, user_input
mov si, clear_string
call os_compare_strings
cmp cl, 1
je clear
mov si, user_input
mov di, pong_string
; Reboot
mov di, user_input
mov si, reboot_string
call os_compare_strings
cmp cl, 1
je os_reboot
; Reboot
mov di, user_input
mov si, cat_string
call os_compare_strings
cmp cl, 1
je cat
; Pong
mov di, user_input
mov si, pong_string
call os_compare_strings
cmp cl, 1
je pong
mov si, user_input
mov di, snake_string
call os_compare_strings
cmp cl, 1
je snake
jmp .unkown
.unkown:
@@ -68,12 +79,12 @@ help:
call os_print_string_nl
call os_read_cli.finish
pong:
call game_pong
cat:
call util_cat
call os_read_cli.finish
snake:
call game_snake
pong:
call game_pong
call os_read_cli.finish
section .data
@@ -83,8 +94,9 @@ section .data
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
snake_string db 'SNAKE', 0
help_text db 'This is for Cowards: "HELP" for this help text, "CLEAR" to clear the screen, esc to reboot', 0
help_text db 'This is for Cowards: "HELP" for this help text, "CLEAR" to clear the screen, esc or "REBOOT" to reboot', 0
command_result_text db 'You typed: ', 0
unknown_command db 'Error: Unkown Command.. ', 0

View File

@@ -12,7 +12,7 @@ os_compare_strings:
.compare:
lodsb
scasb ; Compare di to si
jne .unequal ; If they are no equal, jump to .unequal
jne .unequal ; If they are not equal, jump to .unequal
cmp al, 0 ; Check if string is finished
je .equal ; If it has, return true
jmp .compare ; Finally, repeat
@@ -24,3 +24,26 @@ os_compare_strings:
.equal:
mov cl, 1
ret
; Convert a string to all upper case
os_upper_case:
pusha
mov di, si
.loop:
lodsb
inc di
cmp al, 0
je .finish
cmp al, 7Ah
jns .loop
cmp al, 61h
js .loop
sub al, 20h
dec di
stosb
jmp .loop
.finish:
popa
ret

View File

@@ -0,0 +1,18 @@
; Outputs the contents of a file
util_cat:
pusha
call os_print_newline
mov si, cat_prompt
call os_print_string
mov ax, 11 ; length of input
mov di, user_input
popa
ret
section .data:
cat_prompt db 'Enter file name: ', 0

View File

@@ -2,6 +2,8 @@ ORG 0h
BITS 16
start:
mov si, boot_message
call os_upper_case
mov si, boot_message
call os_print_string_nl
@@ -14,7 +16,7 @@ start:
halt:
jmp halt
boot_message: db 0Dh, 'Welcome to CrawOS!', 0Dh, 0
boot_message: db 'kernel successfully loaded!', 0
; ------------------------------------------------------------------
; FEATURES -- Code to pull into the kernel
@@ -24,9 +26,7 @@ boot_message: db 0Dh, 'Welcome to CrawOS!', 0Dh, 0
%INCLUDE "source/kernel/features/power.asm"
%INCLUDE "source/kernel/features/strings.asm"
%INCLUDE "source/kernel/features/graphics.asm"
%INCLUDE "source/kernel/features/sound.asm"
%INCLUDE "source/kernel/features/basic.asm"
%INCLUDE "source/kernel/features/math.asm"
%INCLUDE "source/kernel/features/utils.asm"
; GAMES -- Games that I wrote for it
%INCLUDE "source/kernel/games/pong.asm"
%INCLUDE "source/kernel/games/snake.asm"