Write loadf and rewrite the shell to load external programs with it instead of internal calls.
This commit is contained in:
parent
59d9c7e89d
commit
2e003c3198
|
@ -0,0 +1,23 @@
|
||||||
|
MIT License
|
||||||
|
===========
|
||||||
|
|
||||||
|
Copyright (c) 2021 CrazyEttin
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,61 @@
|
||||||
|
EttinOS
|
||||||
|
=======
|
||||||
|
|
||||||
|
EttinOS is a minimalist 16-bit DOS-like hobbyist operating system for
|
||||||
|
the IBM PC and compatible computers. Its git repository can be found at
|
||||||
|
https://ahti.space/git/crazyettin/EttinOS.
|
||||||
|
|
||||||
|
System requirements
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
* An Intel 8086 or compatible CPU
|
||||||
|
* BIOS, or UEFI in legacy mode
|
||||||
|
* 64 KiB of RAM
|
||||||
|
* A floppy disk drive
|
||||||
|
|
||||||
|
Building
|
||||||
|
--------
|
||||||
|
|
||||||
|
Build dependencies:
|
||||||
|
* A Unix-like operating system
|
||||||
|
* bash
|
||||||
|
* coreutils
|
||||||
|
* dosfstools
|
||||||
|
* mtools
|
||||||
|
* nasm
|
||||||
|
|
||||||
|
Running make.sh will build EttinOS and create a bootable 360 KiB 5.25"
|
||||||
|
floppy disk image named EttinOS.img. To get a 1.44 MB 3.5" one instead
|
||||||
|
use the argument -1440. If you want to use another floppy disk format
|
||||||
|
you will have to adjust the bootloader disk description tables and
|
||||||
|
install the system manually. Hard disk drives are not supported.
|
||||||
|
|
||||||
|
Input
|
||||||
|
-----
|
||||||
|
|
||||||
|
The EttinOS input system is inspired by typewriters. Typing a character
|
||||||
|
overwrites the cursor location and the erase (=tab) key erases it. The
|
||||||
|
space and backspace keys move the cursor.
|
||||||
|
|
||||||
|
Programming
|
||||||
|
-----------
|
||||||
|
|
||||||
|
EttinOS has a flat address space of 64 KiB with the data, stack, and
|
||||||
|
extra segments set at the beginning of the RAM. Programs are loaded at
|
||||||
|
address 0x2000.
|
||||||
|
|
||||||
|
System calls:
|
||||||
|
* Interrupt 0x20: Return to the shell.
|
||||||
|
* Interrupt 0x21: Input and output:
|
||||||
|
* AH = 0x0: Print a string ending in a null from SI.
|
||||||
|
* AH = 0x1: Read a string ending in a null of at most AL
|
||||||
|
characters to DI until a return.
|
||||||
|
* AH = 0x2: Print a string ending in a null from SI followed by a
|
||||||
|
CRLF.
|
||||||
|
* AH = 0x3: Read a string ending in a null of at most AL
|
||||||
|
characters to DI until a return and print a CRLF.
|
||||||
|
* Interrupt 0x22: Disk operations:
|
||||||
|
* AH = 0x0: Load a file named in SI as a string ending in a null
|
||||||
|
to the offset BX and set AL to 0x0 if the load was
|
||||||
|
succesfull and 0x1 if there was an error.
|
||||||
|
* AH = 0x1: Save a file (under construction).
|
6
make.sh
6
make.sh
|
@ -7,11 +7,12 @@ then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd src/
|
cd src/
|
||||||
if [ "$1" == "-F1440" ]
|
if [ "$1" == "-1440" ]
|
||||||
then nasm BOOT.ASM -d F1440 -f bin -o ../bin/BOOT.BIN
|
then nasm BOOT.ASM -d F1440 -f bin -o ../bin/BOOT.BIN
|
||||||
else nasm BOOT.ASM -f bin -o ../bin/BOOT.BIN
|
else nasm BOOT.ASM -f bin -o ../bin/BOOT.BIN
|
||||||
fi
|
fi
|
||||||
nasm SYSTEM.ASM -f bin -o ../bin/SYSTEM.BIN
|
nasm SYSTEM.ASM -f bin -o ../bin/SYSTEM.BIN
|
||||||
|
nasm HELLO.ASM -f bin -o ../bin/HELLO.BIN
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
if [ "$1" == "-1440" ]
|
if [ "$1" == "-1440" ]
|
||||||
|
@ -20,3 +21,6 @@ if [ "$1" == "-1440" ]
|
||||||
fi
|
fi
|
||||||
dd if=bin/BOOT.BIN of=EttinOS.img conv=notrunc bs=512 count=1
|
dd if=bin/BOOT.BIN of=EttinOS.img conv=notrunc bs=512 count=1
|
||||||
mcopy -i EttinOS.img bin/SYSTEM.BIN ::
|
mcopy -i EttinOS.img bin/SYSTEM.BIN ::
|
||||||
|
mcopy -i EttinOS.img bin/HELLO.BIN ::
|
||||||
|
mcopy -i EttinOS.img README.MD ::
|
||||||
|
mcopy -i EttinOS.img LICENSE.MD ::
|
||||||
|
|
16
src/BOOT.ASM
16
src/BOOT.ASM
|
@ -63,8 +63,8 @@ cli
|
||||||
mov sp, stack
|
mov sp, stack
|
||||||
add sp, 0x100
|
add sp, 0x100
|
||||||
sti
|
sti
|
||||||
;Store the boot device number
|
;Store the boot drive number
|
||||||
mov [bootdev], dl
|
mov [bootdrive], dl
|
||||||
|
|
||||||
;Load the root
|
;Load the root
|
||||||
;Set the source
|
;Set the source
|
||||||
|
@ -90,7 +90,7 @@ push ax
|
||||||
mov ah, 0x2
|
mov ah, 0x2
|
||||||
int 0x13
|
int 0x13
|
||||||
|
|
||||||
;Search the root for the system
|
;Search the root for the system entry
|
||||||
;Set DI to the root
|
;Set DI to the root
|
||||||
mov di, 0x7f00
|
mov di, 0x7f00
|
||||||
;Initialise the search loop
|
;Initialise the search loop
|
||||||
|
@ -99,11 +99,11 @@ mov ax, 0x0
|
||||||
search:
|
search:
|
||||||
;Store CX in the stack
|
;Store CX in the stack
|
||||||
push cx
|
push cx
|
||||||
;Check for the system FAT
|
;Check for the system entry
|
||||||
mov si, sysfile
|
mov si, sysfile
|
||||||
mov cx, 0xb
|
mov cx, 0xb
|
||||||
rep cmpsb
|
rep cmpsb
|
||||||
je loadfat
|
je loadentry
|
||||||
;Set DI to the next entry
|
;Set DI to the next entry
|
||||||
add ax, 0x20
|
add ax, 0x20
|
||||||
mov di, 0x7f00
|
mov di, 0x7f00
|
||||||
|
@ -127,7 +127,7 @@ int 0x10
|
||||||
jmp printerror
|
jmp printerror
|
||||||
|
|
||||||
;Load the system entry
|
;Load the system entry
|
||||||
loadfat:
|
loadentry:
|
||||||
;Load CX from the stack
|
;Load CX from the stack
|
||||||
pop cx
|
pop cx
|
||||||
;Store the first cluster
|
;Store the first cluster
|
||||||
|
@ -203,7 +203,7 @@ boot:
|
||||||
jmp 0x0:0x500
|
jmp 0x0:0x500
|
||||||
|
|
||||||
;Data
|
;Data
|
||||||
bootdev db 0x0
|
bootdrive db 0x0
|
||||||
sysfile db "SYSTEM BIN"
|
sysfile db "SYSTEM BIN"
|
||||||
errormsg db "System not found", 0xd, 0xa, 0x0
|
errormsg db "System not found", 0xd, 0xa, 0x0
|
||||||
cluster dw 0x0
|
cluster dw 0x0
|
||||||
|
@ -227,7 +227,7 @@ mov dh, dl
|
||||||
mov ch, al
|
mov ch, al
|
||||||
pop bx
|
pop bx
|
||||||
pop ax
|
pop ax
|
||||||
mov dl, byte [bootdev]
|
mov dl, byte [bootdrive]
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;Pad the binary to a full sector and make the disk bootable
|
;Pad the binary to a full sector and make the disk bootable
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
;Compares strings from SI and DI until a null and either sets the carry flag if they are equal or clears it if not.
|
|
||||||
|
|
||||||
cmpstr:
|
|
||||||
|
|
||||||
;Store the initial registers in the stack
|
|
||||||
push ax
|
|
||||||
push bx
|
|
||||||
|
|
||||||
;Compare the strings
|
|
||||||
.loop:
|
|
||||||
;Load the current characters
|
|
||||||
mov al, [si]
|
|
||||||
mov bl, [di]
|
|
||||||
;Compare the characters
|
|
||||||
cmp al, bl
|
|
||||||
;Check for difference
|
|
||||||
jne .neq
|
|
||||||
;Check for the string end
|
|
||||||
cmp al, 0x0
|
|
||||||
je .eq
|
|
||||||
;Repeat for the next characters
|
|
||||||
inc si
|
|
||||||
inc di
|
|
||||||
jmp .loop
|
|
||||||
|
|
||||||
;Set the carry flag
|
|
||||||
.eq:
|
|
||||||
stc
|
|
||||||
jmp .done
|
|
||||||
|
|
||||||
;Clear the carry flag
|
|
||||||
.neq:
|
|
||||||
clc
|
|
||||||
|
|
||||||
.done:
|
|
||||||
|
|
||||||
;Load the initial registers from the stack
|
|
||||||
pop bx
|
|
||||||
pop ax
|
|
||||||
|
|
||||||
ret
|
|
21
src/ECHO.INC
21
src/ECHO.INC
|
@ -1,21 +0,0 @@
|
||||||
;Reads a string to the buffer and prints it.
|
|
||||||
|
|
||||||
echo:
|
|
||||||
|
|
||||||
;Read a string
|
|
||||||
mov di, buffer
|
|
||||||
mov al, 0xff
|
|
||||||
mov ah, 0x3
|
|
||||||
int 0x21
|
|
||||||
|
|
||||||
;Check for an empty string
|
|
||||||
cmp byte [buffer], 0x0
|
|
||||||
je .done
|
|
||||||
|
|
||||||
;Print the string
|
|
||||||
mov si, buffer
|
|
||||||
mov ah, 0x2
|
|
||||||
int 0x21
|
|
||||||
|
|
||||||
.done:
|
|
||||||
ret
|
|
124
src/FILEIFY.INC
124
src/FILEIFY.INC
|
@ -1,124 +0,0 @@
|
||||||
;Reads a string, checks if it is a valid 8.3 file name, converts it into FAT formatting, and prints it.
|
|
||||||
|
|
||||||
fileify:
|
|
||||||
|
|
||||||
;Read a string
|
|
||||||
mov di, buffer
|
|
||||||
mov al, 0xff
|
|
||||||
mov ah, 0x3
|
|
||||||
int 0x21
|
|
||||||
|
|
||||||
;Set SI and DI
|
|
||||||
mov si, buffer
|
|
||||||
mov di, .file
|
|
||||||
|
|
||||||
;Initialise the name with spaces
|
|
||||||
mov cx, 0xb
|
|
||||||
mov al, 0x20
|
|
||||||
rep stosb
|
|
||||||
sub di, 0xb
|
|
||||||
|
|
||||||
;Initialise the length counter for the main part of the name
|
|
||||||
mov bl, 0x8
|
|
||||||
|
|
||||||
.nameloop:
|
|
||||||
;Load a character
|
|
||||||
lodsb
|
|
||||||
;Check for a period
|
|
||||||
cmp al, 0x2e
|
|
||||||
je .initext
|
|
||||||
;Check for everything else and convert to upper case
|
|
||||||
call .checkconv
|
|
||||||
jmp .nameloop
|
|
||||||
|
|
||||||
.initext:
|
|
||||||
;Set DI and initialise the length counter for the extension
|
|
||||||
mov bl, 0x3
|
|
||||||
mov di, .file+0x8
|
|
||||||
|
|
||||||
.extloop:
|
|
||||||
;Load a character
|
|
||||||
lodsb
|
|
||||||
;Check for a period
|
|
||||||
push ax
|
|
||||||
cmp al, 0x2e
|
|
||||||
je .error
|
|
||||||
pop ax
|
|
||||||
;Check for everything else and convert to upper case
|
|
||||||
call .checkconv
|
|
||||||
jmp .extloop
|
|
||||||
|
|
||||||
.error:
|
|
||||||
pop ax
|
|
||||||
mov si, .errormsg
|
|
||||||
mov ah, 0x2
|
|
||||||
int 0x21
|
|
||||||
jmp .done
|
|
||||||
|
|
||||||
.print:
|
|
||||||
pop ax
|
|
||||||
mov si, .file
|
|
||||||
mov ah, 0x2
|
|
||||||
int 0x21
|
|
||||||
|
|
||||||
.done:
|
|
||||||
ret
|
|
||||||
|
|
||||||
.file times 0xc db 0x0
|
|
||||||
|
|
||||||
.errormsg db "Invalid file name", 0x0
|
|
||||||
|
|
||||||
.checkconv:
|
|
||||||
|
|
||||||
;Check for the string end
|
|
||||||
cmp al, 0x0
|
|
||||||
je .print
|
|
||||||
|
|
||||||
;Check for the length limit
|
|
||||||
cmp bl, 0x0
|
|
||||||
je .error
|
|
||||||
|
|
||||||
;Check for invalid characters
|
|
||||||
cmp al, 0x22
|
|
||||||
je .error
|
|
||||||
cmp al, 0x2a
|
|
||||||
jl .contcheck1
|
|
||||||
cmp al, 0x2c
|
|
||||||
jg .contcheck1
|
|
||||||
jmp .error
|
|
||||||
.contcheck1:
|
|
||||||
cmp al, 0x2f
|
|
||||||
je .error
|
|
||||||
cmp al, 0x3a
|
|
||||||
jl .contcheck2
|
|
||||||
cmp al, 0x3f
|
|
||||||
jg .contcheck2
|
|
||||||
jmp .error
|
|
||||||
.contcheck2:
|
|
||||||
cmp al, 0x5b
|
|
||||||
jl .contcheck3
|
|
||||||
cmp al, 0x5d
|
|
||||||
jg .contcheck3
|
|
||||||
jmp .error
|
|
||||||
.contcheck3:
|
|
||||||
cmp al, 0x7c
|
|
||||||
je .error
|
|
||||||
|
|
||||||
;Find and convert lower case letters to upper case
|
|
||||||
;Check for lower case
|
|
||||||
cmp al, 0x61
|
|
||||||
jl .storech
|
|
||||||
cmp al, 0x7a
|
|
||||||
jg .storech
|
|
||||||
;Convert lower to upper case
|
|
||||||
sub al, 0x20
|
|
||||||
|
|
||||||
.storech:
|
|
||||||
|
|
||||||
;Store the character
|
|
||||||
stosb
|
|
||||||
|
|
||||||
;Increase the counter
|
|
||||||
dec bl
|
|
||||||
|
|
||||||
ret
|
|
|
@ -1,11 +1,11 @@
|
||||||
|
CPU 8086
|
||||||
|
ORG 0x2000
|
||||||
|
|
||||||
;Prints a hello world.
|
;Prints a hello world.
|
||||||
|
|
||||||
hello:
|
|
||||||
|
|
||||||
mov si, .hello
|
mov si, .hello
|
||||||
mov ah, 0x2
|
mov ah, 0x2
|
||||||
int 0x21
|
int 0x21
|
||||||
|
int 0x20
|
||||||
|
|
||||||
ret
|
;Data
|
||||||
|
|
||||||
.hello db "Hello world!", 0x0
|
.hello db "Hello world!", 0x0
|
11
src/HELP.INC
11
src/HELP.INC
|
@ -1,11 +0,0 @@
|
||||||
;Prints help.
|
|
||||||
|
|
||||||
help:
|
|
||||||
|
|
||||||
mov si, .help
|
|
||||||
mov ah, 0x2
|
|
||||||
int 0x21
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
.help db "Input:", 0xd, 0xa, " * Typing a character overwrites the cursor location.", 0xd, 0xa, " * The erase (=tab) key erases the cursor location.", 0xd, 0xa, " * The space and backspace keys move the cursor.", 0xd, 0xa, "Commands:", 0xd, 0xa, " * echo: echoes its input.", 0xd, 0xa, " * fileify: prints its input in FAT format if it is a valid filename.", 0xd, 0xa, " * hello: a hello world program.", 0xd, 0xa, " * help: you are reading it.", 0xd, 0xa, " * keycode: echoes the BIOS code of a key.", 0x0
|
|
|
@ -1,89 +0,0 @@
|
||||||
;Reads a keypress and prints its BIOS keycode.
|
|
||||||
|
|
||||||
keycode:
|
|
||||||
|
|
||||||
;Read a keypress
|
|
||||||
mov ah, 0x0
|
|
||||||
int 0x16
|
|
||||||
|
|
||||||
;Store the keycode
|
|
||||||
mov [.scan], ah
|
|
||||||
mov [.ascii], al
|
|
||||||
|
|
||||||
;Print the prefix
|
|
||||||
mov si, .prefix
|
|
||||||
mov ah, 0x0
|
|
||||||
int 0x21
|
|
||||||
|
|
||||||
;Convert the scancode to a hex string
|
|
||||||
mov al, [.scan]
|
|
||||||
mov di, .keycode
|
|
||||||
call .byte2hex
|
|
||||||
|
|
||||||
;Convert the ascii value to a hex string
|
|
||||||
mov al, [.ascii]
|
|
||||||
mov di, .keycode
|
|
||||||
add di, 0x2
|
|
||||||
call .byte2hex
|
|
||||||
|
|
||||||
;Print the keycode
|
|
||||||
mov si, .keycode
|
|
||||||
mov ah, 0x2
|
|
||||||
int 0x21
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
.prefix db "0x", 0x0
|
|
||||||
|
|
||||||
.scan db 0x0
|
|
||||||
.ascii db 0x0
|
|
||||||
|
|
||||||
.keycode times 0x5 db 0x0
|
|
||||||
|
|
||||||
.byte2hex:
|
|
||||||
|
|
||||||
;Store the initial registers in the stack
|
|
||||||
push si
|
|
||||||
push ax
|
|
||||||
push bx
|
|
||||||
push cx
|
|
||||||
|
|
||||||
;Move the byte to AH
|
|
||||||
mov ah, al
|
|
||||||
|
|
||||||
;Set a key for the hex digits
|
|
||||||
mov si, .key
|
|
||||||
|
|
||||||
;Set a counter for the two hex digits
|
|
||||||
mov cx, 0x2
|
|
||||||
|
|
||||||
.loop:
|
|
||||||
|
|
||||||
;Read a nibble
|
|
||||||
rol ax, 0x1
|
|
||||||
rol ax, 0x1
|
|
||||||
rol ax, 0x1
|
|
||||||
rol ax, 0x1
|
|
||||||
mov bx, ax
|
|
||||||
|
|
||||||
;Convert the nibble to a hex digit
|
|
||||||
and bx, 0xf
|
|
||||||
mov bl, [si + bx]
|
|
||||||
|
|
||||||
;Store the hex digit
|
|
||||||
mov [di], bl
|
|
||||||
|
|
||||||
;Repeat
|
|
||||||
inc di
|
|
||||||
dec cx
|
|
||||||
jnz .loop
|
|
||||||
|
|
||||||
;Load the initial registers from the stack
|
|
||||||
pop cx
|
|
||||||
pop bx
|
|
||||||
pop ax
|
|
||||||
pop si
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
.key db "0123456789abcdef"
|
|
|
@ -0,0 +1,309 @@
|
||||||
|
;Load a file named in SI as a string ending in a null to the offset BX and set AL to 0x0 if the load was succesful and 0x1 if there was an error.
|
||||||
|
|
||||||
|
loadf:
|
||||||
|
|
||||||
|
;Store the initial registers in the stack
|
||||||
|
push ax
|
||||||
|
push bx
|
||||||
|
push cx
|
||||||
|
push dx
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
|
||||||
|
;Store the offset
|
||||||
|
mov word [.pointer], bx
|
||||||
|
|
||||||
|
;Set DI at .file and initialise it with spaces
|
||||||
|
mov di, .file
|
||||||
|
mov cx, 0xb
|
||||||
|
mov al, 0x20
|
||||||
|
rep stosb
|
||||||
|
sub di, 0xb
|
||||||
|
|
||||||
|
;Convert .file into FAT formatting
|
||||||
|
|
||||||
|
;Initialise the length counter for the main part of the name
|
||||||
|
mov bl, 0x8
|
||||||
|
|
||||||
|
;Convert the main part of the file name
|
||||||
|
.nameloop:
|
||||||
|
;Load a character
|
||||||
|
lodsb
|
||||||
|
;Check for a period
|
||||||
|
cmp al, 0x2e
|
||||||
|
je .initext
|
||||||
|
;Check for everything else and convert to upper case
|
||||||
|
call .checkconv
|
||||||
|
jmp .nameloop
|
||||||
|
|
||||||
|
;Convert the extension
|
||||||
|
.initext:
|
||||||
|
;Set DI and initialise the length counter for the extension
|
||||||
|
mov bl, 0x3
|
||||||
|
mov di, .file+0x8
|
||||||
|
.extloop:
|
||||||
|
;Load a character
|
||||||
|
lodsb
|
||||||
|
;Check for a period
|
||||||
|
push ax
|
||||||
|
cmp al, 0x2e
|
||||||
|
je .error
|
||||||
|
pop ax
|
||||||
|
;Check for everything else and convert to upper case
|
||||||
|
call .checkconv
|
||||||
|
jmp .extloop
|
||||||
|
|
||||||
|
;Set the carry flag and print an error message if the file name is invalid
|
||||||
|
.error:
|
||||||
|
pop ax
|
||||||
|
stc
|
||||||
|
mov si, .errormsg
|
||||||
|
mov ah, 0x2
|
||||||
|
int 0x21
|
||||||
|
jmp .done
|
||||||
|
|
||||||
|
;Find and load the file
|
||||||
|
|
||||||
|
.load:
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
;Load the root
|
||||||
|
;Set the source
|
||||||
|
mov ah, 0x0
|
||||||
|
mov al, [.fats]
|
||||||
|
mul word [.sectorsperfat]
|
||||||
|
add ax, [.bootsectors]
|
||||||
|
push ax
|
||||||
|
call .calcsource
|
||||||
|
;Set the destination
|
||||||
|
mov si, stack
|
||||||
|
add si, 0x100
|
||||||
|
mov bx, si
|
||||||
|
;Set the size
|
||||||
|
push dx
|
||||||
|
mov ax, [.rootentries]
|
||||||
|
mov dx, 0x20
|
||||||
|
mul dx
|
||||||
|
mov dx, 0x0
|
||||||
|
div word [.sectorsize]
|
||||||
|
pop dx
|
||||||
|
push ax
|
||||||
|
;Load
|
||||||
|
mov ah, 0x2
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
;Search the root for the file entry
|
||||||
|
;Set DI to the root
|
||||||
|
mov di, stack
|
||||||
|
add di, 0x100
|
||||||
|
;Initialise the search loop
|
||||||
|
mov cx, word [.rootentries]
|
||||||
|
mov ax, 0x0
|
||||||
|
.search:
|
||||||
|
;Store CX in the stack
|
||||||
|
push cx
|
||||||
|
;Check for the file entry
|
||||||
|
mov si, .file
|
||||||
|
mov cx, 0xb
|
||||||
|
rep cmpsb
|
||||||
|
je .loadentry
|
||||||
|
;Set DI to the next entry
|
||||||
|
add ax, 0x20
|
||||||
|
mov di, stack
|
||||||
|
add di, 0x100
|
||||||
|
add di, ax
|
||||||
|
;Load CX from the stack
|
||||||
|
pop cx
|
||||||
|
loop .search
|
||||||
|
|
||||||
|
;Set the carry flag and print an error message if the file is not found
|
||||||
|
stc
|
||||||
|
mov si, .errormsg
|
||||||
|
mov ah, 0x2
|
||||||
|
int 0x21
|
||||||
|
jmp .clearstack
|
||||||
|
|
||||||
|
;Load the file entry
|
||||||
|
.loadentry:
|
||||||
|
;Load CX from the stack
|
||||||
|
pop cx
|
||||||
|
;Store the first cluster
|
||||||
|
mov ax, word [es:di+0xf]
|
||||||
|
mov word [.cluster], ax
|
||||||
|
;Set the source
|
||||||
|
mov ax, 0x1
|
||||||
|
call .calcsource
|
||||||
|
;Set the destination
|
||||||
|
mov di, stack
|
||||||
|
add di, 0x100
|
||||||
|
mov bx, di
|
||||||
|
;Set the size
|
||||||
|
mov ax, [.sectorsperfat]
|
||||||
|
;Load
|
||||||
|
mov ah, 0x2
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
;Load the file
|
||||||
|
|
||||||
|
;Load a cluster
|
||||||
|
.loadcluster:
|
||||||
|
;Set the source
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
mov ax, word [.cluster]
|
||||||
|
sub ax, 0x2
|
||||||
|
mul byte [.clustersize]
|
||||||
|
add ax, bx
|
||||||
|
add ax, cx
|
||||||
|
push bx
|
||||||
|
push cx
|
||||||
|
call .calcsource
|
||||||
|
;Set the destination
|
||||||
|
mov bx, word [.pointer]
|
||||||
|
;Set the size
|
||||||
|
;mov al, 0x1
|
||||||
|
mov al, [.clustersize]
|
||||||
|
;Load
|
||||||
|
mov ah, 0x2
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
;Calculate the next cluster
|
||||||
|
mov ax, [.cluster]
|
||||||
|
mov dx, 0x0
|
||||||
|
mov bx, 0x3
|
||||||
|
mul bx
|
||||||
|
mov bx, 0x2
|
||||||
|
div bx
|
||||||
|
mov si, stack
|
||||||
|
add si, 0x100
|
||||||
|
add si, ax
|
||||||
|
mov ax, word [ds:si]
|
||||||
|
or dx, dx
|
||||||
|
jz .even
|
||||||
|
shr ax, 1
|
||||||
|
shr ax, 1
|
||||||
|
shr ax, 1
|
||||||
|
shr ax, 1
|
||||||
|
jmp .contcalc
|
||||||
|
.even:
|
||||||
|
and ax, 0xfff
|
||||||
|
.contcalc:
|
||||||
|
mov word [.cluster], ax
|
||||||
|
cmp ax, 0xff8
|
||||||
|
jge .clearcarry
|
||||||
|
mov ax, [.sectorsize]
|
||||||
|
mul word [.clustersize]
|
||||||
|
add word [.pointer], ax
|
||||||
|
jmp .loadcluster
|
||||||
|
|
||||||
|
;Clear the carry flag if the load was succesful
|
||||||
|
.clearcarry:
|
||||||
|
clc
|
||||||
|
|
||||||
|
;Clear left over values from the stack
|
||||||
|
.clearstack:
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
|
||||||
|
.done:
|
||||||
|
|
||||||
|
;Load the initial registers from the stack
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop dx
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
;Set AL to 0x1 if there was an error and to 0x0 otherwise
|
||||||
|
jc .setal
|
||||||
|
mov al, 0x0
|
||||||
|
iret
|
||||||
|
.setal:
|
||||||
|
mov al, 0x1
|
||||||
|
iret
|
||||||
|
|
||||||
|
;Data
|
||||||
|
.file times 0xb db 0x20
|
||||||
|
.errormsg db "File not found", 0x0
|
||||||
|
.cluster dw 0x0
|
||||||
|
.pointer dw 0x0
|
||||||
|
|
||||||
|
;These are temporary until i write something to load them from the disk itself
|
||||||
|
.bootdrive db 0x0
|
||||||
|
.sectorsize dw 0x200 ;bytes
|
||||||
|
.clustersize db 0x2 ;sectors
|
||||||
|
.bootsectors dw 0x1
|
||||||
|
.fats db 0x2
|
||||||
|
.rootentries dw 0x70
|
||||||
|
.sectorsperfat dw 0x2
|
||||||
|
.sectorspertrack dw 0x9
|
||||||
|
.sides dw 0x2
|
||||||
|
|
||||||
|
;Check the file name and convert to upper case
|
||||||
|
.checkconv:
|
||||||
|
;Check for the string end
|
||||||
|
cmp al, 0x0
|
||||||
|
je .load
|
||||||
|
;Check for the length limit
|
||||||
|
cmp bl, 0x0
|
||||||
|
je .error
|
||||||
|
;Check for invalid characters
|
||||||
|
cmp al, 0x22
|
||||||
|
je .error
|
||||||
|
cmp al, 0x2a
|
||||||
|
jl .contcheck1
|
||||||
|
cmp al, 0x2c
|
||||||
|
jg .contcheck1
|
||||||
|
jmp .error
|
||||||
|
.contcheck1:
|
||||||
|
cmp al, 0x2f
|
||||||
|
je .error
|
||||||
|
cmp al, 0x3a
|
||||||
|
jl .contcheck2
|
||||||
|
cmp al, 0x3f
|
||||||
|
jg .contcheck2
|
||||||
|
jmp .error
|
||||||
|
.contcheck2:
|
||||||
|
cmp al, 0x5b
|
||||||
|
jl .contcheck3
|
||||||
|
cmp al, 0x5d
|
||||||
|
jg .contcheck3
|
||||||
|
jmp .error
|
||||||
|
.contcheck3:
|
||||||
|
cmp al, 0x7c
|
||||||
|
je .error
|
||||||
|
;Check for lower case
|
||||||
|
cmp al, 0x61
|
||||||
|
jl .storech
|
||||||
|
cmp al, 0x7a
|
||||||
|
jg .storech
|
||||||
|
;Convert lower to upper case
|
||||||
|
sub al, 0x20
|
||||||
|
.storech:
|
||||||
|
;Store the character
|
||||||
|
stosb
|
||||||
|
;Increase the counter
|
||||||
|
dec bl
|
||||||
|
ret
|
||||||
|
|
||||||
|
;Calculate the source arguments for loading data from the disk
|
||||||
|
.calcsource:
|
||||||
|
push ax
|
||||||
|
push bx
|
||||||
|
mov bx, ax
|
||||||
|
mov dx, 0x0
|
||||||
|
div word [.sectorspertrack]
|
||||||
|
add dl, 0x1
|
||||||
|
mov cl, dl
|
||||||
|
mov ax, bx
|
||||||
|
mov dx, 0x0
|
||||||
|
div word [.sectorspertrack]
|
||||||
|
mov dx, 0x0
|
||||||
|
div word [.sides]
|
||||||
|
mov dh, dl
|
||||||
|
mov ch, al
|
||||||
|
pop bx
|
||||||
|
pop ax
|
||||||
|
mov dl, byte [.bootdrive]
|
||||||
|
ret
|
|
@ -1,18 +0,0 @@
|
||||||
;Prints a newline
|
|
||||||
|
|
||||||
newline:
|
|
||||||
|
|
||||||
;Store the initial registers in the stack
|
|
||||||
push si
|
|
||||||
|
|
||||||
;Print the newline
|
|
||||||
mov si, .newline
|
|
||||||
mov ah, 0x0
|
|
||||||
int 0x21
|
|
||||||
|
|
||||||
;Load the initial registers from the stack
|
|
||||||
pop si
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
.newline db 0xd, 0xa, 0x0
|
|
|
@ -1,4 +1,4 @@
|
||||||
;Prints a string from SI until a null, followed by a newline.
|
;Print a string ending in a null from SI followed by a CRLF.
|
||||||
|
|
||||||
println:
|
println:
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ println:
|
||||||
mov ah, 0x0
|
mov ah, 0x0
|
||||||
int 0x21
|
int 0x21
|
||||||
|
|
||||||
;Print a newline
|
;Print a CRLF
|
||||||
call newline
|
call printcrlf
|
||||||
|
|
||||||
iret
|
iret
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
;Prints a string from SI until a null.
|
;Print a string ending in a null from SI.
|
||||||
|
|
||||||
printstr:
|
printstr:
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
;Reads a string of at most AL characters to DI until a return and prints a newline.
|
;Read a string ending in null of at most AL characters to DI until a return and print a CRLF.
|
||||||
|
|
||||||
readln:
|
readln:
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ readln:
|
||||||
mov ah, 0x1
|
mov ah, 0x1
|
||||||
int 0x21
|
int 0x21
|
||||||
|
|
||||||
;Print a newline
|
;Print a CRLF
|
||||||
call newline
|
call printcrlf
|
||||||
|
|
||||||
iret
|
iret
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
;Reads a string of at most AL characters to DI until a return.
|
;Read a string ending in a null of at most AL characters to DI until a return.
|
||||||
|
|
||||||
readstr:
|
readstr:
|
||||||
|
|
||||||
|
|
139
src/SYSTEM.ASM
139
src/SYSTEM.ASM
|
@ -4,8 +4,10 @@ ORG 0x500
|
||||||
jmp start
|
jmp start
|
||||||
|
|
||||||
;Interrupt handler
|
;Interrupt handler
|
||||||
|
;Return to the shell
|
||||||
int0x20:
|
int0x20:
|
||||||
jmp shell
|
jmp shell
|
||||||
|
;Input and output
|
||||||
int0x21:
|
int0x21:
|
||||||
cmp ah, 0x0
|
cmp ah, 0x0
|
||||||
je printstr
|
je printstr
|
||||||
|
@ -16,8 +18,11 @@ je println
|
||||||
cmp ah, 0x3
|
cmp ah, 0x3
|
||||||
je readln
|
je readln
|
||||||
iret
|
iret
|
||||||
|
;Disk operations
|
||||||
int0x22:
|
int0x22:
|
||||||
;To do: loading and saving files
|
cmp ah, 0x0
|
||||||
|
je loadf
|
||||||
|
;To do: savef
|
||||||
iret
|
iret
|
||||||
|
|
||||||
;System calls
|
;System calls
|
||||||
|
@ -25,17 +30,7 @@ iret
|
||||||
%include "READSTR.INC"
|
%include "READSTR.INC"
|
||||||
%include "PRINTLN.INC"
|
%include "PRINTLN.INC"
|
||||||
%include "READLN.INC"
|
%include "READLN.INC"
|
||||||
|
%include "LOADF.INC"
|
||||||
;Internal calls
|
|
||||||
%include "CMPSTR.INC"
|
|
||||||
%include "NEWLINE.INC"
|
|
||||||
|
|
||||||
;Commands
|
|
||||||
%include "ECHO.INC"
|
|
||||||
%include "FILEIFY.INC"
|
|
||||||
%include "HELLO.INC"
|
|
||||||
%include "HELP.INC"
|
|
||||||
%include "KEYCODE.INC"
|
|
||||||
|
|
||||||
start:
|
start:
|
||||||
|
|
||||||
|
@ -46,20 +41,19 @@ mov sp, stack
|
||||||
add sp, 0x100
|
add sp, 0x100
|
||||||
sti
|
sti
|
||||||
;Set up the interrupt vectors
|
;Set up the interrupt vectors
|
||||||
;Interrupt 0x20
|
;Interrupt 0x20 offset
|
||||||
mov ax, int0x20
|
mov ax, int0x20
|
||||||
mov [0x80], ax
|
mov [0x80], ax
|
||||||
mov ax, 0x0
|
;Interrupt 0x21 offset
|
||||||
mov [0x82], ax
|
|
||||||
;Interrupt 0x21
|
|
||||||
mov ax, int0x21
|
mov ax, int0x21
|
||||||
mov [0x84], ax
|
mov [0x84], ax
|
||||||
mov ax, 0x0
|
;Interrupt 0x22 offset
|
||||||
mov [0x86], ax
|
|
||||||
;Interrupt 0x22
|
|
||||||
mov ax, int0x22
|
mov ax, int0x22
|
||||||
mov [0x88], ax
|
mov [0x88], ax
|
||||||
|
;Segments
|
||||||
mov ax, 0x0
|
mov ax, 0x0
|
||||||
|
mov [0x82], ax
|
||||||
|
mov [0x86], ax
|
||||||
mov [0x8a], ax
|
mov [0x8a], ax
|
||||||
|
|
||||||
;Print a welcome message
|
;Print a welcome message
|
||||||
|
@ -69,86 +63,65 @@ int 0x21
|
||||||
|
|
||||||
shell:
|
shell:
|
||||||
|
|
||||||
|
;Re-set up the stack
|
||||||
|
cli
|
||||||
|
mov sp, stack
|
||||||
|
add sp, 0x100
|
||||||
|
sti
|
||||||
|
|
||||||
;Prompt for and read a command
|
;Prompt for and read a command
|
||||||
;Print a prompt
|
;Print a prompt
|
||||||
mov si, prompt
|
mov si, prompt
|
||||||
mov ah, 0x0
|
mov ah, 0x0
|
||||||
int 0x21
|
int 0x21
|
||||||
;Read a command
|
;Read
|
||||||
mov di, buffer
|
mov di, input
|
||||||
mov al, 0xff
|
mov al, 0xff
|
||||||
mov ah, 0x3
|
mov ah, 0x3
|
||||||
int 0x21
|
int 0x21
|
||||||
|
|
||||||
;Identify and execute the command
|
;Load an execute the program
|
||||||
exec:
|
;Load
|
||||||
;Check for no command
|
mov bx, 0x2000
|
||||||
cmp byte [buffer], 0x0
|
mov si, input
|
||||||
je shell
|
mov ah, 0x0
|
||||||
.echo:
|
int 0x22
|
||||||
;Check
|
;Check for errors
|
||||||
mov si, buffer
|
cmp al, 0x1
|
||||||
mov di, cmd.echo
|
je error
|
||||||
call cmpstr
|
|
||||||
jnc .fileify
|
|
||||||
;Execute
|
;Execute
|
||||||
call echo
|
jmp 0x2000
|
||||||
jmp shell
|
|
||||||
.fileify:
|
;Print an error message and return to the shell
|
||||||
;Check
|
error:
|
||||||
mov si, buffer
|
mov bh, 0x0
|
||||||
mov di, cmd.fileify
|
mov ah, 0x3
|
||||||
call cmpstr
|
int 0x10
|
||||||
jnc .hello
|
dec dh
|
||||||
;Execute
|
mov ah, 0x2
|
||||||
call fileify
|
int 0x10
|
||||||
jmp shell
|
|
||||||
.hello:
|
|
||||||
;Check
|
|
||||||
mov si, buffer
|
|
||||||
mov di, cmd.hello
|
|
||||||
call cmpstr
|
|
||||||
jnc .help
|
|
||||||
;Execute
|
|
||||||
call hello
|
|
||||||
jmp shell
|
|
||||||
.help:
|
|
||||||
;Check
|
|
||||||
mov si, buffer
|
|
||||||
mov di, cmd.help
|
|
||||||
call cmpstr
|
|
||||||
jnc .keycode
|
|
||||||
;Execute
|
|
||||||
call help
|
|
||||||
jmp shell
|
|
||||||
.keycode:
|
|
||||||
;Check
|
|
||||||
mov si, buffer
|
|
||||||
mov di, cmd.keycode
|
|
||||||
call cmpstr
|
|
||||||
jnc .error
|
|
||||||
;Execute
|
|
||||||
call keycode
|
|
||||||
jmp shell
|
|
||||||
.error:
|
|
||||||
mov si, errormsg
|
mov si, errormsg
|
||||||
mov ah, 0x2
|
mov ah, 0x2
|
||||||
int 0x21
|
int 0x21
|
||||||
jmp shell
|
jmp shell
|
||||||
|
|
||||||
|
;Data
|
||||||
welcomemsg db 0xd, 0xa, "Welcome to EttinOS!", 0xd, 0xa, 0x0
|
welcomemsg db 0xd, 0xa, "Welcome to EttinOS!", 0xd, 0xa, 0x0
|
||||||
|
prompt db "> ", 0x0
|
||||||
|
errormsg db "Unknown command", 0x0
|
||||||
|
input times 0xff db 0x0
|
||||||
|
crlf db 0xd, 0xa, 0x0
|
||||||
|
|
||||||
prompt db "> ", 0x0
|
;Print a CRLF
|
||||||
|
printcrlf:
|
||||||
cmd:
|
;Store the initial registers in the stack
|
||||||
.echo db "echo", 0x0
|
push si
|
||||||
.fileify db "fileify", 0x0
|
;Print the CRLF
|
||||||
.hello db "hello", 0x0
|
mov si, crlf
|
||||||
.help db "help", 0x0
|
mov ah, 0x0
|
||||||
.keycode db "keycode", 0x0
|
int 0x21
|
||||||
|
;Load the initial registers from the stack
|
||||||
errormsg db "Unknown command", 0x0
|
pop si
|
||||||
|
ret
|
||||||
buffer times 0xff db 0x0
|
|
||||||
|
|
||||||
stack:
|
stack:
|
||||||
|
|
Loading…
Reference in New Issue