forked from PoliEcho-holding-org/kern
Began moving to C. (No C yet)
If you want to build the assembly version, run the buildAsm.sh script Currently just setting up the bootloader.
This commit is contained in:
@@ -0,0 +1,504 @@
|
||||
[bits 16]
|
||||
|
||||
start:
|
||||
; Save the drive number from stack
|
||||
mov byte [driveNum], dl
|
||||
|
||||
mov bx, 0x2000
|
||||
mov es, bx
|
||||
xor bx, bx
|
||||
|
||||
call resetTextMode
|
||||
call clearText
|
||||
|
||||
; Print start message
|
||||
mov si, startMsg
|
||||
call print
|
||||
|
||||
; Runs prompt
|
||||
input:
|
||||
mov si, prompt
|
||||
call print
|
||||
mov ax, 0x2000
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov si, userInput
|
||||
xor cx, cx
|
||||
.loop:
|
||||
xor ax, ax ; Clear ax
|
||||
int 0x16 ; Get a character
|
||||
|
||||
cmp al, 0x0d ; Compare with CR
|
||||
je .enter
|
||||
cmp al, 0x08 ; Compare with BS
|
||||
je .backspace
|
||||
|
||||
mov ah, 0x0e ; Echo back input
|
||||
mov bh, 0
|
||||
int 0x10
|
||||
|
||||
mov [si], al ; Add the input to userInput
|
||||
inc cx
|
||||
inc si
|
||||
jmp .loop
|
||||
.backspace:
|
||||
cmp cx, 0 ; Check if we can backspace
|
||||
je .loop
|
||||
mov byte [si], 0
|
||||
dec si
|
||||
dec cx
|
||||
mov al, 0x08
|
||||
int 0x10
|
||||
mov al, ' '
|
||||
int 0x10
|
||||
mov al, 0x08
|
||||
int 0x10
|
||||
jmp .loop
|
||||
.enter:
|
||||
push si
|
||||
mov si, newline
|
||||
call print
|
||||
pop si
|
||||
mov byte [si], 0 ; NULL terminate userInput (Replaces CR)
|
||||
mov byte [inputLen], cl
|
||||
|
||||
cmp byte [inputLen], 0 ; Check if user input something
|
||||
je input
|
||||
|
||||
tokenize: ; Tokenize
|
||||
mov byte cl, [inputLen]
|
||||
mov di, tokens
|
||||
.tokenLoop:
|
||||
lodsb
|
||||
cmp al, 0 ; Check for end of input
|
||||
je runCommand
|
||||
.wsLoop:
|
||||
cmp al, ' ' ; Compare with whitespace
|
||||
jne .stringLoop
|
||||
lodsb
|
||||
jmp .wsLoop
|
||||
.stringLoop:
|
||||
cmp al, ' '
|
||||
je .next
|
||||
|
||||
.next:
|
||||
|
||||
|
||||
; Runs a command in userInput
|
||||
; Expects tokenized input
|
||||
runCommand:
|
||||
mov di, lsCmd
|
||||
call .cmp
|
||||
je fileList
|
||||
|
||||
mov di, gfxCmd
|
||||
call .cmp
|
||||
je graphicsTest
|
||||
|
||||
mov di, helpCmd
|
||||
call .cmp
|
||||
je help
|
||||
|
||||
mov di, rebootCmd
|
||||
call .cmp
|
||||
je reboot
|
||||
|
||||
mov di, clearCmd
|
||||
call .cmp
|
||||
je clear
|
||||
|
||||
mov di, exitCmd
|
||||
call .cmp
|
||||
je shutdown
|
||||
|
||||
mov di, rmCmd
|
||||
call .cmp
|
||||
je rmFile
|
||||
|
||||
jmp .end
|
||||
.cmp:
|
||||
push cx
|
||||
mov si, userInput
|
||||
repe cmpsb
|
||||
pop cx
|
||||
ret
|
||||
.end:
|
||||
|
||||
;
|
||||
; Load Program - Takes userInput and tries to run that file
|
||||
;
|
||||
loadProgram:
|
||||
mov di, userInput
|
||||
mov bx, FILETAB_LOC
|
||||
mov es, bx
|
||||
xor bx, bx ; Get [es:bx] to be start of filetable
|
||||
.nextCh:
|
||||
mov al, [es:bx]
|
||||
cmp al, 0 ; Check for end of filetable
|
||||
je .notFound
|
||||
|
||||
cmp al, [di] ; Check for starting character
|
||||
je .beginSearch
|
||||
|
||||
add bx, 16 ; Move to the next entry
|
||||
jmp .nextCh
|
||||
.beginSearch:
|
||||
push bx ; Save position, if it doesn't equal
|
||||
mov byte cl, [inputLen]
|
||||
.searchLoop:
|
||||
mov al, [es:bx]
|
||||
inc bx
|
||||
cmp al, [di]
|
||||
jne .restartSearch
|
||||
|
||||
dec cl
|
||||
jz .match
|
||||
inc di
|
||||
jmp .searchLoop
|
||||
.match:
|
||||
mov al, [es:bx]
|
||||
cmp al, 0 ; Check if we are at the end of a filename
|
||||
je foundProgram
|
||||
.restartSearch:
|
||||
mov di, userInput
|
||||
pop bx
|
||||
inc bx
|
||||
jmp .nextCh
|
||||
.notFound:
|
||||
mov si, fileNotFoundMsg
|
||||
call print
|
||||
jmp input
|
||||
|
||||
foundProgram:
|
||||
mov al, [es:bx]
|
||||
cmp al, 0 ; Loop until we find the extension
|
||||
jne .getMetadata
|
||||
inc bx
|
||||
jmp foundProgram
|
||||
.getMetadata:
|
||||
mov al, [es:bx]
|
||||
mov [fileExt], al
|
||||
inc bx
|
||||
mov al, [es:bx]
|
||||
mov [fileExt+1], al
|
||||
inc bx
|
||||
mov al, [es:bx]
|
||||
mov [fileExt+2], al
|
||||
inc bx
|
||||
|
||||
inc bx ; Ignore Number of FT entries for now
|
||||
|
||||
mov cl, [es:bx] ; Starting sector
|
||||
inc bx
|
||||
mov al, [es:bx] ; Number of sectors to read
|
||||
push ax ; Save file size
|
||||
|
||||
mov ah, 0 ; Reset disk system
|
||||
mov dl, byte [driveNum]
|
||||
int 0x13
|
||||
|
||||
mov bx, PROGRAM_LOC
|
||||
mov es, bx
|
||||
xor bx, bx ; [es:bx] - Place to load out program
|
||||
|
||||
mov ah, 2 ; Read sectors into memory
|
||||
mov dl, byte [driveNum]
|
||||
mov ch, 0 ; Cylinder
|
||||
mov dh, 0 ; Head
|
||||
int 0x13
|
||||
jnc .loaded ; Loaded file successfully
|
||||
|
||||
mov si, programLoadFailMsg
|
||||
call print
|
||||
|
||||
jmp input
|
||||
.loaded:
|
||||
; Check file extension. If 'bin', then run, if 'txt', print
|
||||
pop ax ; Restore file size
|
||||
|
||||
mov cx, 3 ; Check file extension
|
||||
mov si, fileExt
|
||||
mov ax, 0x2000
|
||||
mov es, ax
|
||||
mov di, binExt
|
||||
repe cmpsb
|
||||
jne .printText ; TODO: Check for more file extensions
|
||||
|
||||
mov dl, [driveNum]
|
||||
|
||||
mov ax, PROGRAM_LOC
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
jmp PROGRAM_LOC:0x0000
|
||||
.printText:
|
||||
mov bx, PROGRAM_LOC
|
||||
mov es, bx
|
||||
xor bx, bx
|
||||
mov cx, 512
|
||||
mul cx
|
||||
mov cx, ax
|
||||
mov ah, 0x0e
|
||||
.textLoop:
|
||||
mov al, [es:bx]
|
||||
cmp al, 0
|
||||
je .rep
|
||||
int 0x10
|
||||
.rep:
|
||||
inc bx
|
||||
dec cx
|
||||
jnz .textLoop
|
||||
|
||||
mov si, newline
|
||||
call print
|
||||
jmp input
|
||||
|
||||
;
|
||||
; Help - Prints the help message (helpMsg)
|
||||
;
|
||||
help:
|
||||
mov si, helpMsg
|
||||
call print
|
||||
jmp input
|
||||
|
||||
;
|
||||
; Clears the screen
|
||||
;
|
||||
clear:
|
||||
call clearText
|
||||
jmp input
|
||||
|
||||
;
|
||||
; Shuts the system down
|
||||
; Only works for QEMU
|
||||
;
|
||||
shutdown:
|
||||
mov ax, 0x2000
|
||||
mov dx, 0x0604
|
||||
out dx, ax
|
||||
|
||||
;
|
||||
; Remove file (rm)
|
||||
;
|
||||
rmFile:
|
||||
call removeFile
|
||||
jmp input
|
||||
|
||||
;
|
||||
; File list (ls)
|
||||
;
|
||||
fileList:
|
||||
mov bx, FILETAB_LOC
|
||||
mov es, bx
|
||||
xor bx, bx
|
||||
|
||||
mov al, 2 ; Read from disk
|
||||
mov byte dl, [driveNum]
|
||||
mov ch, 0 ; Cylinder
|
||||
mov dh, 0 ; Head
|
||||
mov cl, 2 ; Sector
|
||||
mov al, 1 ; Read 1 sector
|
||||
int 0x13 ; Move filetable to es:bx
|
||||
|
||||
mov si, fileListMsg
|
||||
call print
|
||||
|
||||
; Prints the filetable
|
||||
printFiletable:
|
||||
mov bx, FILETAB_LOC
|
||||
mov es, bx
|
||||
xor bx, bx
|
||||
xor cx, cx ; Entry byte couter
|
||||
mov ah, 0x0e ; Prepare for printing
|
||||
.filenameLoop:
|
||||
mov al, [es:bx] ; Get filename character
|
||||
cmp al, 0 ; Check if it's NULL
|
||||
je .filenameEnd ; If so, end the filename reading
|
||||
cmp cx, 9 ; Check if we already read 10 Bytes
|
||||
je .filenameEnd
|
||||
int 0x10 ; Else print the character
|
||||
inc cx ; Increment byte counter
|
||||
inc bx
|
||||
jmp .filenameLoop
|
||||
.filenameEnd:
|
||||
push cx
|
||||
.skipNull:
|
||||
cmp cx, 0
|
||||
je .done
|
||||
cmp cx, 10 ; Check if we're at the end of filename
|
||||
je .fileExt ; If so, print extension
|
||||
inc cx
|
||||
inc bx
|
||||
jmp .skipNull
|
||||
.fileExt:
|
||||
; push cx ; Save the counter
|
||||
mov al, '.' ; Print a "." to separate filename from extension
|
||||
int 0x10
|
||||
.fileExtLoop:
|
||||
mov al, [es:bx]
|
||||
cmp cx, 13 ; Check if we printed 3 characters
|
||||
je .fileExtEnd
|
||||
cmp al, 0
|
||||
je .fileExtEnd
|
||||
int 0x10
|
||||
inc cx
|
||||
inc bx
|
||||
jmp .fileExtLoop
|
||||
.fileExtEnd:
|
||||
cmp cx, 13
|
||||
je .whitespace
|
||||
inc cx
|
||||
inc bx
|
||||
mov al, ' ' ; Print whitespace
|
||||
int 0x10
|
||||
jmp .fileExtEnd
|
||||
.whitespace:
|
||||
pop cx
|
||||
.wsLoop:
|
||||
cmp cx, 11 ; Max filename length + 1 for spacing
|
||||
je .fileInfo
|
||||
mov al, ' '
|
||||
int 0x10
|
||||
inc cx
|
||||
jmp .wsLoop
|
||||
.fileInfo:
|
||||
; Entry number
|
||||
mov dl, [es:bx]
|
||||
call printHexByte
|
||||
inc bx
|
||||
mov al, ' '
|
||||
int 0x10
|
||||
; Start sector
|
||||
mov dl, [es:bx]
|
||||
call printHexByte
|
||||
inc bx
|
||||
mov al, ' '
|
||||
int 0x10
|
||||
int 0x10
|
||||
int 0x10
|
||||
; File size
|
||||
mov al, [es:bx]
|
||||
inc bx
|
||||
cmp al, 1
|
||||
je .oneSector ; Only print 512B
|
||||
shr al, 1 ; Divide by 2
|
||||
jc .oneHalf ; We had an odd number of sectors
|
||||
add al, '0'
|
||||
int 0x10
|
||||
mov si, kilobyteText
|
||||
call print
|
||||
jmp .repeat
|
||||
.oneHalf:
|
||||
add al, '0'
|
||||
int 0x10
|
||||
mov si, oneHalfText
|
||||
call print
|
||||
jmp .repeat
|
||||
.oneSector:
|
||||
mov si, sectorLenText
|
||||
call print
|
||||
.repeat:
|
||||
mov si, newline
|
||||
call print
|
||||
xor cx, cx
|
||||
jmp .filenameLoop
|
||||
.done:
|
||||
jmp input
|
||||
|
||||
;
|
||||
; Graphics Mode Test
|
||||
;
|
||||
graphicsTest:
|
||||
call resetGraphicsMode
|
||||
|
||||
; Test square
|
||||
mov ah, 0x0c ; Write gfx pixel
|
||||
mov al, 0x02 ; Green
|
||||
mov bh, 0 ; Page number
|
||||
|
||||
mov cx, 100 ; Column number
|
||||
mov dx, 100 ; Row number
|
||||
int 0x10
|
||||
.colLoop:
|
||||
inc cx
|
||||
int 0x10
|
||||
cmp cx, 150
|
||||
jne .colLoop
|
||||
|
||||
inc dx
|
||||
int 0x10
|
||||
mov cx, 99
|
||||
cmp dx, 150
|
||||
jne .colLoop
|
||||
.done:
|
||||
mov si, startMsg
|
||||
call print
|
||||
|
||||
xor ax, ax
|
||||
int 0x16
|
||||
|
||||
call resetTextMode
|
||||
jmp input
|
||||
|
||||
;
|
||||
; Reboots the OS
|
||||
;
|
||||
reboot: jmp 0xffff:0x0000
|
||||
|
||||
;; Includes
|
||||
%include "./src/lib/print.asm"
|
||||
%include "./src/lib/screen.asm"
|
||||
%include "./src/lib/disk.asm"
|
||||
|
||||
;; Variables
|
||||
driveNum: db 0
|
||||
|
||||
startMsg: db "kern.", ENDL, ENDL, 0 ; The bootup message
|
||||
prompt: db "> ", 0 ; Prompt for input
|
||||
fileNotFoundMsg: db "File not found!", ENDL, 0 ; User tries to load nonexistent file
|
||||
programLoadFailMsg: db "Couldn't load file!", ENDL, 0 ; File load fail
|
||||
sectorLenText: db "512B", 0
|
||||
kilobyteText: db "kB", 0
|
||||
oneHalfText: db ".5kB", 0
|
||||
|
||||
fileListMsg: db " Filename E# St Size ", ENDL, \
|
||||
"---------- ------- ------", ENDL, 0
|
||||
|
||||
helpMsg: db "Available Commands:", ENDL, \
|
||||
" clear | Clears the screen", ENDL, \
|
||||
" edit | Opens the code editor", ENDL, \
|
||||
" exit | Shuts the system down", ENDL, \
|
||||
" gfx | Graphics mode test", ENDL, \
|
||||
" help | Prints this message", ENDL, \
|
||||
" ls | List all files", ENDL, \
|
||||
" reboot | Reboots the system", ENDL, \
|
||||
" rm | Removes a file", ENDL, ENDL, 0
|
||||
|
||||
; Commands
|
||||
; TODO: Put these into a file or something
|
||||
clearCmd: db "clear", 0
|
||||
exitCmd: db "exit"
|
||||
gfxCmd: db "gfx", 0
|
||||
helpCmd: db "help", 0
|
||||
lsCmd: db "ls", 0
|
||||
rebootCmd: db "reboot", 0
|
||||
rmCmd: db "rm", 0
|
||||
|
||||
; Files
|
||||
fileExt: db " ", 0
|
||||
binExt: db "bin", 0
|
||||
txtExt: db "txt", 0
|
||||
|
||||
tokens: times 50 db 0 ; char[10][5] (List of 5 strings that are 10 chars long each or null terminated)
|
||||
tokenLen: times 5 db 0 ; 5 lengths for each token
|
||||
tokenCount: db 0
|
||||
inputLen: db 0
|
||||
userInput: times 80 db 0
|
||||
|
||||
;; Constants
|
||||
FILETAB_LOC equ 0x1000
|
||||
PROGRAM_LOC equ 0x8000
|
||||
|
||||
times 4*512-($-$$) db 0
|
||||
Reference in New Issue
Block a user