289 lines
5.1 KiB
NASM
289 lines
5.1 KiB
NASM
cpu 8086
|
|
org 0x7c00
|
|
|
|
;Jump to the code
|
|
jmp start
|
|
|
|
;Padding
|
|
nop
|
|
|
|
;OEM label
|
|
db "ETTINOS "
|
|
|
|
%ifdef F1440
|
|
|
|
;1.44 MB 3.5" floppy disk BPB (enable with the argument -d F1440)
|
|
sectorsize dw 0x200 ;bytes
|
|
clustersize db 0x1 ;sectors
|
|
reservedsectors dw 0x1
|
|
fats db 0x2
|
|
rootentries dw 0xe0
|
|
logicalsectors dw 0xb40
|
|
mediadescriptor db 0xf0
|
|
sectorsperfat dw 0x9
|
|
sectorspertrack dw 0x12
|
|
heads dw 0x2
|
|
|
|
%else
|
|
|
|
;360 KiB 5.25" floppy disk BPB (default)
|
|
sectorsize dw 0x200 ;bytes
|
|
clustersize db 0x2 ;sectors
|
|
reservedsectors dw 0x1
|
|
fats db 0x2
|
|
rootentries dw 0x70
|
|
logicalsectors dw 0x2d0
|
|
mediadescriptor db 0xfd
|
|
sectorsperfat dw 0x2
|
|
sectorspertrack dw 0x9
|
|
heads dw 0x2
|
|
|
|
%endif
|
|
|
|
|
|
;Setup
|
|
;Set the segments
|
|
start:
|
|
mov ax, 0x0
|
|
mov ds, ax
|
|
mov ss, ax
|
|
mov es, ax
|
|
;Set the stack
|
|
cli
|
|
mov sp, 0x0
|
|
sti
|
|
;Store the boot drive number
|
|
mov [drive], dl
|
|
|
|
;Calculate and store variables not found in the BPB
|
|
;Start of the root
|
|
mov ah, 0x0
|
|
mov al, [fats]
|
|
mul word [sectorsperfat]
|
|
add ax, [reservedsectors]
|
|
mov [rootstart], ax
|
|
;Size of the root in sectors
|
|
mov ax, [rootentries]
|
|
mov dx, 0x20
|
|
mul dx
|
|
mov dx, 0x0
|
|
div word [sectorsize]
|
|
mov [rootsectors], ax
|
|
;Start of data
|
|
add ax, [rootstart]
|
|
mov [datastart], ax
|
|
|
|
;Load the root
|
|
;Set the source
|
|
mov ax, [rootstart]
|
|
;Set the destination
|
|
mov si, buffer
|
|
mov bx, si
|
|
;Set the size
|
|
mov cx, [rootsectors]
|
|
;Store the source and the loop counter in the stack
|
|
loadrootsector:
|
|
push ax
|
|
push cx
|
|
;Set the source
|
|
call calcsource
|
|
;Set the size
|
|
mov al, 0x1
|
|
;Load a sector
|
|
mov ah, 0x2
|
|
int 0x13
|
|
;Load the loop counter and the source from the stack
|
|
pop cx
|
|
pop ax
|
|
;Set the next sector
|
|
add ax, 0x1
|
|
add bx, word [sectorsize]
|
|
;Load the next sector
|
|
loop loadrootsector
|
|
|
|
;Search the root for the system entry
|
|
;Set DI to the root
|
|
mov di, buffer
|
|
;Set the number of root entries
|
|
mov cx, word [rootentries]
|
|
;Set the entry pointer
|
|
mov ax, 0x0
|
|
;Store the loop counter in the stack
|
|
search:
|
|
push cx
|
|
;Check for the system entry
|
|
mov si, file
|
|
mov cx, 0xb
|
|
rep cmpsb
|
|
je loadfat
|
|
;Set DI at the next entry
|
|
add ax, 0x20
|
|
mov di, buffer
|
|
add di, ax
|
|
;Load the loop counter from the stack
|
|
pop cx
|
|
;Search the next entry
|
|
loop search
|
|
|
|
;Print an error message and hang if the system is not found
|
|
;Set SI at the file error message
|
|
mov si, filerrormsg
|
|
;Load a character
|
|
printstr:
|
|
lodsb
|
|
;Check for the string end
|
|
cmp al, 0x0
|
|
je $
|
|
;Print the character
|
|
mov ah, 0xe
|
|
int 0x10
|
|
;Print the next character
|
|
jmp printstr
|
|
|
|
;Load the FAT
|
|
;Load CX from the stack
|
|
loadfat:
|
|
pop cx
|
|
;Store the address of the first cluster
|
|
mov ax, [di + 0xf]
|
|
mov [cluster], ax
|
|
;Set the source
|
|
mov ax, [reservedsectors]
|
|
call calcsource
|
|
;Set the destination
|
|
mov bx, buffer
|
|
;Set the size
|
|
mov ax, [sectorsperfat]
|
|
;Load the FAT
|
|
mov ah, 0x2
|
|
int 0x13
|
|
|
|
;Load a cluster
|
|
loadcluster:
|
|
;Set the source
|
|
mov ax, word [cluster]
|
|
sub ax, 0x2
|
|
mul byte [clustersize]
|
|
add ax, [datastart]
|
|
;Set the destination
|
|
mov bx, word [pointer]
|
|
;Set the size
|
|
mov ch, 0x0
|
|
mov cl, byte [clustersize]
|
|
;Store the loop counter in the stack
|
|
loadclustersector:
|
|
push cx
|
|
;Set the source
|
|
call calcsource
|
|
;Set the size
|
|
push ax
|
|
mov al, 0x1
|
|
;Load a sector
|
|
mov ah, 0x2
|
|
int 0x13
|
|
pop ax
|
|
;Set the next sector
|
|
add ax, 0x1
|
|
add bx, [sectorsize]
|
|
;Load the loop counter from the stack
|
|
pop cx
|
|
;Load the next sector
|
|
loop loadclustersector
|
|
|
|
;Calculate the next cluster
|
|
;Check if the cluster is even or odd
|
|
mov ax, [cluster]
|
|
mov dx, 0x0
|
|
mov bx, 0x3
|
|
mul bx
|
|
mov bx, 0x2
|
|
div bx
|
|
mov si, buffer
|
|
add si, ax
|
|
mov ax, word [si]
|
|
or dx, dx
|
|
jz even
|
|
;If the cluster is odd shift out the first four bits
|
|
times 0x4 shr ax, 0x1
|
|
jmp contcalc
|
|
;If the cluster is even mask out the final four bits
|
|
even:
|
|
and ax, 0xfff
|
|
contcalc:
|
|
;Check for the file end
|
|
cmp ax, 0xff8
|
|
jge boot
|
|
;Store the address of the next cluster
|
|
mov word [cluster], ax
|
|
;Set the destination of the next cluster
|
|
mov ax, [sectorsize]
|
|
mul word [clustersize]
|
|
add word [pointer], ax
|
|
;Load the next cluster
|
|
jmp loadcluster
|
|
|
|
;Boot the system
|
|
;Pass the boot drive number to the system
|
|
boot:
|
|
mov dl, byte [drive]
|
|
;Boot the system
|
|
jmp 0x0:0x500
|
|
|
|
;Data
|
|
drive db 0x0
|
|
rootstart dw 0x0
|
|
rootsectors dw 0x0
|
|
datastart dw 0x0
|
|
file db "SYSTEM BIN"
|
|
filerrormsg db "System not found", 0xd, 0xa, 0x0
|
|
cluster dw 0x0
|
|
pointer dw 0x500
|
|
|
|
;***
|
|
|
|
;Calculate the source arguments for loading data from the disk
|
|
calcsource:
|
|
|
|
;Store AX and BX in the stack
|
|
push ax
|
|
push bx
|
|
|
|
;Calculate the cylinder, head, and sector
|
|
;Store the logical sector in BX
|
|
mov bx, ax
|
|
;Calculate the sector
|
|
mov dx, 0x0
|
|
div word [sectorspertrack]
|
|
add dl, 0x1
|
|
mov cl, dl
|
|
;Load the logical sector from BX
|
|
mov ax, bx
|
|
;Calculate the head and cylinder
|
|
mov dx, 0x0
|
|
div word [sectorspertrack]
|
|
mov dx, 0x0
|
|
div word [heads]
|
|
mov dh, dl ;Head
|
|
mov ch, al ;Cylinder
|
|
|
|
;Load the boot drive number
|
|
mov dl, byte [drive]
|
|
|
|
;Load BX and AX from the stack
|
|
pop bx
|
|
pop ax
|
|
|
|
;Return
|
|
ret
|
|
|
|
;***
|
|
|
|
;Padding
|
|
times 0x1fe-($-$$) db 0x0
|
|
|
|
;Boot signature
|
|
dw 0xaa55
|
|
|
|
;File system buffer
|
|
buffer:
|