My FirstOS
Posted: Thu Oct 27, 2011 5:20 pm
Hey anyone who wants to feel free to test this bootloader. I made it from the ground up. I would be particularly interested in ways to improve the code. It comes with a simple kernel that prints a message and hangs. You may certainly substitute your own kernel. Tested in Bochs, not on real hardware yet.
Outline:
KERNEL.BIN loads and begins execution at 0x1000:0x0000 in real mode. ds and es are 0x1000, ax, bx, cx, dx, di and si are 0x0000. The screen is in text mode, and filled with spaces with color attribute 0x07. The cursor is at the top left corner of the screen.
Floppy image: floppy.img
Bootloader (MASM):
Kernel (MASM):
Outline:
KERNEL.BIN loads and begins execution at 0x1000:0x0000 in real mode. ds and es are 0x1000, ax, bx, cx, dx, di and si are 0x0000. The screen is in text mode, and filled with spaces with color attribute 0x07. The cursor is at the top left corner of the screen.
Floppy image: floppy.img
Bootloader (MASM):
Code: Select all
.186
.model small
.code
kernel segment at 1000h
org 0
start label far
kernel ends
org 7c00h
first:
jmp short Main
nop
OSName db "FIRSTOS "
BytesPerSector dw 512
SectorsPerCluster db 1
ReservedSectors dw 1
NumberOfFATs db 2
RootDirEntries dw 224
NumberOfSectors dw 2880
MediaType db 0f0h
SectorsPerFAT dw 9
SectorsPerTrack dw 18
NumberOfHeads dw 2
HiddenSectors dd 0
DWSectors dd 0
DriveNumber db 0
Reserved db 0
BootSignature db 29h
SerialNumber dd 0
VolumeLabel db "FOSBOOTDISK"
FileSystem db "FAT12 "
Main:
; set up segments & stack
cli
xor ax, ax
mov ds, ax
mov es, ax
jmp es:MainSetCS
MainSetCS:
mov ss, ax
mov sp, 0f000h
sti
; load root directory
mov ax, 0500h
mov es, ax
mov cx, 4
MainRetryRoot:
push cx
xor ax, ax
mov al, [NumberOfFATs]
mul [SectorsPerFAT]
add ax, [ReservedSectors]
mov [LBAFirstData], ax
call LBAToCHS
mov ax, 0020h
push dx
mul [RootDirEntries]
div [BytesPerSector]
pop dx
add [LBAFirstData], ax
mov ah, 02h
xor bx, bx
int 13h
pop cx
jnc MainSuccessRoot
loop MainRetryRoot
int 18h
MainSuccessRoot:
; read root directory
mov cx, [RootDirEntries]
xor di, di
MainNextEntry:
push cx
mov cx, 11
mov si, offset KernelFile
push di
repe cmpsb
pop di
pop cx
je MainEntryFound
add di, 0020h
loop MainNextEntry
int 18h
MainEntryFound:
add di, 26
mov ax, es:[di]
mov [Cluster], ax
; load FAT
mov cx, 4
MainRetryFAT:
push cx
mov ax, [ReservedSectors]
call LBAToCHS
mov ax, [SectorsPerFAT]
mov ah, 02h
int 13h
pop cx
jnc MainSuccessFAT
loop MainRetryFAT
int 18h
MainSuccessFAT:
; read FAT and load clusters
MainReadCluster:
mov ax, 1000h
mov es, ax
mov cx, 4
MainRetryCluster:
push cx
mov ax, [Cluster]
sub ax, 2
xor dx, dx
mov dl, [SectorsPerCluster]
mul dx
add ax, [LBAFirstData]
call LBAToCHS
mov al, [SectorsPerCluster]
mov ah, 02h
int 13h
pop cx
jnc MainNextCluster
loop MainRetryCluster
int 18h
MainNextCluster:
mov ax, 0500h
mov es, ax
mov ax, [Cluster]
mov dx, ax
shr ax, 1
add ax, dx
push bx
mov bx, ax
mov ax, es:[bx]
pop bx
test dx, 0001h
jnz MainOddCluster
and ax, 0fffh
jmp MainClusterNumber
MainOddCluster:
shr ax, 4
MainClusterNumber:
add bx, [BytesPerSector]
mov [Cluster], ax
cmp ax, 0ff0h
jb MainReadCluster
; clear screen and move cursor
mov ax, 0b800h
mov es, ax
mov ax, 0720h
xor bx, bx
MainNextChar:
mov es:[bx], ax
add bx, 2
cmp bx, 4000
jb MainNextChar
xor bx, bx
xor dx, dx
mov ah, 02h
int 10h
; set up registers and call kernel
mov ax, kernel
mov ds, ax
mov es, ax
xor ax, ax
xor bx, bx
xor cx, cx
xor dx, dx
xor di, di
jmp kernel:start
LBAToCHS:
xor dx, dx
div [SectorsPerTrack]
mov cl, dl
inc cl
xor dx, dx
div [NumberOfHeads]
mov ch, al
mov dh, dl
mov dl, [DriveNumber]
ret
KernelFile db "KERNEL BIN"
LBAFirstData dw 0
Cluster dw 0
;db (510 - ($ - first)) dup (0)
;dw 0aa55h
end
Code: Select all
.model tiny
.code
mov si, offset msg
Next:
lodsb
or al, al
jz Done
mov ah, 0eh
int 10h
jmp Next
Done:
jmp $
msg db "In the kernel! :)", 0
end