我写了一个引导加载程序,但它总是跳到我写的失败部分,并且不加载我的stage 2



我写了一个引导加载程序,它应该加载我的KRNLDR。SYS在FAT12格式的img文件上。但它不起作用

我用来创建它的命令:

nasm -fbin -o boot.bin boot.asm
dd if=/dev/zero of=test.img bs=512 count=2880
sudo losetup /dev/loop0 test.img
sudo mkdosfs -F 12 /dev/loop0

现在,我的系统识别并安装了设备,然后我放上了KRNLDR。上的SYS

然后我执行:

sudo dd if=boot.bin of=/dev/loop0 bs=512 count=1 conv=notrunc
sudo umount /dev/loop0
sudo losetup -d /dev/loop0

现在,该文件看起来像FAT12软盘,带有引导扇区和文件KRNLDR。系统

现在我在QEMU:中执行它

qemu-system-i386 -device format=raw,file=test.img 

输出:

Operating System not found
Press any key to reboot

如果文件KRNLDR,这是我的引导加载程序打印到屏幕上的输出。我的引导程序找不到SYS

我的代码:

org 0x0
bits 16
jmp     word loader
bsOEMName:                  db "TestOS  "
bpbBytesPerSector:          dw 512
bpbSectorsPerCluster:       db 1
bpbReservedSectors:         dw 1
bpbNumberOfFATs:            db 2
bpbNumberOfRootEntries:     dw 224
bpbTotalSectors:            dw 2880
bpbMedia:                   db 0xf0
bpbSectorsPerFAT:           dw 9
bpbSectorsPerTrack:         dw 18
bpbNumberOfHeads:           dw 2
bpbHiddenSectors:           dd 0
bpbTotalSectorsBig:         dd 0
bsDriveNumber:              db 0
bsReserved:                 db 0
bsExtendedBootSignature:    db 0x29
bsVolumeID:                 dd 0x12345678
bsVolumeLabel:              db "TestOS     "
bsFileSystem:               db "FAT12   "
;-------------------------------------------------------------------------------
; SI = Zero terminated string to print
;-------------------------------------------------------------------------------
printMsg:
push    ax
.printStart:
lodsb
or      al, al
jz      .printEnd
mov     ah, 0x0e
int     0x10
jmp     .printStart
.printEnd:
pop     ax
ret
;-------------------------------------------------------------------------------
; AX = Starting sector
; CX = Number of sectors to read
; ES:BX = Buffer
;-------------------------------------------------------------------------------
readSectors:
mov     di, 0x0005
.readLoop:
push    ax
push    bx
push    cx
call    lbaToChs
mov     ah, 0x02
mov     al, 0x01
mov     ch, byte [track]
mov     cl, byte [sector]
mov     dh, byte [head]
mov     dl, byte [bsDriveNumber]
int     0x13
jnc     .success
dec     di
pop     cx
pop     bx
pop     ax
jnz     .readLoop
.success:
pop     cx
pop     bx
pop     ax
inc     ax
add     bx, word [bpbBytesPerSector]
loop    readSectors
ret
track:      db      0
head:       db      0
sector:     db      0
;-------------------------------------------------------------------------------
; AX = Logical sector
;-------------------------------------------------------------------------------
lbaToChs:
xor     dx, dx
div     word [bpbSectorsPerTrack]
inc     dl
mov     byte [sector], dl
xor     dx, dx
div     word [bpbNumberOfHeads]
mov     byte [head], dl
mov     byte [track], al
ret
;-------------------------------------------------------------------------------
; AX = Cluster number
;-------------------------------------------------------------------------------
clusterToLba:
sub     ax, 0x0002
xor     cx, cx
mov     cl, byte [bpbSectorsPerCluster]
mul     cx
ret
;-------------------------------------------------------------------------------
loader:
cli
mov     ax, 0x07c0
mov     es, ax
mov     gs, ax
mov     fs, ax
mov     ds, ax
mov     ax, 0x0000
mov     ss, ax
mov     sp, 0xffff
sti
mov     byte [bsDriveNumber], dl
xor     dx, dx
xor     cx, cx
mov     ax, 0x0020
mul     word [bpbNumberOfRootEntries]
div     word [bpbBytesPerSector]
xchg    cx, ax ; Number of sectors of the root directory
mov     al, byte [bpbNumberOfFATs]
mul     word [bpbSectorsPerFAT]
add     ax, word [bpbReservedSectors] ; Starting sector of the root directory
mov     bx, 0x0200
call    readSectors
mov     cx, word [bpbNumberOfRootEntries]
mov     di, 0x0200
searchRoot:
push    cx
mov     cx, 0x000b
mov     si, stage2
push    di
rep cmpsb
pop     di
je      loadFat
pop     cx
add     di, 0x0020
loop    searchRoot
jmp     failure
loadFat:
mov     dx, [di + 26] ; Starting address of entry
xor     ax, ax
mov     al, byte [bpbNumberOfFATs]
mul     word [bpbSectorsPerFAT] ; Number of sectors used by the FATs
mov     word [cluster], dx
mov     cx, ax
mov     ax, word [bpbReservedSectors]
mov     bx, 0x0200
call    readSectors
mov     ax, 0x0050
mov     es, ax
mov     bx, 0x0000
push    bx
loadFile:
mov     ax, word [cluster]
pop     bx
call    clusterToLba
xor     cx, cx
mov     cl, byte [bpbSectorsPerCluster]
call    readSectors
push    bx
mov     ax, word [cluster]
mov     cx, ax
mov     dx, ax
shr     dx, 1
add     cx, dx
mov     bx, 0x0200
add     bx, cx
mov     dx, [bx]
test    ax, 1
jnz     oddCluster
evenCluster:
and     dx, 0b0000111111111111
jmp     next
oddCluster:
shr     dx, 4
next:
mov     word [cluster], dx
cmp     dx, 0x0ff0
jb      loadFile
jmp     0x0050:0 ; Far jmp to KRNLDR.SYS
failure:
mov     si, fail
call    printMsg
mov     si, anykey
call    printMsg
mov     ah, 0x00
int     0x16 ; Await key press
jmp     0xffff:0 ; Reboot with far jmp to BIOS
stage2:         db          "KRNLDR  SYS"
fail:           db          "Operating system not found", 0xd, 0xa, 0x0
anykey:         db          "Press any key to reboot", 0xd, 0xa, 0x0
cluster:        dw          0
times 510 - ($ - $$) db 0
dw 0xaa55

我能做什么?感谢的帮助

loadFat:
mov     dx, [di + 26] ; Starting address of entry
xor     ax, ax
mov     al, byte [bpbNumberOfFATs]
mul     word [bpbSectorsPerFAT] ; Number of sectors used by the FATs
mov     word [cluster], dx

这里的一个问题是具有字操作数的mul将该字乘以ax,并将结果留在寄存器对dx:ax中。因此,在使用零来初始化名为cluster的变量之前,您将用零覆盖dx。当将FAT条目索引转换为扇区号时,从零减去2会得到非常高的扇区号。

这就引出了我发现的第二期。通常,[集群]中的零应该减去2,其结果乘以1(每个集群的扇区数量(,然后添加"第一个数据扇区",这将再次导致一个非常低的数字,这将导致故障,但可能会有所不同。然而,您的clusterToLba实际上并没有转换为该集群数据的LBA起始扇区,因为它没有添加"第一个数据扇区"(即第一个集群的第一个扇区的LBA编号(。这需要由加载程序进行计算。它是根目录的起始扇区加上根目录扇区的数量。

相关内容

  • 没有找到相关文章

最新更新