this is my code and make file
Code: Select all
jmp entery_point
;*********************************************
; BIOS Parameters Block
;********************************************
bytesPerSector dw 512
sectorsPerCluster db 1
reservedSectors dw 1
numberOfFATs db 2
rootEntries dw 244
totalSectors dw 2880
media db 0xF0
sectorsPerFAT dw 9
sectorsPerTrack dw 18
headsPerCylinder dw 2
hiddenSectors dd 0
totalSectorsBig dd 0
driveNumber db 0
unused db 0
extBootSignature db 0x29
serialNumber dd 0xa0a1a1a6
volumeLabel db "MY FLOPPY"
fileSystem db "FAT 12"
;********************************************
; FUNCTIONS AND PROCS
;*******************************************
regs_init:
;;setting up the stack
cli
xor ax, ax
mov ss, ax
mov sp, 0xFFFF
sti
;;setting up the segment registers
mov ax, 0x07C0
mov ds, ax
mov es, ax
jmp back
;;print procedure
print:
lodsb
or al, al
jz done
mov ah, 0x0E
int 0x10
jmp print
done:
ret
;;disk reset function
disk_reset:
mov ah, 0 ;resetting function code
mov dl, 0 ;drive to reset. 0 represents the floppy drive
int 0x13
ret
load_root_dir:
;; computing the root directory size
;; its equals to [rootEntries*the size of each entery (32 byte)] / the size of one sector
xor dx, dx
xor cx, cx
mov ax, 0x0020
mul WORD [rootEntries]
div WORD [bytesPerSector]
;mov WORD [rootDirSize], ax
xchg ax, cx
;; computing the first cluster of the root directory
;; according to the geometry of FAT12, the rootdir comes after
;; the FAT tabels, the reserved and the hidden sectors
;; thus its equal to numberOfFATs*sectorsPerFAT + reservedSectors + hiddenSectors
mov al, BYTE [numberOfFATs]
mul WORD [sectorsPerFAT]
add ax, WORD [reservedSectors]
; add ax, WORD [hiddenSectors]
mov WORD [rootDirStart], ax
; add ax, WORD [rootDirSize]
mov WORD [dataSectionStart], ax
add WORD [dataSectionStart], cx
ret
;********************************************************
; READ SECTORS FUNCTION
; CX = NUMBER OF SECTORS TO READ
; AX = NUMBER OF SECTORS TO READ
; ES:BS = BUFFER TO READ TO, DEFAULT FOR INT 0x13
;*********************************************************
readSectors:
main_read_loop:
mov di, 0x0003 ;try 3 times before returning failure
sector_read_loop:
push ax
push cx
push bx
call LBAtoCHS
mov ah, 0x02 ;function code for reading a sector
mov al, 0x01 ;read one sector
mov ch, BYTE [CHSTrack] ;track to read
mov cl, BYTE [CHSSector] ;sector to read
mov dh, BYTE [CHSHead] ;head to read
mov dl, BYTE [driveNumber] ;drive number to read from, refer the BPB
int 0x13 ;call the function
jnc read_done
call disk_reset ;if there is an error, reset the disk and try again
dec di ;decrese the trial counter by 1
pop ax
pop cx
pop bx
jnz sector_read_loop
read_done:
pop ax
pop cx
pop bx
add bx, WORD [bytesPerSector] ;move the saving buffer into a new unused memory address
inc ax ;increase the sector to be read
loop main_read_loop
ret
;**********************************************************************
; LBA TO CHS CONVERSION
; AX = LBA TO BE CONVERTED
; CHSTrack = (LBA SECTOR / sectorsPerTrack) / + 1
; CHSHead = (LBA SECTOR / sectorsPerTrack) % headsPerCylinder
; CHSSector= (LBA SECTOR / [sectorsPerTrack * headsPerCylinder])
;************************************************************************
LBAtoCHS:
xor dx, dx ;reset dx and prepare it to save the value bx:ax
div WORD [sectorsPerTrack] ;divide the value in ax by sectors per track and store the result at bx:ax
inc dl ;add one to dl
mov BYTE [CHSSector], dl
xor dx, dx
div WORD [headsPerCylinder]
mov BYTE [CHSHead], dl
mov BYTE [CHSTrack], al
ret
;***************************************************
; CHS TO LBA CONVERSION
; LBA = (CLUSTER - 2) * sectorsPerCluster
;***************************************************
ClustersLBA:
sub ax, 0x0002 ;subtract 2 from the cluster number
mov cx, 0x0000 ;clear cx
mov cl, BYTE [sectorsPerCluster]
mul cx ;multiply cx by ax and store the value in ax
add ax, WORD [dataSectionStart] ;adds the start of the data sector to the LBA address
ret
;*****************************************************
; THE BOOTLOADER BODY
;****************************************************
entery_point:
jmp regs_init
back:
call disk_reset ;resets the disk and make it ready for reading
; #############################################
; STAGE 1, LOAD THE ROOT DIR
; ############################################
call load_root_dir ;load the root directory
;the root dir info are stored at rootDirSize, rootDirStart
;;move the valuse of the root dir info into register AX, CX to read the root dir using readSectors function
; mov cx, WORD [rootDirSize]
; mov ax, WORD [dataSectionStart]
;;Load the root directory into ES:BX
;;ES is 0x7C00, set BX to be 0x0020
mov bx, 0x0200
call readSectors
;the execution never reaches this line
mov si, msgd
call print
; ###########################################
; STAGE 2, FIND THE NEXT STAGE
; ##########################################
; now the root dir contents are loaded, all i have to do is to look for the second stage name
; cmpsb's logic is cmp (DS:SI), (ES:DI)
mov cx, WORD [rootEntries]
mov di, 0x0020 ;where our root dir is loaded
search_stage2_loop:
push cx
mov cx, 0x000B ;11 character for the file name
mov si, fileName
push di
rep cmpsb
pop di
je loadFAT
pop cx
add di, 0x0020 ;32 byte entry, move to the next entry
loop search_stage2_loop
jmp stage2_not_found
loadFAT:
mov si, msgd
call print
jmp exit
stage2_not_found:
mov si, msgd
call print
exit:
cli
hlt
;*******************************************************
; VARIABELS SECTION
;*******************************************************
CHSTrack db 0
CHSSector db 0
CHSHead db 0
dataSectionStart dw 0
fileName db "NDBOOT SYS"
kernelStartingSector dw 0
rootDirSize dw 0
rootDirStart dw 0
msgd db "Finally ",0
times 510 - ($-$$) db 0
dw 0xAA55
Code: Select all
ASM = nasm
INPUT = "bootloader.nasm"
BIN = "loader.bin"
IMG = "img.img"
STAGE2 = "NDBOOT.SYS"
Bootloader: create_bin create_floppy
dd if=$(BIN) bs=512 of=$(IMG) conv=notrunc
create_bin:
$(ASM) -f bin $(INPUT) -o $(BIN) -g
create_floppy:
dd if=/dev/zero bs=512 count=2880 of=$(IMG)
mkdosfs $(IMG)
mcopy -i $(IMG) $(STAGE2) ::/$(STAGE2)
mdir -i img.img
run:
qemu-system-i386 -fda $(IMG)
clean:
rm img.img loader.bin