EttinOS/src/SYSTEM.ASM

294 lines
4.7 KiB
NASM

cpu 8086
org 0x500
;Jump to the code
jmp start
;Interrupt handler
;Return to the shell
int0x20:
jmp shell
;Input and output
int0x21:
cmp ah, 0x0
je printstr
cmp ah, 0x1
je readstr
cmp ah, 0x2
je println
cmp ah, 0x3
je readln
iret
;Disk operations
int0x22:
cmp ah, 0x2
je loadf
;To do: savef
iret
;System call includes
%include "PRINTSTR.INC"
%include "READSTR.INC"
%include "PRINTLN.INC"
%include "READLN.INC"
%include "LOADF.INC"
;Set up the interrupt vectors
;Interrupt 0x20 offset
start:
mov ax, int0x20
mov [0x80], ax
;Interrupt 0x21 offset
mov ax, int0x21
mov [0x84], ax
;Interrupt 0x22 offset
mov ax, int0x22
mov [0x88], ax
;Segments
mov ax, 0x0
mov [0x82], ax
mov [0x86], ax
mov [0x8a], ax
;Store the boot drive number as the current drive and set the current
;drive letter
mov [curdrive], dl
call setcurdriveletter
;Print a welcome message
mov si, welcomemsg
mov ah, 0x2
int 0x21
shell:
;Re-set the stack
cli
mov sp, 0x0
sti
;Prompt for and read a command
;Print the current drive letter
mov si, curdriveletter
mov ah, 0x0
int 0x21
;Print a prompt
mov si, prompt
mov ah, 0x0
int 0x21
;Read
mov di, input
mov al, 0x4c
mov ah, 0x3
int 0x21
;Check for an empty command
cmp byte [input], 0x0
jz shell
;Set SI at the command
;Set SI at input
mov si, input
;Ignore leading spaces
call ignoreleading
;Check for a current drive change command
cmp byte [si + 0x1], ":"
jne extract
cmp byte [si + 0x2], 0x0
je changecurdrive
cmp byte [si + 0x2], 0x20
je changecurdrive
;Extract the specification of the program file
extract:
;Set DI at program
mov di, program
;Initialise program with spaces
mov cx, 0xe
mov al, 0x20
rep stosb
sub di, 0xe
;Set the length counter
mov bl, 0xa
;Load a character
specloop:
lodsb
;Check for the string end
cmp al, 0x0
je addext
;Check for a space
cmp al, 0x20
je addext
;Check for the length limit
cmp bl, 0x0
je cmderror
;Store the character
stosb
;Decrease the counter
dec bl
;Extract the next character
jmp specloop
;Store the start of the command tail in the stack
addext:
push si
;Add extension to the specification
mov si, extension
mov cx, 0x5
rep movsb
;Load and execute the program
;Load the program
mov bx, 0x3000
mov si, program
mov ah, 0x2
int 0x22
;Check for errors
cmp al, 0x0
jne shell
;Pass the current drive and command tail to the program
mov dl, [curdrive]
pop si
call ignoreleading
;Execute the program
jmp 0x3000
;Print a command error message and return to the shell
cmderror:
mov si, cmderrormsg
mov ah, 0x2
int 0x21
jmp shell
;Change the current drive
;Get the BIOS equipment list
changecurdrive:
int 0x11
;Get the number of floppy drives
times 0x6 shr ax, 0x1
and ax, 0x3
inc ax
;Set the loop and drive letter counters and the drive letter and number
mov cx, ax
mov di, driveletters
mov al, [si]
mov dl, 0x0
;Check which drive to change to
checkdrive:
cmp al, [di]
je contchdrive
inc di
cmp al, [di]
je contchdrive
inc di
inc dl
loop checkdrive
;Print a drive error message and return to the shell
mov si, driverrormsg
mov ah, 0x2
int 0x21
jmp shell
;Change the drive
contchdrive:
mov [curdrive], dl
call setcurdriveletter
jmp shell
;Welcome message
welcomemsg db 0xd, 0xa, "Welcome to EttinOS!", 0xd, 0xa, 0x0
;Drive stuff
curdrive db 0x0
driveletters db "AaBbCcDd"
;Shell
curdriveletter db "?:", 0x0
prompt db "> ", 0x0
input times 0x4c db 0x0
program times 0xf db 0x0
extension db ".BIN", 0x0
cmderrormsg db "File or command not found", 0x0
driverrormsg db "Drive not found", 0x0
;Disk parameters
drive db 0x0
sectorsize dw 0x0 ;bytes
clustersize db 0x0 ;sectors
reservedsectors dw 0x0
fats db 0x0
rootentries dw 0x0
sectorsperfat dw 0x0
sectorspertrack dw 0x0
heads dw 0x0
rootstart dw 0x0
rootsectors dw 0x0
datastart dw 0x0
;***
;Set the drive letter
setcurdriveletter:
;Set the drive number and letter counters
mov dh, 0x0
mov si, driveletters
;Check the drive number
.checkdrive:
cmp dl, dh
je .set
add si, 0x2
inc dh
jmp .checkdrive
;Set the drive letter
.set:
mov al, [si]
mov byte [curdriveletter], al
;Return
ret
;***
;Ignore leading spaces in the command and its tail
ignoreleading:
;Check for a space
lodsb
cmp al, 0x20
je ignoreleading
;Set SI to the first non-space character
dec si
;Return
ret
;***
;Print a CRLF
printcrlf:
;Store SI in the stack
push si
;Print the CRLF
mov si, .crlf
mov ah, 0x0
int 0x21
;Load SI from the stack
pop si
;Return
ret
;Data
.crlf db 0xd, 0xa, 0x0
;***
;File system buffer
buffer: