INT 13h 无法读取特定扇区之后的内容。

huangapple go评论87阅读模式
英文:

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

huangapple
  • 本文由 发表于 2023年8月10日 23:15:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76877105.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定