1
0
Fork 0

Change the line endings of the text files from Unix to DOS style.

This commit is contained in:
CrazyEttin 2021-06-22 16:05:09 +03:00
parent 08f2d57bb2
commit 2bfa61b669
10 changed files with 1024 additions and 1024 deletions

View File

@ -1,23 +1,23 @@
MIT License MIT License
=========== ===========
Copyright (c) 2021 CrazyEttin Copyright (c) 2021 CrazyEttin
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to permit persons to whom the Software is furnished to do so, subject to
the following conditions: the following conditions:
The above copyright notice and this permission notice shall be included The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software. in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

126
README.MD
View File

@ -1,63 +1,63 @@
EttinOS EttinOS
======= =======
EttinOS is a minimalist 16-bit DOS-like hobbyist operating system for 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 the IBM PC and compatible computers. Its git repository can be found at
https://ahti.space/git/crazyettin/EttinOS. https://ahti.space/git/crazyettin/EttinOS.
System requirements System requirements
------------------- -------------------
* An Intel 8086 or compatible CPU * An Intel 8086 or compatible CPU
* BIOS, or UEFI in legacy mode * BIOS, or UEFI in legacy mode
* 64 KiB of RAM * 64 KiB of RAM
* A floppy disk drive * A floppy disk drive
Building Building
-------- --------
Build dependencies: Build dependencies:
* A Unix-like operating system * A Unix-like operating system
* bash * bash
* coreutils * coreutils
* dosfstools * dosfstools
* mtools * mtools
* nasm * nasm
Running make.sh will build EttinOS and create a bootable 360 KiB 5.25" 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 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 use the argument -1440. If you want to use another floppy disk format
you will have to adjust the bootloader disk description tables and you will have to adjust the bootloader disk description tables and
install the system manually. Hard disk drives are not supported. install the system manually. Hard disk drives are not supported.
Input Input
----- -----
The EttinOS input system is inspired by typewriters. Typing a character The EttinOS input system is inspired by typewriters. Typing a character
overwrites the cursor location and the erase (=tab) key erases it. The overwrites the cursor location and the erase (=tab) key erases it. The
space and backspace keys move the cursor. space and backspace keys move the cursor.
Programming Programming
----------- -----------
EttinOS has a flat address space of 64 KiB. The data, stack, and EttinOS has a flat address space of 64 KiB. The data, stack, and
extra segments are set at the beginning of the RAM and the system stack extra segments are set at the beginning of the RAM and the system stack
at the end of the address space. Programs are loaded at address 0x2000. at the end of the address space. Programs are loaded at address 0x2000.
The stack is reset back to the end of the address space after a program The stack is reset back to the end of the address space after a program
has finished running. has finished running.
System calls: System calls:
* Interrupt 0x20: Return to the shell. * Interrupt 0x20: Return to the shell.
* Interrupt 0x21: Input and output: * Interrupt 0x21: Input and output:
* AH = 0x0: Print a string ending in a null from SI. * AH = 0x0: Print a string ending in a null from SI.
* AH = 0x1: Read a string ending in a null of at most AL * AH = 0x1: Read a string ending in a null of at most AL
characters to DI until a return. characters to DI until a return.
* AH = 0x2: Print a string ending in a null from SI followed by a * AH = 0x2: Print a string ending in a null from SI followed by a
CRLF. CRLF.
* AH = 0x3: Read a string ending in a null of at most AL * AH = 0x3: Read a string ending in a null of at most AL
characters to DI until a return and print a CRLF. characters to DI until a return and print a CRLF.
* Interrupt 0x22: Disk operations: * Interrupt 0x22: Disk operations:
* AH = 0x0: Load a file named in SI as a string ending in a null * 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 to the offset BX and set AL to 0x0 if the load was
succesfull and 0x1 if there was an error. succesfull and 0x1 if there was an error.
* AH = 0x1: Save a file (under construction). * AH = 0x1: Save a file (under construction).

View File

@ -1,243 +1,243 @@
CPU 8086 CPU 8086
ORG 0x7c00 ORG 0x7c00
jmp start jmp start
nop nop
;Disk description tables ;Disk description tables
%ifdef F1440 %ifdef F1440
;1.44 MB 3.5" floppy disk (enable with the argument -d F1440 when building) ;1.44 MB 3.5" floppy disk (enable with the argument -d F1440 when building)
oemlabel db "ETTINOS " oemlabel db "ETTINOS "
sectorsize dw 0x200 ;bytes sectorsize dw 0x200 ;bytes
clustersize db 0x1 ;sectors clustersize db 0x1 ;sectors
bootsectors dw 0x1 bootsectors dw 0x1
fats db 0x2 fats db 0x2
rootentries dw 0xe0 rootentries dw 0xe0
logicalsectors dw 0xb40 logicalsectors dw 0xb40
mediadescriptor db 0xf0 mediadescriptor db 0xf0
sectorsperfat dw 0x9 sectorsperfat dw 0x9
sectorspertrack dw 0x12 sectorspertrack dw 0x12
sides dw 0x2 sides dw 0x2
hiddensectors dd 0x0 hiddensectors dd 0x0
largesectors dd 0x0 largesectors dd 0x0
driveid dw 0x0 driveid dw 0x0
drivesignature db 0x29 drivesignature db 0x29
volumeid dd 0x0 volumeid dd 0x0
volumelabel db "ETTINOS " volumelabel db "ETTINOS "
filesystem db "FAT12 " filesystem db "FAT12 "
%else %else
;360 KiB 5.25" floppy disk (default) ;360 KiB 5.25" floppy disk (default)
oemlabel db "ETTINOS " oemlabel db "ETTINOS "
sectorsize dw 0x200 ;bytes sectorsize dw 0x200 ;bytes
clustersize db 0x2 ;sectors clustersize db 0x2 ;sectors
bootsectors dw 0x1 bootsectors dw 0x1
fats db 0x2 fats db 0x2
rootentries dw 0x70 rootentries dw 0x70
logicalsectors dw 0x2d0 logicalsectors dw 0x2d0
mediadescriptor db 0xfd mediadescriptor db 0xfd
sectorsperfat dw 0x2 sectorsperfat dw 0x2
sectorspertrack dw 0x9 sectorspertrack dw 0x9
sides dw 0x2 sides dw 0x2
hiddensectors dd 0x0 hiddensectors dd 0x0
largesectors dd 0x0 largesectors dd 0x0
driveid dw 0x0 driveid dw 0x0
drivesignature db 0x29 drivesignature db 0x29
volumeid dd 0x0 volumeid dd 0x0
volumelabel db "ETTINOS " volumelabel db "ETTINOS "
filesystem db "FAT12 " filesystem db "FAT12 "
%endif %endif
start: start:
;Setup ;Setup
;Set up the data, stack, and extra segments ;Set up the data, stack, and extra segments
mov ax, 0x0 mov ax, 0x0
mov ds, ax mov ds, ax
mov ss, ax mov ss, ax
mov es, ax mov es, ax
;Set up the stack ;Set up the stack
cli cli
mov sp, 0x0 mov sp, 0x0
sti sti
;Store the boot drive number ;Store the boot drive number
mov [bootdrive], dl mov [bootdrive], dl
;Load the root ;Load the root
;Set the source ;Set the source
mov ah, 0x0 mov ah, 0x0
mov al, [fats] mov al, [fats]
mul word [sectorsperfat] mul word [sectorsperfat]
add ax, [bootsectors] add ax, [bootsectors]
push ax push ax
call calcsource call calcsource
;Set the destination ;Set the destination
mov si, buffer mov si, buffer
mov bx, si mov bx, si
;Set the size ;Set the size
push dx push dx
mov ax, [rootentries] mov ax, [rootentries]
mov dx, 0x20 mov dx, 0x20
mul dx mul dx
mov dx, 0x0 mov dx, 0x0
div word [sectorsize] div word [sectorsize]
pop dx pop dx
push ax push ax
;Load ;Load
mov ah, 0x2 mov ah, 0x2
int 0x13 int 0x13
;Search the root for the system entry ;Search the root for the system entry
;Set DI to the root ;Set DI to the root
mov di, buffer mov di, buffer
;Initialise the search loop ;Initialise the search loop
mov cx, word [rootentries] mov cx, word [rootentries]
mov ax, 0x0 mov ax, 0x0
search: search:
;Store CX in the stack ;Store CX in the stack
push cx push cx
;Check for the system entry ;Check for the system entry
mov si, sysfile mov si, sysfile
mov cx, 0xb mov cx, 0xb
rep cmpsb rep cmpsb
je loadentry je loadentry
;Set DI to the next entry ;Set DI to the next entry
add ax, 0x20 add ax, 0x20
mov di, buffer mov di, buffer
add di, ax add di, ax
;Load CX from the stack ;Load CX from the stack
pop cx pop cx
loop search loop search
;Print an error message if the system is not found ;Print an error message if the system is not found
mov si, errormsg mov si, errormsg
printerror: printerror:
;Load a character ;Load a character
lodsb lodsb
;Check for the string end ;Check for the string end
cmp al, 0x0 cmp al, 0x0
je $ je $
;Print the character ;Print the character
mov ah, 0xe mov ah, 0xe
int 0x10 int 0x10
;Repeat ;Repeat
jmp printerror jmp printerror
;Load the system entry ;Load the system entry
loadentry: loadentry:
;Load CX from the stack ;Load CX from the stack
pop cx pop cx
;Store the first cluster ;Store the first cluster
mov ax, word [es:di+0xf] mov ax, word [es:di+0xf]
mov word [cluster], ax mov word [cluster], ax
;Set the source ;Set the source
mov ax, 0x1 mov ax, 0x1
call calcsource call calcsource
;Set the destination ;Set the destination
mov di, buffer mov di, buffer
mov bx, di mov bx, di
;Set the size ;Set the size
mov ax, [sectorsperfat] mov ax, [sectorsperfat]
;Load ;Load
mov ah, 0x2 mov ah, 0x2
int 0x13 int 0x13
;Load the system file ;Load the system file
;Load a cluster ;Load a cluster
loadcluster: loadcluster:
;Set the source ;Set the source
pop cx pop cx
pop bx pop bx
mov ax, word [cluster] mov ax, word [cluster]
sub ax, 0x2 sub ax, 0x2
mul byte [clustersize] mul byte [clustersize]
add ax, bx add ax, bx
add ax, cx add ax, cx
push bx push bx
push cx push cx
call calcsource call calcsource
;Set the destination ;Set the destination
mov bx, word [pointer] mov bx, word [pointer]
;Set the size ;Set the size
;mov al, 0x1 ;mov al, 0x1
mov al, [clustersize] mov al, [clustersize]
;Load ;Load
mov ah, 0x2 mov ah, 0x2
int 0x13 int 0x13
;Calculate the next cluster ;Calculate the next cluster
mov ax, [cluster] mov ax, [cluster]
mov dx, 0x0 mov dx, 0x0
mov bx, 0x3 mov bx, 0x3
mul bx mul bx
mov bx, 0x2 mov bx, 0x2
div bx div bx
mov si, buffer mov si, buffer
add si, ax add si, ax
mov ax, word [ds:si] mov ax, word [ds:si]
or dx, dx or dx, dx
jz even jz even
odd: odd:
shr ax, 1 shr ax, 1
shr ax, 1 shr ax, 1
shr ax, 1 shr ax, 1
shr ax, 1 shr ax, 1
jmp contcalc jmp contcalc
even: even:
and ax, 0xfff and ax, 0xfff
contcalc: contcalc:
mov word [cluster], ax mov word [cluster], ax
cmp ax, 0xff8 cmp ax, 0xff8
jge boot jge boot
mov ax, [sectorsize] mov ax, [sectorsize]
mul word [clustersize] mul word [clustersize]
add word [pointer], ax add word [pointer], ax
jmp loadcluster jmp loadcluster
;Clear the stack and boot the system ;Clear the stack and boot the system
boot: boot:
;Clear ;Clear
pop cx pop cx
pop bx pop bx
;Boot ;Boot
jmp 0x0:0x500 jmp 0x0:0x500
;Data ;Data
bootdrive 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
pointer dw 0x500 pointer dw 0x500
;Calculate the source arguments for loading data from the disk ;Calculate the source arguments for loading data from the disk
calcsource: calcsource:
push ax push ax
push bx push bx
mov bx, ax mov bx, ax
mov dx, 0x0 mov dx, 0x0
div word [sectorspertrack] div word [sectorspertrack]
add dl, 0x1 add dl, 0x1
mov cl, dl mov cl, dl
mov ax, bx mov ax, bx
mov dx, 0x0 mov dx, 0x0
div word [sectorspertrack] div word [sectorspertrack]
mov dx, 0x0 mov dx, 0x0
div word [sides] div word [sides]
mov dh, dl mov dh, dl
mov ch, al mov ch, al
pop bx pop bx
pop ax pop ax
mov dl, byte [bootdrive] 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
;Padding ;Padding
times 0x1fe-($-$$) db 0x0 times 0x1fe-($-$$) db 0x0
;Boot signature ;Boot signature
dw 0xaa55 dw 0xaa55
;File system buffer ;File system buffer
buffer: buffer:

View File

@ -1,11 +1,11 @@
CPU 8086 CPU 8086
ORG 0x2000 ORG 0x2000
;Prints a hello world. ;Prints a hello world.
mov si, .hello mov si, .hello
mov ah, 0x2 mov ah, 0x2
int 0x21 int 0x21
int 0x20 int 0x20
;Data ;Data
.hello db "Hello world!", 0x0 .hello db "Hello world!", 0x0

View File

@ -1,304 +1,304 @@
;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. ;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: loadf:
;Store the initial registers in the stack ;Store the initial registers in the stack
push ax push ax
push bx push bx
push cx push cx
push dx push dx
push si push si
push di push di
;Store the offset ;Store the offset
mov word [.pointer], bx mov word [.pointer], bx
;Set DI at .file and initialise it with spaces ;Set DI at .file and initialise it with spaces
mov di, .file mov di, .file
mov cx, 0xb mov cx, 0xb
mov al, 0x20 mov al, 0x20
rep stosb rep stosb
sub di, 0xb sub di, 0xb
;Convert .file into FAT formatting ;Convert .file into FAT formatting
;Initialise the length counter for the main part of the name ;Initialise the length counter for the main part of the name
mov bl, 0x8 mov bl, 0x8
;Convert the main part of the file name ;Convert the main part of the file name
.nameloop: .nameloop:
;Load a character ;Load a character
lodsb lodsb
;Check for a period ;Check for a period
cmp al, 0x2e cmp al, 0x2e
je .initext je .initext
;Check for everything else and convert to upper case ;Check for everything else and convert to upper case
call .checkconv call .checkconv
jmp .nameloop jmp .nameloop
;Convert the extension ;Convert the extension
.initext: .initext:
;Set DI and initialise the length counter for the extension ;Set DI and initialise the length counter for the extension
mov bl, 0x3 mov bl, 0x3
mov di, .file+0x8 mov di, .file+0x8
.extloop: .extloop:
;Load a character ;Load a character
lodsb lodsb
;Check for a period ;Check for a period
push ax push ax
cmp al, 0x2e cmp al, 0x2e
je .error je .error
pop ax pop ax
;Check for everything else and convert to upper case ;Check for everything else and convert to upper case
call .checkconv call .checkconv
jmp .extloop jmp .extloop
;Set the carry flag and print an error message if the file name is invalid ;Set the carry flag and print an error message if the file name is invalid
.error: .error:
pop ax pop ax
stc stc
mov si, .errormsg mov si, .errormsg
mov ah, 0x2 mov ah, 0x2
int 0x21 int 0x21
jmp .done jmp .done
;Find and load the file ;Find and load the file
.load: .load:
pop ax pop ax
;Load the root ;Load the root
;Set the source ;Set the source
mov ah, 0x0 mov ah, 0x0
mov al, [.fats] mov al, [.fats]
mul word [.sectorsperfat] mul word [.sectorsperfat]
add ax, [.bootsectors] add ax, [.bootsectors]
push ax push ax
call .calcsource call .calcsource
;Set the destination ;Set the destination
mov si, buffer mov si, buffer
mov bx, si mov bx, si
;Set the size ;Set the size
push dx push dx
mov ax, [.rootentries] mov ax, [.rootentries]
mov dx, 0x20 mov dx, 0x20
mul dx mul dx
mov dx, 0x0 mov dx, 0x0
div word [.sectorsize] div word [.sectorsize]
pop dx pop dx
push ax push ax
;Load ;Load
mov ah, 0x2 mov ah, 0x2
int 0x13 int 0x13
;Search the root for the file entry ;Search the root for the file entry
;Set DI to the root ;Set DI to the root
mov di, buffer mov di, buffer
;Initialise the search loop ;Initialise the search loop
mov cx, word [.rootentries] mov cx, word [.rootentries]
mov ax, 0x0 mov ax, 0x0
.search: .search:
;Store CX in the stack ;Store CX in the stack
push cx push cx
;Check for the file entry ;Check for the file entry
mov si, .file mov si, .file
mov cx, 0xb mov cx, 0xb
rep cmpsb rep cmpsb
je .loadentry je .loadentry
;Set DI to the next entry ;Set DI to the next entry
add ax, 0x20 add ax, 0x20
mov di, buffer mov di, buffer
add di, ax add di, ax
;Load CX from the stack ;Load CX from the stack
pop cx pop cx
loop .search loop .search
;Set the carry flag and print an error message if the file is not found ;Set the carry flag and print an error message if the file is not found
stc stc
mov si, .errormsg mov si, .errormsg
mov ah, 0x2 mov ah, 0x2
int 0x21 int 0x21
jmp .clearstack jmp .clearstack
;Load the file entry ;Load the file entry
.loadentry: .loadentry:
;Load CX from the stack ;Load CX from the stack
pop cx pop cx
;Store the first cluster ;Store the first cluster
mov ax, word [es:di+0xf] mov ax, word [es:di+0xf]
mov word [.cluster], ax mov word [.cluster], ax
;Set the source ;Set the source
mov ax, 0x1 mov ax, 0x1
call .calcsource call .calcsource
;Set the destination ;Set the destination
mov di, buffer mov di, buffer
mov bx, di mov bx, di
;Set the size ;Set the size
mov ax, [.sectorsperfat] mov ax, [.sectorsperfat]
;Load ;Load
mov ah, 0x2 mov ah, 0x2
int 0x13 int 0x13
;Load the file ;Load the file
;Load a cluster ;Load a cluster
.loadcluster: .loadcluster:
;Set the source ;Set the source
pop cx pop cx
pop bx pop bx
mov ax, word [.cluster] mov ax, word [.cluster]
sub ax, 0x2 sub ax, 0x2
mul byte [.clustersize] mul byte [.clustersize]
add ax, bx add ax, bx
add ax, cx add ax, cx
push bx push bx
push cx push cx
call .calcsource call .calcsource
;Set the destination ;Set the destination
mov bx, word [.pointer] mov bx, word [.pointer]
;Set the size ;Set the size
;mov al, 0x1 ;mov al, 0x1
mov al, [.clustersize] mov al, [.clustersize]
;Load ;Load
mov ah, 0x2 mov ah, 0x2
int 0x13 int 0x13
;Calculate the next cluster ;Calculate the next cluster
mov ax, [.cluster] mov ax, [.cluster]
mov dx, 0x0 mov dx, 0x0
mov bx, 0x3 mov bx, 0x3
mul bx mul bx
mov bx, 0x2 mov bx, 0x2
div bx div bx
mov si, buffer mov si, buffer
add si, ax add si, ax
mov ax, word [ds:si] mov ax, word [ds:si]
or dx, dx or dx, dx
jz .even jz .even
shr ax, 1 shr ax, 1
shr ax, 1 shr ax, 1
shr ax, 1 shr ax, 1
shr ax, 1 shr ax, 1
jmp .contcalc jmp .contcalc
.even: .even:
and ax, 0xfff and ax, 0xfff
.contcalc: .contcalc:
mov word [.cluster], ax mov word [.cluster], ax
cmp ax, 0xff8 cmp ax, 0xff8
jge .clearcarry jge .clearcarry
mov ax, [.sectorsize] mov ax, [.sectorsize]
mul word [.clustersize] mul word [.clustersize]
add word [.pointer], ax add word [.pointer], ax
jmp .loadcluster jmp .loadcluster
;Clear the carry flag if the load was succesful ;Clear the carry flag if the load was succesful
.clearcarry: .clearcarry:
clc clc
;Clear the stack ;Clear the stack
.clearstack: .clearstack:
pop cx pop cx
pop bx pop bx
.done: .done:
;Load the initial registers from the stack ;Load the initial registers from the stack
pop di pop di
pop si pop si
pop dx pop dx
pop cx pop cx
pop bx pop bx
pop ax pop ax
;Set AL to 0x1 if there was an error and to 0x0 otherwise and return ;Set AL to 0x1 if there was an error and to 0x0 otherwise and return
jc .setal jc .setal
mov al, 0x0 mov al, 0x0
iret iret
.setal: .setal:
mov al, 0x1 mov al, 0x1
iret iret
;Data ;Data
.file times 0xb db 0x20 .file times 0xb db 0x20
.errormsg db "File not found", 0x0 .errormsg db "File not found", 0x0
.cluster dw 0x0 .cluster dw 0x0
.pointer dw 0x0 .pointer dw 0x0
;These are temporary until i write something to load them from the disk itself ;These are temporary until i write something to load them from the disk itself
.bootdrive db 0x0 .bootdrive db 0x0
.sectorsize dw 0x200 ;bytes .sectorsize dw 0x200 ;bytes
.clustersize db 0x2 ;sectors .clustersize db 0x2 ;sectors
.bootsectors dw 0x1 .bootsectors dw 0x1
.fats db 0x2 .fats db 0x2
.rootentries dw 0x70 .rootentries dw 0x70
.sectorsperfat dw 0x2 .sectorsperfat dw 0x2
.sectorspertrack dw 0x9 .sectorspertrack dw 0x9
.sides dw 0x2 .sides dw 0x2
;Check the file name and convert to upper case ;Check the file name and convert to upper case
.checkconv: .checkconv:
;Check for the string end ;Check for the string end
cmp al, 0x0 cmp al, 0x0
je .load je .load
;Check for the length limit ;Check for the length limit
cmp bl, 0x0 cmp bl, 0x0
je .error je .error
;Check for invalid characters ;Check for invalid characters
cmp al, 0x22 cmp al, 0x22
je .error je .error
cmp al, 0x2a cmp al, 0x2a
jl .contcheck1 jl .contcheck1
cmp al, 0x2c cmp al, 0x2c
jg .contcheck1 jg .contcheck1
jmp .error jmp .error
.contcheck1: .contcheck1:
cmp al, 0x2f cmp al, 0x2f
je .error je .error
cmp al, 0x3a cmp al, 0x3a
jl .contcheck2 jl .contcheck2
cmp al, 0x3f cmp al, 0x3f
jg .contcheck2 jg .contcheck2
jmp .error jmp .error
.contcheck2: .contcheck2:
cmp al, 0x5b cmp al, 0x5b
jl .contcheck3 jl .contcheck3
cmp al, 0x5d cmp al, 0x5d
jg .contcheck3 jg .contcheck3
jmp .error jmp .error
.contcheck3: .contcheck3:
cmp al, 0x7c cmp al, 0x7c
je .error je .error
;Check for lower case ;Check for lower case
cmp al, 0x61 cmp al, 0x61
jl .storech jl .storech
cmp al, 0x7a cmp al, 0x7a
jg .storech jg .storech
;Convert lower to upper case ;Convert lower to upper case
sub al, 0x20 sub al, 0x20
.storech: .storech:
;Store the character ;Store the character
stosb stosb
;Increase the counter ;Increase the counter
dec bl dec bl
ret ret
;Calculate the source arguments for loading data from the disk ;Calculate the source arguments for loading data from the disk
.calcsource: .calcsource:
push ax push ax
push bx push bx
mov bx, ax mov bx, ax
mov dx, 0x0 mov dx, 0x0
div word [.sectorspertrack] div word [.sectorspertrack]
add dl, 0x1 add dl, 0x1
mov cl, dl mov cl, dl
mov ax, bx mov ax, bx
mov dx, 0x0 mov dx, 0x0
div word [.sectorspertrack] div word [.sectorspertrack]
mov dx, 0x0 mov dx, 0x0
div word [.sides] div word [.sides]
mov dh, dl mov dh, dl
mov ch, al mov ch, al
pop bx pop bx
pop ax pop ax
mov dl, byte [.bootdrive] mov dl, byte [.bootdrive]
ret ret

View File

@ -1,12 +1,12 @@
;Print a string ending in a null from SI followed by a CRLF. ;Print a string ending in a null from SI followed by a CRLF.
println: println:
;Print the string ;Print the string
mov ah, 0x0 mov ah, 0x0
int 0x21 int 0x21
;Print a CRLF ;Print a CRLF
call printcrlf call printcrlf
iret iret

View File

@ -1,28 +1,28 @@
;Print a string ending in a null from SI. ;Print a string ending in a null from SI.
printstr: printstr:
;Store the initial registers in the stack ;Store the initial registers in the stack
push ax push ax
push si push si
;Print the string ;Print the string
.loop: .loop:
;Load the current character ;Load the current character
lodsb lodsb
;Check for the string end ;Check for the string end
cmp al, 0x0 cmp al, 0x0
je .done je .done
;Print the character ;Print the character
mov ah, 0xe mov ah, 0xe
int 0x10 int 0x10
;Repeat for the next character ;Repeat for the next character
jmp .loop jmp .loop
.done: .done:
;Load the initial registers from the stack ;Load the initial registers from the stack
pop si pop si
pop ax pop ax
iret iret

View File

@ -1,12 +1,12 @@
;Read a string ending in null of at most AL characters to DI until a return and print a CRLF. ;Read a string ending in null of at most AL characters to DI until a return and print a CRLF.
readln: readln:
;Read the string ;Read the string
mov ah, 0x1 mov ah, 0x1
int 0x21 int 0x21
;Print a CRLF ;Print a CRLF
call printcrlf call printcrlf
iret iret

View File

@ -1,204 +1,204 @@
;Read a string ending in a null 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:
;Store the initial registers in the stack ;Store the initial registers in the stack
push ax push ax
push bx push bx
push cx push cx
push dx push dx
push di push di
;Setup ;Setup
;Store the input length in the stack ;Store the input length in the stack
mov ah, 0 mov ah, 0
push ax push ax
;Initialise the destination with spaces ;Initialise the destination with spaces
mov cx, ax mov cx, ax
mov al, 0x20 mov al, 0x20
rep stosb rep stosb
pop ax pop ax
push ax push ax
sub di, ax sub di, ax
;Initialise the cursor pointer in BL and clear BH ;Initialise the cursor pointer in BL and clear BH
mov bx, 0x1 mov bx, 0x1
.loop: .loop:
;Read a keypress ;Read a keypress
mov ah, 0x0 mov ah, 0x0
int 0x16 int 0x16
;Check for special keys and non-printing characters ;Check for special keys and non-printing characters
;Check for return ;Check for return
cmp al, 0xd cmp al, 0xd
je .return je .return
;Check for backspace ;Check for backspace
cmp al, 0x8 cmp al, 0x8
je .backspace je .backspace
;Check for input end ;Check for input end
pop dx pop dx
push dx push dx
cmp bl, dl cmp bl, dl
je .loop je .loop
;Check for space ;Check for space
cmp al, 0x20 cmp al, 0x20
je .space je .space
;Check for erase ;Check for erase
cmp al, 0x9 cmp al, 0x9
je .erase je .erase
;Check for non-printing characters ;Check for non-printing characters
cmp al, 0x1f cmp al, 0x1f
jle .loop jle .loop
cmp al, 0x7f cmp al, 0x7f
je .loop je .loop
;Store and print a character ;Store and print a character
.character: .character:
;Store the character ;Store the character
stosb stosb
;Print the character ;Print the character
mov ah, 0xe mov ah, 0xe
int 0x10 int 0x10
;Move the cursor pointer ;Move the cursor pointer
inc bl inc bl
jmp .loop jmp .loop
;Replace the cursor position with a space ;Replace the cursor position with a space
.erase: .erase:
mov al, 0x20 mov al, 0x20
jmp .character jmp .character
;Move the cursor forward ;Move the cursor forward
.space: .space:
call .nextchar call .nextchar
inc di inc di
inc bl inc bl
jmp .loop jmp .loop
;Move the cursor backward ;Move the cursor backward
.backspace: .backspace:
;Check for the input beginning ;Check for the input beginning
cmp bl, 0x1 cmp bl, 0x1
je .loop je .loop
;Move the cursor ;Move the cursor
call .prevchar call .prevchar
dec di dec di
dec bl dec bl
jmp .loop jmp .loop
;Finish reading the string ;Finish reading the string
.return: .return:
;Find and remove trailing spaces ;Find and remove trailing spaces
;Go to the end of the input ;Go to the end of the input
pop ax pop ax
mov bh, 0x0 mov bh, 0x0
sub ax, bx sub ax, bx
push di push di
add di, ax add di, ax
.findtrailing: .findtrailing:
;Check for a trailing space ;Check for a trailing space
cmp byte [di], 0x20 cmp byte [di], 0x20
je .deltrailing je .deltrailing
jmp .end jmp .end
.deltrailing: .deltrailing:
;Delete a trailing space ;Delete a trailing space
mov al, 0x0 mov al, 0x0
stosb stosb
sub di, 0x2 sub di, 0x2
jmp .findtrailing jmp .findtrailing
;Move the cursor to the end of the input string ;Move the cursor to the end of the input string
.end: .end:
pop di pop di
.findend: .findend:
cmp byte [di], 0x0 cmp byte [di], 0x0
jne .notend jne .notend
jmp .done jmp .done
.notend: .notend:
call .nextchar call .nextchar
inc di inc di
inc bl inc bl
jmp .findend jmp .findend
.done: .done:
;Load the initial registers from the stack ;Load the initial registers from the stack
pop di pop di
pop dx pop dx
pop cx pop cx
pop bx pop bx
pop ax pop ax
iret iret
;Move the cursor forward ;Move the cursor forward
;Move forward within a line ;Move forward within a line
.nextchar: .nextchar:
;Get the cursor position ;Get the cursor position
mov ah, 0x3 mov ah, 0x3
int 0x10 int 0x10
;Check for the end of the line ;Check for the end of the line
cmp dl, 0x4f cmp dl, 0x4f
je .nextln je .nextln
;Move ;Move
inc dl inc dl
mov ah, 0x2 mov ah, 0x2
int 0x10 int 0x10
ret ret
;Move to the beginning of the next line ;Move to the beginning of the next line
.nextln: .nextln:
;Check if the current line is the last on screen ;Check if the current line is the last on screen
cmp dh, 0x18 cmp dh, 0x18
je .scroll je .scroll
;Move ;Move
mov ah, 0x2 mov ah, 0x2
inc dh inc dh
mov dl, 0x0 mov dl, 0x0
int 0x10 int 0x10
ret ret
;Scroll the screen up by one line ;Scroll the screen up by one line
.scroll: .scroll:
;Scroll ;Scroll
mov ah, 0x6 mov ah, 0x6
mov al, 0x1 mov al, 0x1
mov bh, 0x7 mov bh, 0x7
mov ch, 0x0 mov ch, 0x0
mov cl, 0x0 mov cl, 0x0
mov dh, 0x18 mov dh, 0x18
mov dl, 0x4f mov dl, 0x4f
int 0x10 int 0x10
;Move to the beginning of the new line ;Move to the beginning of the new line
mov ah, 0x2 mov ah, 0x2
mov bh, 0x0 mov bh, 0x0
mov dl, 0x0 mov dl, 0x0
int 0x10 int 0x10
ret ret
;Move the cursor backward ;Move the cursor backward
;Move backward within a line ;Move backward within a line
.prevchar: .prevchar:
;Get the cursor position ;Get the cursor position
mov ah, 0x3 mov ah, 0x3
int 0x10 int 0x10
;Check for the beginning of the line ;Check for the beginning of the line
cmp dl, 0x0 cmp dl, 0x0
je .prevln je .prevln
;Move ;Move
dec dl dec dl
mov ah, 0x2 mov ah, 0x2
int 0x10 int 0x10
ret ret
;Move to the end of the previous line ;Move to the end of the previous line
.prevln: .prevln:
mov ah, 0x2 mov ah, 0x2
dec dh dec dh
mov dl, 0x4f mov dl, 0x4f
int 0x10 int 0x10
ret ret

View File

@ -1,124 +1,124 @@
CPU 8086 CPU 8086
ORG 0x500 ORG 0x500
jmp start jmp start
;Interrupt handler ;Interrupt handler
;Return to the shell ;Return to the shell
int0x20: int0x20:
jmp shell jmp shell
;Input and output ;Input and output
int0x21: int0x21:
cmp ah, 0x0 cmp ah, 0x0
je printstr je printstr
cmp ah, 0x1 cmp ah, 0x1
je readstr je readstr
cmp ah, 0x2 cmp ah, 0x2
je println je println
cmp ah, 0x3 cmp ah, 0x3
je readln je readln
iret iret
;Disk operations ;Disk operations
int0x22: int0x22:
cmp ah, 0x0 cmp ah, 0x0
je loadf je loadf
;To do: savef ;To do: savef
iret iret
;System calls ;System calls
%include "PRINTSTR.INC" %include "PRINTSTR.INC"
%include "READSTR.INC" %include "READSTR.INC"
%include "PRINTLN.INC" %include "PRINTLN.INC"
%include "READLN.INC" %include "READLN.INC"
%include "LOADF.INC" %include "LOADF.INC"
start: start:
;Set up the interrupt vectors ;Set up the interrupt vectors
;Interrupt 0x20 offset ;Interrupt 0x20 offset
mov ax, int0x20 mov ax, int0x20
mov [0x80], ax mov [0x80], ax
;Interrupt 0x21 offset ;Interrupt 0x21 offset
mov ax, int0x21 mov ax, int0x21
mov [0x84], ax mov [0x84], ax
;Interrupt 0x22 offset ;Interrupt 0x22 offset
mov ax, int0x22 mov ax, int0x22
mov [0x88], ax mov [0x88], ax
;Segments ;Segments
mov ax, 0x0 mov ax, 0x0
mov [0x82], ax mov [0x82], ax
mov [0x86], ax mov [0x86], ax
mov [0x8a], ax mov [0x8a], ax
;Print a welcome message ;Print a welcome message
mov si, welcomemsg mov si, welcomemsg
mov ah, 0x2 mov ah, 0x2
int 0x21 int 0x21
shell: shell:
;Re-set the stack ;Re-set the stack
cli cli
mov sp, 0x0 mov sp, 0x0
sti 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 ;Read
mov di, input mov di, input
mov al, 0x4e mov al, 0x4e
mov ah, 0x3 mov ah, 0x3
int 0x21 int 0x21
;Load an execute the program ;Load an execute the program
;Check for an empty command ;Check for an empty command
cmp byte [input], 0x0 cmp byte [input], 0x0
jz shell jz shell
;Load ;Load
mov bx, 0x2000 mov bx, 0x2000
mov si, input mov si, input
mov ah, 0x0 mov ah, 0x0
int 0x22 int 0x22
;Check for errors ;Check for errors
cmp al, 0x1 cmp al, 0x1
je error je error
;Execute ;Execute
jmp 0x2000 jmp 0x2000
;Print an error message and return to the shell ;Print an error message and return to the shell
error: error:
mov bh, 0x0 mov bh, 0x0
mov ah, 0x3 mov ah, 0x3
int 0x10 int 0x10
dec dh dec dh
mov ah, 0x2 mov ah, 0x2
int 0x10 int 0x10
mov si, errormsg mov si, errormsg
mov ah, 0x2 mov ah, 0x2
int 0x21 int 0x21
jmp shell jmp shell
;Data ;Data
welcomemsg db 0xd, 0xa, "Welcome to EttinOS!", 0xd, 0xa, 0x0 welcomemsg db 0xd, 0xa, "Welcome to EttinOS!", 0xd, 0xa, 0x0
prompt db "> ", 0x0 prompt db "> ", 0x0
errormsg db "Unknown command", 0x0 errormsg db "Unknown command", 0x0
input times 0x4e db 0x0 input times 0x4e db 0x0
crlf db 0xd, 0xa, 0x0 crlf db 0xd, 0xa, 0x0
;Print a CRLF ;Print a CRLF
printcrlf: printcrlf:
;Store the initial registers in the stack ;Store the initial registers in the stack
push si push si
;Print the CRLF ;Print the CRLF
mov si, crlf mov si, crlf
mov ah, 0x0 mov ah, 0x0
int 0x21 int 0x21
;Load the initial registers from the stack ;Load the initial registers from the stack
pop si pop si
ret ret
;File system buffer ;File system buffer
buffer: buffer: