My bootloader crashes while reading the root directory
Posted: Thu Jan 11, 2018 2:20 am
Hello, after loading the to size of the root directory size and start into cx, ax respectively, i face a problem while trying to read it using readSector proc. the bootloader crashes and give me this error and QEMU closes.
this is my code and make file
the execution never reaches the line after calling readSector procedure. Whats wrong?
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