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
|
||||
|
||||
cd src/
|
||||
if [ "$1" == "-F1440" ]
|
||||
if [ "$1" == "-1440" ]
|
||||
then nasm BOOT.ASM -d F1440 -f bin -o ../bin/BOOT.BIN
|
||||
else nasm BOOT.ASM -f bin -o ../bin/BOOT.BIN
|
||||
fi
|
||||
nasm SYSTEM.ASM -f bin -o ../bin/SYSTEM.BIN
|
||||
nasm HELLO.ASM -f bin -o ../bin/HELLO.BIN
|
||||
|
||||
cd ..
|
||||
if [ "$1" == "-1440" ]
|
||||
|
@ -20,3 +21,6 @@ if [ "$1" == "-1440" ]
|
|||
fi
|
||||
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/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
|
||||
add sp, 0x100
|
||||
sti
|
||||
;Store the boot device number
|
||||
mov [bootdev], dl
|
||||
;Store the boot drive number
|
||||
mov [bootdrive], dl
|
||||
|
||||
;Load the root
|
||||
;Set the source
|
||||
|
@ -90,7 +90,7 @@ push ax
|
|||
mov ah, 0x2
|
||||
int 0x13
|
||||
|
||||
;Search the root for the system
|
||||
;Search the root for the system entry
|
||||
;Set DI to the root
|
||||
mov di, 0x7f00
|
||||
;Initialise the search loop
|
||||
|
@ -99,11 +99,11 @@ mov ax, 0x0
|
|||
search:
|
||||
;Store CX in the stack
|
||||
push cx
|
||||
;Check for the system FAT
|
||||
;Check for the system entry
|
||||
mov si, sysfile
|
||||
mov cx, 0xb
|
||||
rep cmpsb
|
||||
je loadfat
|
||||
je loadentry
|
||||
;Set DI to the next entry
|
||||
add ax, 0x20
|
||||
mov di, 0x7f00
|
||||
|
@ -127,7 +127,7 @@ int 0x10
|
|||
jmp printerror
|
||||
|
||||
;Load the system entry
|
||||
loadfat:
|
||||
loadentry:
|
||||
;Load CX from the stack
|
||||
pop cx
|
||||
;Store the first cluster
|
||||
|
@ -203,7 +203,7 @@ boot:
|
|||
jmp 0x0:0x500
|
||||
|
||||
;Data
|
||||
bootdev db 0x0
|
||||
bootdrive db 0x0
|
||||
sysfile db "SYSTEM BIN"
|
||||
errormsg db "System not found", 0xd, 0xa, 0x0
|
||||
cluster dw 0x0
|
||||
|
@ -227,7 +227,7 @@ mov dh, dl
|
|||
mov ch, al
|
||||
pop bx
|
||||
pop ax
|
||||
mov dl, byte [bootdev]
|
||||
mov dl, byte [bootdrive]
|
||||
ret
|
||||
|
||||
;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.
|
||||
|
||||
hello:
|
||||
|
||||
mov si, .hello
|
||||
mov ah, 0x2
|
||||
int 0x21
|
||||
int 0x20
|
||||
|
||||
ret
|
||||
|
||||
;Data
|
||||
.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:
|
||||
|
||||
|
@ -6,7 +6,7 @@ println:
|
|||
mov ah, 0x0
|
||||
int 0x21
|
||||
|
||||
;Print a newline
|
||||
call newline
|
||||
;Print a CRLF
|
||||
call printcrlf
|
||||
|
||||
iret
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
;Prints a string from SI until a null.
|
||||
;Print a string ending in a null from SI.
|
||||
|
||||
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:
|
||||
|
||||
|
@ -6,7 +6,7 @@ readln:
|
|||
mov ah, 0x1
|
||||
int 0x21
|
||||
|
||||
;Print a newline
|
||||
call newline
|
||||
;Print a CRLF
|
||||
call printcrlf
|
||||
|
||||
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:
|
||||
|
||||
|
|
139
src/SYSTEM.ASM
139
src/SYSTEM.ASM
|
@ -4,8 +4,10 @@ ORG 0x500
|
|||
jmp start
|
||||
|
||||
;Interrupt handler
|
||||
;Return to the shell
|
||||
int0x20:
|
||||
jmp shell
|
||||
;Input and output
|
||||
int0x21:
|
||||
cmp ah, 0x0
|
||||
je printstr
|
||||
|
@ -16,8 +18,11 @@ je println
|
|||
cmp ah, 0x3
|
||||
je readln
|
||||
iret
|
||||
;Disk operations
|
||||
int0x22:
|
||||
;To do: loading and saving files
|
||||
cmp ah, 0x0
|
||||
je loadf
|
||||
;To do: savef
|
||||
iret
|
||||
|
||||
;System calls
|
||||
|
@ -25,17 +30,7 @@ iret
|
|||
%include "READSTR.INC"
|
||||
%include "PRINTLN.INC"
|
||||
%include "READLN.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"
|
||||
%include "LOADF.INC"
|
||||
|
||||
start:
|
||||
|
||||
|
@ -46,20 +41,19 @@ mov sp, stack
|
|||
add sp, 0x100
|
||||
sti
|
||||
;Set up the interrupt vectors
|
||||
;Interrupt 0x20
|
||||
;Interrupt 0x20 offset
|
||||
mov ax, int0x20
|
||||
mov [0x80], ax
|
||||
mov ax, 0x0
|
||||
mov [0x82], ax
|
||||
;Interrupt 0x21
|
||||
;Interrupt 0x21 offset
|
||||
mov ax, int0x21
|
||||
mov [0x84], ax
|
||||
mov ax, 0x0
|
||||
mov [0x86], ax
|
||||
;Interrupt 0x22
|
||||
;Interrupt 0x22 offset
|
||||
mov ax, int0x22
|
||||
mov [0x88], ax
|
||||
;Segments
|
||||
mov ax, 0x0
|
||||
mov [0x82], ax
|
||||
mov [0x86], ax
|
||||
mov [0x8a], ax
|
||||
|
||||
;Print a welcome message
|
||||
|
@ -69,86 +63,65 @@ int 0x21
|
|||
|
||||
shell:
|
||||
|
||||
;Re-set up the stack
|
||||
cli
|
||||
mov sp, stack
|
||||
add sp, 0x100
|
||||
sti
|
||||
|
||||
;Prompt for and read a command
|
||||
;Print a prompt
|
||||
mov si, prompt
|
||||
mov ah, 0x0
|
||||
int 0x21
|
||||
;Read a command
|
||||
mov di, buffer
|
||||
;Read
|
||||
mov di, input
|
||||
mov al, 0xff
|
||||
mov ah, 0x3
|
||||
int 0x21
|
||||
|
||||
;Identify and execute the command
|
||||
exec:
|
||||
;Check for no command
|
||||
cmp byte [buffer], 0x0
|
||||
je shell
|
||||
.echo:
|
||||
;Check
|
||||
mov si, buffer
|
||||
mov di, cmd.echo
|
||||
call cmpstr
|
||||
jnc .fileify
|
||||
;Load an execute the program
|
||||
;Load
|
||||
mov bx, 0x2000
|
||||
mov si, input
|
||||
mov ah, 0x0
|
||||
int 0x22
|
||||
;Check for errors
|
||||
cmp al, 0x1
|
||||
je error
|
||||
;Execute
|
||||
call echo
|
||||
jmp shell
|
||||
.fileify:
|
||||
;Check
|
||||
mov si, buffer
|
||||
mov di, cmd.fileify
|
||||
call cmpstr
|
||||
jnc .hello
|
||||
;Execute
|
||||
call fileify
|
||||
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:
|
||||
jmp 0x2000
|
||||
|
||||
;Print an error message and return to the shell
|
||||
error:
|
||||
mov bh, 0x0
|
||||
mov ah, 0x3
|
||||
int 0x10
|
||||
dec dh
|
||||
mov ah, 0x2
|
||||
int 0x10
|
||||
mov si, errormsg
|
||||
mov ah, 0x2
|
||||
int 0x21
|
||||
jmp shell
|
||||
|
||||
;Data
|
||||
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
|
||||
|
||||
cmd:
|
||||
.echo db "echo", 0x0
|
||||
.fileify db "fileify", 0x0
|
||||
.hello db "hello", 0x0
|
||||
.help db "help", 0x0
|
||||
.keycode db "keycode", 0x0
|
||||
|
||||
errormsg db "Unknown command", 0x0
|
||||
|
||||
buffer times 0xff db 0x0
|
||||
;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
|
||||
|
||||
stack:
|
||||
|
|
Loading…
Reference in New Issue