EttinOS/src/SYSTEM.ASM

269 lines
4.1 KiB
NASM

CPU 8086
ORG 0x500
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, 0x0
je loadf
;To do: savef
iret
;System calls
%include "PRINTSTR.INC"
%include "READSTR.INC"
%include "PRINTLN.INC"
%include "READLN.INC"
%include "LOADF.INC"
start:
;Set up the interrupt vectors
;Interrupt 0x20 offset
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 and set the drive letter
mov [drive], dl
call setdriveletter
;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 drive letter
mov si, driveletter
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
;Check for a drive change command
;Set SI at input
mov si, input
;Ignore leading spaces
call ignoreleading
;Check
cmp byte [si + 0x1], ":"
jne extract
cmp byte [si + 0x2], 0x0
je changedrive
cmp byte [si + 0x2], 0x20
je changedrive
;Extract the specification of the program file
extract:
;Set SI at input and DI at program
mov si, input
mov di, program
;Ignore leading spaces
call ignoreleading
;Initialise program with spaces
mov cx, 0xe
mov al, 0x20
rep stosb
sub di, 0xe
;Initialise the length counter
mov bl, 0xa
specloop:
;Load a character
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
jmp specloop
;Add extension to the name
addext:
push si
mov si, extension
mov cx, 0x5
rep movsb
;Load and execute the program
;Load
mov bx, 0x3000
mov si, program
mov ah, 0x0
int 0x22
;Check for errors
cmp al, 0x0
jne shell
;Pass the drive and command tail to the program
mov dl, [drive]
pop si
call ignoreleading
;Execute
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 drive
changedrive:
;Check which drive to change to
cmp byte [si], "a"
je cha
cmp byte [si], "A"
je cha
cmp byte [si], "b"
je chb
cmp byte [si], "B"
je chb
cmp byte [si], "c"
je chc
cmp byte [si], "C"
je chc
cmp byte [si], "d"
je chd
cmp byte [si], "D"
je chd
;Print a drive error message and return to the shell
mov si, driverrormsg
mov ah, 0x2
int 0x21
jmp shell
;Change
cha:
mov dl, 0x0
mov [drive], dl
call setdriveletter
jmp shell
chb:
mov dl, 0x1
mov [drive], dl
call setdriveletter
jmp shell
chc:
mov dl, 0x2
mov [drive], dl
call setdriveletter
jmp shell
chd:
mov dl, 0x3
mov [drive], dl
call setdriveletter
jmp shell
;Data
welcomemsg db 0xd, 0xa, "Welcome to EttinOS!", 0xd, 0xa, 0x0
drive db 0x0
driveletter 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
;Set the drive letter
setdriveletter:
;Check the drive number
cmp dl, 0x0
je .seta
cmp dl, 0x1
je .setb
cmp dl, 0x2
je .setc
cmp dl, 0x3
je .setd
ret
;Set
.seta:
mov byte [driveletter], "A"
ret
.setb:
mov byte [driveletter], "B"
ret
.setc:
mov byte [driveletter], "C"
ret
.setd:
mov byte [driveletter], "D"
ret
;Ignore leading spaces in the command and its tail
ignoreleading:
lodsb
cmp al, 0x20
je ignoreleading
dec si
ret
;Print a CRLF
printcrlf:
;Store the initial registers in the stack
push si
;Print the CRLF
mov si, .crlf
mov ah, 0x0
int 0x21
;Load the initial registers from the stack
pop si
ret
;Data
.crlf db 0xd, 0xa, 0x0
;File system buffer
buffer: