Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
Juhani Krekelä | 3f4c6c0559 | |
Juhani Krekelä | 7e41612687 |
|
@ -1,4 +1,3 @@
|
|||
*.bin
|
||||
*.img
|
||||
*.d
|
||||
*.krn
|
||||
|
|
16
Makefile
16
Makefile
|
@ -1,30 +1,24 @@
|
|||
FLOPPY = 360
|
||||
FLOPPY = 1440
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .bin .asm
|
||||
|
||||
all: nor86.img
|
||||
|
||||
nor86.img: boot.bin nor86.krn CC0 README.md
|
||||
nor86.img: bootsect.bin kernel.bin CC0 README.md
|
||||
rm -f $@
|
||||
mkdosfs -C $@ $(FLOPPY)
|
||||
rw -i boot.bin -o $@
|
||||
rw -i bootsect.bin -o $@
|
||||
mcopy -i $@ CC0 ::
|
||||
mcopy -i $@ README.md ::
|
||||
mcopy -i $@ *.asm ::
|
||||
mcopy -i $@ *.inc ::
|
||||
mcopy -i $@ nor86.krn ::
|
||||
|
||||
nor86.krn: kernel.asm
|
||||
nasm -fbin -d F$(FLOPPY) -o $@ $<
|
||||
nasm -MD $@.d -d F$(FLOPPY) -fbin -o $@ $<
|
||||
mcopy -i $@ kernel.bin ::
|
||||
|
||||
.asm.bin:
|
||||
nasm -fbin -d F$(FLOPPY) -o $@ $<
|
||||
nasm -MD $@.d -d F$(FLOPPY) -fbin -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f *.bin *.img *.bin.d *.krn *.krn.d
|
||||
rm -f *.bin *.img *.bin.d
|
||||
|
||||
run: nor86.img
|
||||
qemu-system-i386 -fda $<
|
||||
|
|
|
@ -8,6 +8,6 @@ Floppy sizes
|
|||
------------
|
||||
|
||||
You can build either a 1440K or a 360K floppy image from Nor86 sources, the
|
||||
default being 360K. To build a 1440K floppy instead, run:
|
||||
default being 1440K. To build a 360K floppy instead, run:
|
||||
|
||||
make FLOPPY=1440
|
||||
make FLOPPY=360
|
||||
|
|
|
@ -67,6 +67,29 @@ _start:
|
|||
; Save bootdrive
|
||||
mov [drivenumber], dl
|
||||
|
||||
select_os:
|
||||
mov si, prompt
|
||||
.print:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .end
|
||||
; On the original IBM PC BIOS the int 0x10 will clobber this
|
||||
mov ah, 0xe
|
||||
int 0x10
|
||||
jmp .print
|
||||
.end:
|
||||
|
||||
xor ax, ax
|
||||
int 0x16
|
||||
|
||||
cmp al, 'e'
|
||||
jne calc_constants
|
||||
|
||||
mov si, ettinos_kernel_name
|
||||
mov di, kernel_name
|
||||
mov cx, 11
|
||||
rep movsb
|
||||
|
||||
calc_constants:
|
||||
; Disk organization:
|
||||
; Reserved sectors (MBR)
|
||||
|
@ -97,15 +120,25 @@ calc_constants:
|
|||
fat:
|
||||
; FAT1 (the main one) follows right after bootsector(s)
|
||||
mov ax, [reservedsectors]
|
||||
call chs
|
||||
|
||||
; TODO: handle possible crossing of track boundary
|
||||
mov ax, [sectorsperfat]
|
||||
mov ah, 2
|
||||
mov dl, [drivenumber]
|
||||
mov bx, 0x8000
|
||||
mov cx, [sectorsperfat]
|
||||
call loadsectors
|
||||
int 0x13
|
||||
|
||||
root_dir:
|
||||
mov ax, [rootdir]
|
||||
call chs
|
||||
|
||||
; TODO: handle possible crossing of track boundary
|
||||
mov ax, [rootdirsectors]
|
||||
mov ah, 2
|
||||
mov dl, [drivenumber]
|
||||
mov bx, 0x500
|
||||
mov cx, [rootdirsectors]
|
||||
call loadsectors
|
||||
int 0x13
|
||||
|
||||
search_root:
|
||||
mov bx, [rootdirentries]
|
||||
|
@ -120,53 +153,26 @@ search_root:
|
|||
cmp byte [si], 0
|
||||
je .end
|
||||
|
||||
; Deleted file?
|
||||
cmp byte [si], 0xe5
|
||||
je .skipentry
|
||||
|
||||
test byte [si + 11], 0x08 + 0x10
|
||||
jnz .skipentry
|
||||
jz .isfile
|
||||
|
||||
; Make sure the file has non-zero size
|
||||
; File size must be <32K anyways so don't bother with >64K
|
||||
cmp word [si + 28], 0
|
||||
jne .isfile
|
||||
|
||||
.skipentry:
|
||||
add si, 32
|
||||
jmp .entry
|
||||
|
||||
.isfile:
|
||||
.nor86:
|
||||
cmp word [si + 8], 'KR'
|
||||
jne .ettinos
|
||||
cmp byte [si + 10], 'N'
|
||||
jne .ettinos
|
||||
mov cx, 11
|
||||
mov bx, kernel_name
|
||||
|
||||
mov ax, [si + 26] ; First cluster
|
||||
mov [kernel_cluster], ax
|
||||
.compare:
|
||||
lodsb
|
||||
cmp al, [bx]
|
||||
jne .nomatch
|
||||
inc bx
|
||||
loop .compare
|
||||
|
||||
jmp .skipentry
|
||||
jmp found
|
||||
|
||||
.ettinos:
|
||||
mov cx, 11
|
||||
mov bx, ettinos_kernel_name
|
||||
|
||||
.compare:
|
||||
lodsb
|
||||
cmp al, [bx]
|
||||
jne .nextentry
|
||||
inc bx
|
||||
loop .compare
|
||||
|
||||
; SI points to 11 bytes after the start of the
|
||||
; entry, so adjust offset
|
||||
mov ax, [si - 11 + 26] ; First cluster
|
||||
mov [ettinos_kernel_cluster], ax
|
||||
|
||||
inc cx ; Offset so that falling through will work
|
||||
|
||||
.nextentry:
|
||||
.nomatch:
|
||||
; Each entry is 32 bytes long
|
||||
; During each iteration of the compare loop, si is
|
||||
; incremented and cx is decremented
|
||||
|
@ -180,47 +186,20 @@ search_root:
|
|||
|
||||
.end:
|
||||
|
||||
which_found:
|
||||
mov bx, [kernel_cluster]
|
||||
mov cx, [ettinos_kernel_cluster]
|
||||
|
||||
test bx, bx
|
||||
jz .no_nor86
|
||||
test cx, cx
|
||||
jz found
|
||||
|
||||
mov si, choose_msg
|
||||
.loop:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .end
|
||||
|
||||
mov ah, 0xe
|
||||
int 0x10
|
||||
jmp .loop
|
||||
|
||||
.end:
|
||||
|
||||
xor ax, ax
|
||||
int 0x16
|
||||
|
||||
cmp ah, 0x12 ; E-key
|
||||
je found_cx
|
||||
jmp found
|
||||
|
||||
.no_nor86:
|
||||
test cx, cx
|
||||
jnz found_cx
|
||||
|
||||
notfound:
|
||||
mov si, notfound_msg
|
||||
jmp fatal_error
|
||||
; TODO: Better error messages
|
||||
mov ax, 0x0e00 + '?'
|
||||
int 0x10
|
||||
|
||||
found_cx:
|
||||
mov bx, cx
|
||||
hang:
|
||||
hlt
|
||||
jmp hang
|
||||
|
||||
found:
|
||||
mov ax, bx
|
||||
; SI points to 11 bytes after the start of the entry, so adjust all
|
||||
; offsets
|
||||
; TODO: Handle zero-length files
|
||||
mov ax, [si - 11 + 26] ; First cluster
|
||||
push ax
|
||||
|
||||
; Load OS at the start of the memory
|
||||
|
@ -231,8 +210,7 @@ found:
|
|||
.tosector:
|
||||
; Adjust the cluster number to account for first two
|
||||
; "clusters" in the FAT being used for metadata
|
||||
dec ax
|
||||
dec ax
|
||||
sub ax, 2
|
||||
|
||||
; Scale by number of sectors per cluster
|
||||
xor bx, bx
|
||||
|
@ -243,12 +221,27 @@ found:
|
|||
add ax, [rootdir]
|
||||
add ax, [rootdirsectors]
|
||||
|
||||
.load:
|
||||
; Load sectors
|
||||
pop bx
|
||||
xor cx, cx
|
||||
mov cl, [sectorspercluster]
|
||||
call loadsectors
|
||||
; Load sectors
|
||||
pop bx
|
||||
xor cx, cx
|
||||
mov cl, [sectorspercluster]
|
||||
mov dl, [drivenumber]
|
||||
.loop:
|
||||
push ax
|
||||
push cx
|
||||
|
||||
call chs
|
||||
|
||||
mov ah, 2
|
||||
mov al, 1
|
||||
int 0x13
|
||||
|
||||
pop cx
|
||||
pop ax
|
||||
|
||||
add bx, 512
|
||||
inc ax
|
||||
loop .loop
|
||||
|
||||
.next:
|
||||
pop ax
|
||||
|
@ -271,7 +264,11 @@ found:
|
|||
; ^ where we start reading on odd cluster numbers
|
||||
; ^^^^^ loading word: 0xXYZA
|
||||
test ax, 1
|
||||
jz .even
|
||||
jnz .odd
|
||||
|
||||
.even:
|
||||
and dx, 0x0fff
|
||||
jmp .check_cluster
|
||||
|
||||
.odd:
|
||||
shr dx, 1
|
||||
|
@ -279,9 +276,6 @@ found:
|
|||
shr dx, 1
|
||||
shr dx, 1
|
||||
|
||||
.even:
|
||||
and dx, 0x0fff
|
||||
|
||||
.check_cluster:
|
||||
mov ax, dx
|
||||
|
||||
|
@ -297,102 +291,51 @@ execute_kernel:
|
|||
mov dl, [drivenumber]
|
||||
jmp 0:0x500
|
||||
|
||||
; Note: bx will point to after the read data
|
||||
; Note: ax, cx, dx, and di will be clobbered
|
||||
loadsectors:
|
||||
chs:
|
||||
push ax
|
||||
push bx
|
||||
|
||||
.loop:
|
||||
mov di, 3 + 1 ; Retry thrice, + 1 is since we dec first
|
||||
; Save drive number
|
||||
mov bl, dl
|
||||
|
||||
.retry:
|
||||
xor dx, dx
|
||||
; cylinder (track) - head - sector
|
||||
; cylinder = LBA / sectorspertrack / heads
|
||||
; head = LBA / sectorspertrack % heads
|
||||
; sector = LBA % sectorspertrack + 1
|
||||
div word [sectorspertrack]
|
||||
; ax = LBA / sectorspertrack
|
||||
; dx = LBA % sectorspertrack
|
||||
|
||||
push ax
|
||||
push cx
|
||||
; sector
|
||||
mov cl, dl
|
||||
inc cl
|
||||
|
||||
.chs:
|
||||
xor dx, dx
|
||||
; cylinder (track) - head - sector
|
||||
; cylinder = LBA / sectorspertrack / heads
|
||||
; head = LBA / sectorspertrack % heads
|
||||
; sector = LBA % sectorspertrack + 1
|
||||
div word [sectorspertrack]
|
||||
; ax = LBA / sectorspertrack
|
||||
; dx = LBA % sectorspertrack
|
||||
xor dx, dx
|
||||
div word [heads]
|
||||
; ax = LBA / sectorspertrack / heads
|
||||
; dx = LBA / sectorspertrack % heads
|
||||
|
||||
; sector
|
||||
mov cl, dl
|
||||
inc cl
|
||||
; head
|
||||
mov dh, dl
|
||||
|
||||
xor dx, dx
|
||||
div word [heads]
|
||||
; ax = LBA / sectorspertrack / heads
|
||||
; dx = LBA / sectorspertrack % heads
|
||||
; cylinder (track)
|
||||
mov ch, al
|
||||
;shr ax, 1
|
||||
;shr ax, 1
|
||||
;and al, 0xC0
|
||||
;or cl, al
|
||||
|
||||
; head
|
||||
mov dh, dl
|
||||
|
||||
; cylinder (track)
|
||||
mov ch, al
|
||||
;shr ax, 1
|
||||
;shr ax, 1
|
||||
;and al, 0xC0
|
||||
;or cl, al
|
||||
|
||||
mov ax, 0x0201
|
||||
mov dl, [drivenumber]
|
||||
int 0x13
|
||||
|
||||
jc .error
|
||||
|
||||
mov ax, 0x0e00 + '.'
|
||||
int 0x10
|
||||
|
||||
pop cx
|
||||
pop ax
|
||||
|
||||
inc ax
|
||||
add bx, 512
|
||||
|
||||
loop .loop
|
||||
; Restore drive number
|
||||
mov dl, bl
|
||||
|
||||
pop bx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
.error:
|
||||
; Do we still have retries remaining?
|
||||
mov si, diskerror_msg
|
||||
dec di
|
||||
jz fatal_error ; No, fail
|
||||
|
||||
; Yes, reset disk
|
||||
xor ah, ah
|
||||
int 0x13
|
||||
|
||||
; Execute the loop again
|
||||
pop cx
|
||||
pop ax
|
||||
jmp .retry
|
||||
|
||||
fatal_error:
|
||||
mov cx, 9
|
||||
.loop:
|
||||
lodsb
|
||||
mov ah, 0xe
|
||||
int 0x10
|
||||
loop .loop
|
||||
|
||||
hang:
|
||||
hlt
|
||||
jmp hang
|
||||
|
||||
|
||||
kernel_cluster dw 0
|
||||
ettinos_kernel_cluster dw 0
|
||||
|
||||
ettinos_kernel_name db "SYSTEM BIN"
|
||||
|
||||
notfound_msg db "No kernel"
|
||||
diskerror_msg db "Disk error"
|
||||
choose_msg db 13, 10, "EttinOS/Nor86?", 0
|
||||
prompt: db "Select OS. 'e' for EttinOS, any other key Nor86.", 0
|
||||
kernel_name: db "KERNEL BIN"
|
||||
ettinos_kernel_name: db "SYSTEM BIN"
|
||||
|
||||
times 510-($-$$) db 0
|
||||
db 0x55, 0xaa
|
39
console.inc
39
console.inc
|
@ -1,39 +0,0 @@
|
|||
; IN:
|
||||
; ds:si = start of asciz string
|
||||
printz:
|
||||
push ax
|
||||
push si
|
||||
|
||||
.loop:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .end
|
||||
|
||||
call printc
|
||||
|
||||
jmp .loop
|
||||
|
||||
.end:
|
||||
|
||||
pop si
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; IN:
|
||||
; al = cp437 character
|
||||
printc:
|
||||
push ax
|
||||
|
||||
cmp al, 10
|
||||
jne .output
|
||||
|
||||
mov ax, 0x0e0d
|
||||
int 0x10
|
||||
mov al, 10
|
||||
|
||||
.output:
|
||||
mov ah, 0xe
|
||||
int 0x10
|
||||
|
||||
pop ax
|
||||
ret
|
|
@ -0,0 +1,32 @@
|
|||
hexprint16:
|
||||
xchg ah, al
|
||||
call hexprint8
|
||||
xchg ah, al
|
||||
|
||||
hexprint8:
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
mov cl, al
|
||||
xor bx, bx
|
||||
|
||||
mov ah, 0xe
|
||||
shr al, 1
|
||||
shr al, 1
|
||||
shr al, 1
|
||||
shr al, 1
|
||||
mov bl, al
|
||||
mov al, [.digits + bx]
|
||||
int 0x10
|
||||
|
||||
mov bl, 0xf
|
||||
and bl, cl
|
||||
mov al, [.digits + bx]
|
||||
int 0x10
|
||||
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
.digits: db '0123456789abcdef'
|
46
kernel.asm
46
kernel.asm
|
@ -1,50 +1,8 @@
|
|||
cpu 8086
|
||||
org 0x500
|
||||
|
||||
greet:
|
||||
mov si, kernel_greeting
|
||||
call printz
|
||||
|
||||
mov al, dl
|
||||
add al, '0'
|
||||
call printc
|
||||
mov al, 10
|
||||
call printc
|
||||
|
||||
memsize:
|
||||
; Get and display memory size
|
||||
int 0x12
|
||||
mov bx, buffer
|
||||
call itoa
|
||||
|
||||
mov si, bx
|
||||
call printz
|
||||
mov si, memsize_trailer
|
||||
call printz
|
||||
|
||||
floppies:
|
||||
; Get and display number of floppy disks
|
||||
int 0x11
|
||||
times 6 shr ax, 1
|
||||
and ax, 3
|
||||
inc ax
|
||||
|
||||
add al, '0'
|
||||
call printc
|
||||
|
||||
mov si, floppies_trailer
|
||||
call printz
|
||||
mov ax, 0x0e40
|
||||
int 0x10
|
||||
|
||||
hang:
|
||||
hlt
|
||||
jmp hang
|
||||
|
||||
%include "console.inc"
|
||||
%include "printhex.inc"
|
||||
%include "strint.inc"
|
||||
|
||||
kernel_greeting db 10, "Nor86 kernel succesfully loaded", 10, "Loaded from disk ", 0
|
||||
memsize_trailer db "k RAM", 10, 0
|
||||
floppies_trailer db " floppy drive(s)", 10, 0
|
||||
|
||||
buffer times 256 db 0
|
||||
|
|
36
printhex.inc
36
printhex.inc
|
@ -1,36 +0,0 @@
|
|||
; IN:
|
||||
; ax = hex value
|
||||
printh16:
|
||||
xchg ah, al
|
||||
call printh8
|
||||
xchg ah, al
|
||||
|
||||
; IN:
|
||||
; al = hex value
|
||||
printh8:
|
||||
push ax
|
||||
mov ah, al
|
||||
|
||||
shr al, 1
|
||||
shr al, 1
|
||||
shr al, 1
|
||||
shr al, 1
|
||||
call .printh4
|
||||
|
||||
mov al, 0xf
|
||||
and al, ah
|
||||
call .printh4
|
||||
|
||||
pop ax
|
||||
ret
|
||||
|
||||
.printh4:
|
||||
cmp al, 10
|
||||
jb .numeric
|
||||
|
||||
add al, 'a' - 10
|
||||
jmp printc
|
||||
|
||||
.numeric:
|
||||
add al, '0'
|
||||
jmp printc
|
33
strint.inc
33
strint.inc
|
@ -1,33 +0,0 @@
|
|||
; IN:
|
||||
; ax = number to convert
|
||||
; ds:bx = storage buffer
|
||||
; OUT:
|
||||
; ds:bx = start of converted number
|
||||
itoa:
|
||||
push ax
|
||||
push cx
|
||||
push dx
|
||||
|
||||
mov cx, 10
|
||||
|
||||
add bx, 5
|
||||
mov byte [bx], 0
|
||||
|
||||
.convert_loop:
|
||||
test ax, ax
|
||||
jz .end
|
||||
|
||||
xor dx, dx
|
||||
div cx
|
||||
|
||||
add dl, '0'
|
||||
dec bx
|
||||
mov byte [bx], dl
|
||||
|
||||
jmp .convert_loop
|
||||
|
||||
.end:
|
||||
pop dx
|
||||
pop cx
|
||||
pop ax
|
||||
ret
|
Loading…
Reference in New Issue