assembly 阅读磁盘以加载操作系统内核时出现错误0x0C80

hpxqektj  于 5个月前  发布在  其他
关注(0)|答案(1)|浏览(63)

当我尝试使用BIOS从磁盘读取时,我得到错误0x0C80,以下是我的代码:

disk_load:
    push dx
    mov ah, 0x42 ; BIOS extended read routine
    mov dl, 0x80 ; Drive number (0x80 for the first HDD)
    mov si, DAP  ; DS:SI -> Disk Address Packet
    int 0x13     ; BIOS Disk interrupt
    jc disk_error
    pop dx
    cmp dh, al
    jne disk_sectors_error
    jmp disk_success
    jmp disk_exit

DAP:
    db 0x10      ; Size of DAP
    db 0x00      ; Reserved
    dw 16         ; Number of sectors to read, equal to value in dh
    dw 0x1000    ; Offset to buffer
    dw 0x0000    ; Segment of buffer
    dq 1         ; Starting absolute block number (LBA)

disk_success:
    mov bx, SUCCESS_MSG
    jmp disk_exit

disk_error:
    mov bx, DISK_ERR_MSG
    call print_string
    mov dh, ah   ; AH contains the error code
    call print_hex
    jmp disk_loop

disk_sectors_error:
    mov bx, SECTORS_ERR_MSG
    call print_string

SUCCESS_MSG:
    db "Disk was successfully read ", 0

DISK_ERR_MSG:
    db "Disk read error! Error code: ", 0

SECTORS_ERR_MSG:
    db "Incorrect number of sectors read ", 0

disk_loop:
    jmp $

disk_exit:
    ret

个字符
我需要读取前16个扇区并加载内核,然后进入32位保护模式并执行
我从Github中获取了代码的基础
Console
我试着在互联网上搜索,但我找不到任何可以帮助我:(

csbfibhn

csbfibhn1#

关于disk_load

call print_string
mov dh, ah   ; AH contains the error code
call print_hex

字符串
您没有向我们显示'print_string.asm'或'print_hex.asm'的内容,因此我们无法检查AH是否在 print_string 调用中存活,或者 print_hex 是否期望输入DH!
错误代码0 Ch从IBM/MS INT 13扩展读取“不支持的轨道或无效的媒体”。
这可能是因为你使用了一个硬编码的驱动器号,就像在mov dl, 0x80 ; Drive number (0x80 for the first HDD)中一样。你确实把BIOS给你的 * Boot _DRIVE* 代码传递给了你的 disk_load 例程,那么你为什么要覆盖它呢?
另外,如果你不打算使用DH中的扇区计数,而只是信任磁盘地址包中已经硬编码的值,那么在DH中传递扇区计数有什么意义呢?对于 KERNEL_OFFSET 参数也是如此。正如@拿骚在评论中所写的,确保你用qemu创建的磁盘映像至少包含这16个扇区。

cmp dh, al
  jne disk_sectors_error
  ...
disk_sectors_error:
  mov bx, SECTORS_ERR_MSG
  call print_string
SUCCESS_MSG:
  db "Disk was successfully read ", 0


“ExtendedRead”函数不报告通过AL寄存器成功传输的块数!在DAP中查找此信息。
在可能失败时,您可以打印一条合适的消息,但允许CPU开始执行文本消息!这些消息属于最后的disk_exit:ret。这样,disk_sectors_error 代码可以正确地落入disk_loop:jmp $代码。

关于IBM/MS INT 13扩展

永远不要只是假设这些扩展是可用的!它们带有一个“安装检查”功能,将通知您有关其功能。使用它:

mov  dl, [BOOT_DRIVE]
test dl, dl
jns  UseCHS     ; Not meant for drives [00h,7Fh]
mov  bx, 55AAh
mov  ah, 41h
int  13h        ; -> AX BX CX DH CF
jc   UseCHS     ; Extensions not supported
cmp  bx, 0AA55h
jne  UseCHS     ; Not installed
shr  cx, 1
jnc  UseCHS     ; Functions 42h, 43h, 44h, 47h, 48h not supported


如果扩展不可用,则使用适当的消息中止或回退到正常的CHS(HackderHeadSector)功能。

bootloader

BIOS将我们的 Boot 驱动器存储在DL中,所以最好记住这一点以备后用。(记住BIOS在 Boot 时将我们的 Boot 驱动器设置在'dl'中)
你的评论是正确的,但它比这更深入。DL是唯一的寄存器,保证在启动 Bootstrap 时保存有意义的值。你必须自己设置段寄存器和堆栈指针,而不是相信BIOS已经为你做了这些。
%include“OS/boot/print_string_pm.asm”
%include“OS/boot/switch.asm”
%包含“OS/boot/gdt. asm”
切换到保护模式不是 Bootstrap 应该做的事情!它属于内核的设置代码。
%include“OS/boot/print_string. asm”
%include“OS/boot/print_hex. asm”
%include“OS/boot/disk_load.asm”
为什么你有这么多的包含文件?它们所做的工作并不足以证明一个单独的文件是正确的,更重要的是,它们诱使你犯这些错误。我指的是引导加载程序和 disk_load 之间的参数不匹配,以及 disk_loadprint_hex 之间的参数不匹配。
只需在引导加载程序源代码中插入它们的实际源代码文本。

[org 0x7c00]

KERNEL_OFFSET equ 0x1000

  cld
  xor  ax, ax
  mov  ds, ax
  mov  es, ax
  mov  ss, ax
  mov  sp, 0x9000
  mov  [BOOT_DRIVE], dl

  mov  bx, KERNEL_OFFSET
  mov  cx, 16
  call disk_load

  jmp  0:KERNEL_OFFSET
; ---------------------------------
; IN (ax:bx,cx,dl)
disk_load:
    mov  si, DAP    ; DS:SI -> Disk Address Packet
    mov  [si+2], cx ; Count
    mov  [si+4], bx ; Offset
    mov  [si+6], ax ; Segment

    test dl, dl
    jns  UseCHS     ; Not meant for drives [00h,7Fh]
    mov  bx, 55AAh
    mov  ah, 41h    ; BIOS.InstallationCheck
    int  13h        ; -> AX BX CX DH CF
    jc   UseCHS     ; Extensions not supported
    cmp  bx, 0AA55h
    jne  UseCHS     ; Not installed
    shr  cx, 1
    jnc  UseCHS     ; Functions 42h, 43h, 44h, 47h, 48h not supported

    mov  ah, 0x42   ; BIOS.ExtendedRead
    int  0x13       ; -> AH CF
    jc   disk_error
    cmp  [si+2], cx
    je   disk_success
disk_sectors_error:
    mov  si, SECTORS_ERR_MSG
    call print_string
    jmp  $
disk_error:
    push ax         ; AH contains the error code
    mov  si, DISK_ERR_MSG
    call print_string
    pop  ax
    call print_hex
    jmp  $

UseCHS:

    ...

disk_success:
    mov  si, SUCCESS_MSG
; ----------------------------
; IN (si) OUT (si) MOD (ax)
print_string:
    lodsb
    mov   ah, 0Eh
.next:
    int   10h
    lodsb
    cmp   al, 0
    jne   .next 
    ret
; ----------------------------
; IN (ax)
print_hex:

    ...

    ret
; ----------------------------
DAP:
    db 16       ; Size of DAP
    db 0        ; Reserved
    dw 0        ; Number of sectors to read
    dw 0        ; Offset to buffer
    dw 0        ; Segment of buffer
    dq 1        ; Starting absolute block number (LBA)
SUCCESS_MSG:
    db "Disk was successfully read ", 0
DISK_ERR_MSG:
    db "Disk read error! Error code: ", 0
SECTORS_ERR_MSG:
    db "Incorrect number of sectors read ", 0
BOOT_DRIVE:
    db 0
; ----------------------------
times 510-($-$$) db 0
dw 0xAA55

相关问题