英文:
INT 13h cannot read beyond specific sector
问题
这是加载磁盘扇区到内存的操作系统内核函数的代码部分。你提到函数无法读取第19扇区,并且检查了AH寄存器的值为0x01。
英文:
I am writing a kernel for my operating system and I have ran into a problem while loading a sector of a disk to memory.
Here is the portion of the code of the function that loads the sector from the disk:
mov ax, #0x3000
mov es, ax
mov ax, #0x0201
mov bx, word ptr [bp - 6] ; bx = 0x000, 0x200, 0x400, ...
xor ch, ch
mov cl, byte ptr [bp - 8] ; cl = target cluster to read
xor dx, dx
int 0x13
jc load_cluster_carry ; carry == 1 when error
xor ax, ax
inc ax
jmp load_cluster_end
load_cluster_carry:
xor ax, ax
load_cluster_end:
mov word ptr [bp - 10], ax
And the function cannot read from sector 19. So I checked AH register and its value was 0x01.
答案1
得分: 2
> mov ax, #0x0201
> mov bx, word ptr [bp - 6] ; bx = 0x000, 0x200, 0x400, ...
> xor ch, ch
> mov cl, byte ptr [bp - 8] ; cl = target cluster to read
> xor dx, dx
> int 0x13
; 注释 `; bx = 0x000, 0x200, 0x400, ...` 告诉我们您想要读取多个扇区。从 `xor ch, ch` (CH 代表柱面) 和 `xor dx, dx` (DH 代表磁头) 可以推断出您似乎希望在同一个柱面(0)和磁头(0)上找到所有这些扇区。这不会是情况:在某个时候,您将读取当前磁道上的所有可用扇区,然后需要前进到下一个磁道。
; 此处的回答 https://stackoverflow.com/questions/30990880/how-are-all-disk-sectors-iterated-in-assembly 具有一个可行的代码示例,展示了如何正确执行此操作。该代码不会猜测磁盘的几何结构,并会向 BIOS 请求这些值。
; 您的 `xor dx, dx` 也将 DL 寄存器清零,该寄存器指定要使用的驱动器。除非您非常确定它需要为 0,否则我建议您使用 BIOS 在引导加载程序启动时提供的值。驱动器标识在 DL 寄存器中传递给您,顺便说一下,这是 BIOS 在引导加载程序开始时提供的唯一信息。
; 额外的技巧
> jc load_cluster_carry ; 当错误发生时 carry == 1
> xor ax, ax
> inc ax
> jmp load_cluster_end
> load_cluster_carry:
> xor ax, ax
> load_cluster_end:
> mov word ptr [bp - 10], ax
; 您可以用以下更简单/更清晰的代码替换上述代码:
cmc
sbb ax, ax
neg ax
mov [bp - 10], ax
英文:
> mov ax, #0x0201
> mov bx, word ptr [bp - 6] ; bx = 0x000, 0x200, 0x400, ...
> xor ch, ch
> mov cl, byte ptr [bp - 8] ; cl = target cluster to read
> xor dx, dx
> int 0x13
The comment ; bx = 0x000, 0x200, 0x400, ...
tells us that you want to read multiple sectors. From xor ch, ch
(CH for Cylinder) and xor dx, dx
(DH for Head), we can conclude that you seem to expect to find all of those sectors on the same Cylinder (0) and Head (0). This will not be the case: at some point you will have read all the available sectors on the current track and you will need to advance to the next track.
The answer at https://stackoverflow.com/questions/30990880/how-are-all-disk-sectors-iterated-in-assembly has a working code that shows how to do that correctly. The code does not guess about the disk's geometry and asks BIOS for these values.
Your xor dx, dx
also zeroes the DL register that specifies the drive to use. Unless you are very sure that it needs to be 0, I would advice that instead you use the value that BIOS gave you when your bootloader got started. The drive id is passed to you in the DL register, and BTW it's the only information that BIOS provides when your bootloader begins.
Extra trick
> jc load_cluster_carry ; carry == 1 when error
> xor ax, ax
> inc ax
> jmp load_cluster_end
> load_cluster_carry:
> xor ax, ax
> load_cluster_end:
> mov word ptr [bp - 10], ax
You can replace the above by next simpler/cleaner code:
cmc
sbb ax, ax
neg ax
mov [bp - 10], ax
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论