我正在滚动自己的简单的两阶段引导加载程序以加载到我最近编写的内核中。到目前为止,这是一段很棒的经历,而且我学到了很多东西,这些东西我认为是最有用的第一阶段。但是在程序的早期,尝试加载到我的FAT12文件系统的根目录中时,中断0x13反复失败。
通过几次打印调用,我设法缩小了问题的范围,以找出扇区读取子例程中发生的错误,下面将在其中进行介绍。我做了很多挖掘工作,以确保可以在程序开始时正确设置段以及所有实际读取之前的参数和功能。
为澄清起见,此问题与其他类似的问题不同之处在于,在大多数情况下,INT13H读取成功(即,进位位设置为0),然后问题进一步出现。在我的情况下,无论如何,INT13都会设置进位。
我正在QEMU中进行仿真,并且一直在使用GDB来帮助调试过程。
我的主程序从org 0x0开始,然后我进一步设置了适当的段位置(看到它在网上的几个地方都没问题,发现它看起来更干净)
cli
mov ax, 0x07C0
mov ds, ax
mov es, ax ; ES gets set here
mov fs, ax
mov gs, ax
; Create the stack
mov ax, 0x8000
mov ss, ax
xor ax, ax
mov sp, ax
sti
接着,我为函数调用设置参数:
; CX = size of the root directory in sectors
xor cx, cx
xor dx, dx
mov ax, 0x0020
mul word [bpbNumRootEntries]
div word [bpbBytesPerSector]
xchg ax, cx
; AX = where the root directory begins. BX = offset for ES:BX
mov al, byte [bpbNumberOfFATs]
mul word [bpbSectorsPerFAT]
add ax, word [bpbNumReservedSectors]
mov bx, 0x0200 ; Root dir. goes directly below code
调用一次(参数设置后立即执行),功能如下。我将整个过程包括在内:我发现这很难调试,并且怀疑这可能是一个很小的问题。
ReadSectors:
.begin
mov di, 0x000A
.loop
push ax
push bx
push cx
call LBACHS ; Converts LBA -> CHS
mov ah, 0x02
mov al, 0x01
mov ch, byte [absoluteTrack]
mov cl, byte [absoluteSector]
mov dh, byte [absoluteHead]
mov dl, byte [bpbDriveNumber]
int 0x13
jnc .finish
mov si, progmsg ; Keeps printing -> INT13H failing
call Print
xor ax, ax
int 0x13
dec di
pop cx
pop bx
pop ax
jnz .loop
jmp Failure
.finish
pop cx pop bx
pop ax
add bx, word [bpbBytesPerSector]
inc ax
loop .begin
ret
我正在使用NASM编译为二进制格式,然后通过dd将其闪存到具有FAT12文件系统的软盘中-通过QEMU从其启动。使用虚拟磁盘或仅使用-fda二进制文件会产生相同的问题。
sudo dd if=bootfirst.bin bs=512 of=/dev/disk2
sudo qemu-system-x86_64 -device floppy /dev/disk2
对于能解决此问题的任何见解,我将不胜感激,并愿意根据需要进行更大的更改。谢谢!