我想开发一个引导加载器,简单地扫描自己的引导介质(FAT16的软盘)的根目录,然后跳转到它。最后我遇到了一个问题,我在网上找不到任何地方,我觉得我做错了什么。在我的代码开始的时候,当我用INT 0x13读取驱动器的根目录时,carry标志被设置了,在我让它打印出AH中的错误代码后,我得到了0x80,似乎对应于磁盘超时。我已经试过将DL硬编码为0x00(软盘#1--和以前一样),0x01(软盘#2--AH=0x01非法功能)和0x80(硬盘#1--实际上有数据,但和预期的一样,不是软盘镜像的数据)。我也试过硬编码计算参数,我也试过只读一个扇区。下面是错误似乎发生的代码。
BITS 16
jmp short bootload
nop
; Drive parameters
bootload:
; Segment registers
mov ax, 0x07C0+544
cli
mov ss, ax
mov sp, 4096
sti
mov ax, 0x07C0
mov ds, ax
mov es, ax
; Boot device
mov [bootdev], dl
; Calculations (I just hardcoded them in this example to make it easier to understand)
mov byte [rootdirsize], 14
mov byte [rootdirchssec], 1
mov word [rootdirchstrack], 1
; Read sectors
mov ah, 0x02 ; Read sectors
mov al, byte [rootdirsize] ; The amount of sectors needed by the root dir entries
; (RootDirEntries / 16)
mov dl, byte [bootdev]
mov dh, 0 ; Heads are ignored... yet
mov cl, byte [rootdirchssec] ; Sector number of the root dir in CHS
and cx, 0b0000_0000_0011_1111 ; Sector only uses bits 0-5 of CX
mov bx, word [rootdirchstrack] ; Track number of the root dir in CHS
shl bx, 6 ; Track uses bits 6-15 of CX
or cx, bx ; Transfer to CX
mov bx, 0x0100 ; Segment where it is loaded
mov es, bx
mov bx, 0 ; Offset = 0
int 0x13
jc disk_error ; CF = error
jmp $ ; the rest of the bootloader
disk_error:
mov al, ah ; AH is the error code
mov ah, 0x0E ; print it
int 0x10 ; returns 'Ç' = 0x80 = timeout
jmp $
data:
bootdev db 0
rootdirsec dw 0
rootdirchssec db 0
rootdirchstrack dw 0
rootdirsize db 0
times 510-($-$$) db 0
dw 0xAA55
真正的代码当然要长得多,我只写了问题的关键部分。其他细节,可能会有帮助。
你说的没错,Cylinders(Tracks)可以是一个10位的数字,而要读取的扇区号是6位。两者都装在一个16位的寄存器中(CX) int 0x13
BIOS磁盘读取调用。10位的圆筒号只适用于硬盘类型的介质(或任何模拟为硬盘驱动器的东西)。对于软盘介质,圆柱体被限制为8位值(0-255),扇区号仍然被限制在1-63(6位)之间。
你将一个包含圆柱体的16位字载入到 BX 来进行计算。你移 BX 左6位。这就把圆柱体计数的下2位放到了圆柱体计数的上2位。BL 和上8位进入 BH 寄存器。这不是圆柱体编号的编码方式。寄存器的文件 INT 13hAH=2 说。
CH = low eight bits of cylinder number CL = sector number 1-63 (bits 0-5) high two bits of cylinder (bits 6-7, hard disk only)
这说明必须将圆柱体编号的前2位存储在... CL,扇区号是低6位的 CL. CH 包含圆柱体编号的低8位。
为了解决这个问题,你可以把这几行改为
mov bx, word [rootdirchstrack] ; Track number of the root dir in CHS
shl bx, 6 ; Track uses bits 6-15 of CX
or cx, bx ; Transfer to CX
改成类似于:
mov bx, word [rootdirchstrack] ; Track*Cylinder) number of the root dir in CHS
xchg bl, bh ; Place lower 8 bits of Cylinder in BH
; Upper 2 bits of Cylinder are now the lower 2 bits of BL
ror bl, 2 ; Rotate the lower 2 bits into the upper 2 bits of BL
or cx, bx ; Transfer to CX already containing sec # in lower 6 bits