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: