BIOS int 13h/AH=42 未读取磁盘或未读取到内存中的正确位置

Posted

技术标签:

【中文标题】BIOS int 13h/AH=42 未读取磁盘或未读取到内存中的正确位置【英文标题】:BIOS int 13h/AH=42 not reading disk or reading into right place in memory 【发布时间】:2021-12-20 11:03:51 【问题描述】:

编辑: 请。为了上帝的爱。如果您在真实模式下执行,请记得添加[BITS 16]。它会拯救你。

我正在尝试让 Bios 从磁盘中读取一小部分并执行它。到目前为止我有

; Boot sector if you didn't know. The entire purpose of this is to jump to protected mode setup (PMS)
%define BIOS_ERROR_FREQUENCY 440
%define ERR_LBA_NOT_FOUND    1
%define ERR_BIOS_WRITE       2

extern BIOS_BLOCK_SIZE
extern boot_sector_e
extern pms_s
extern pms_e
extern pms_number_of_blocks

section .boot
    ; Check if the BIOS supports LBA
    mov ah, 0x41
    mov bx, 0x55AA
    ; dl has already been set to the boot drive
    int 0x13
    ; Error handle
    mov al, ERR_LBA_NOT_FOUND
    jc boot_error

    ; If it does support LBA, we read in PMS to memory and start executing it
    mov ah, 0x42
    ; dl already set
    mov si, bios_lba_packet_s
    int 0x13
    mov al, ERR_BIOS_WRITE
    jc boot_error
    jmp pms_s
    ; Please note that this will overwrite and read extra from the disk. We don't know what this is however, we can just ignore it :)

    ; Misc
    bios_lba_packet_s:
    db bios_lba_packet_e - bios_lba_packet_s ; Size
    db 0 ; Reserved
    dw pms_number_of_blocks
    dw boot_sector_e ; Offset of transfer buffer location
    dw 0x0 ; Section
    dq 0 ; Starting block. We have the ability to hardcode this because it's at the set position of one sector off (boot sector is 0)
    bios_lba_packet_e:

    boot_error: ; Will just print out a upon error
        mov ah, 0x0E
        mov al, "a"
        int 0x10
        jmp $

section .boot-header
    dw 0xAA55 ; 55AA tells the BIOS that this is bootable (reversed because of endians)

section .pms
    mov ah, 0x0E
    mov al, "w"
    int 0x10

这是我要加载的内容,并且在工作时会简单地打印出“w”

我把它链接在一起

SECTIONS 
    .boot ORG : 
        boot_sector_s = .;
        *( .boot );
    
    . += BIOS_BLOCK_SIZE - boot_header_size - boot_size;
    .boot-header : 
        *( .boot-header );
        boot_sector_e = .;
    
    
    .pms : 
        pms_s = .;
        *( .pms );
        pms_e = .;
    

/* Constants */
BIOS_BLOCK_SIZE = 512;
ORG = 0x7C00;

boot_size = SIZEOF( .boot );
boot_header_size = SIZEOF( .boot-header ); /* This has be defined after the .boot-header section has been defined (it's weird, I know) */
pms_number_of_blocks = ((pms_e - pms_s) + BIOS_BLOCK_SIZE) / BIOS_BLOCK_SIZE;

我已经转储了内存,但没有找到加载的部分。我还检查了进位标志,它们没有设置。是否与我的最终二进制文件没有填充有关,以便使我要加载的部分成为完整的 512 字节?

【问题讨论】:

您确定 DS 就是您认为的那样吗? Rumor has it 你不应该假设引导加载程序时寄存器中的内容(DL 除外)。 dl 是 0x80,这是默认的 HDA & ds 是 0x0。 dq 0 表示您将加载第一个扇区。 是的,我用 dq 0dq 1 尝试过,但无济于事 【参考方案1】:

InstallationCheck 函数 41h 报告 CF=0 的事实并不意味着一切。 您仍然需要验证 BX=AA55h 以查看 IBM/MS INT 13 Extensions 是否确实安装。 并检查CX 中的SubsetSupportBitmap。如果 CX 的第 0 位被设置,那么 ExtendedRead 函数 42h 是支持的。

pms_number_of_blocks = ((pms_e - pms_s) + BIOS_BLOCK_SIZE) / BIOS_BLOCK_SIZE;

这会将您的 pms_number_of_blocks 设置为 1。您需要将 StartingAbsoluteBlockNumber 设置为 1 而不是 0。(0 将重新读取引导扇区。)

bios_lba_packet_s:
db 16
db 0
dw pms_number_of_blocks
dd 0:pms_s
dq 1

这是否与我的最终二进制文件没有填充以使我要加载的部分成为完整的 512 字节有关?

继续垫吧!无论如何你都应该这样做。


奇怪的是,在读取的函数上报告了“ERR_BIOS_WRITE”。

BIOS.Teletype 函数 0Eh 使用 BH DisplayPage 参数。将其设置为 0。

  section .pms
      mov  bh, 0
      mov  ax, 0x0E * 256 + "w"
      int  0x10
      times (512 - 7) db 0

BIOS 仅将DL 寄存器中的引导驱动器传递给您。没有其他的!不要相信段寄存器的任何特定设置。明确设置DS=0

始终在安全的地方设置堆栈。在这里将其设置在引导扇区下方:

  xor  ax, ax
  mov  ds, ax
  mov  ss, ax
  mov  sp, 0x7C00

【讨论】:

以上是关于BIOS int 13h/AH=42 未读取磁盘或未读取到内存中的正确位置的主要内容,如果未能解决你的问题,请参考以下文章

USB 硬盘仿真导致磁盘读取失败(BIOS int 13)?

使用 Int 13H 读取磁盘参数

读取磁盘:CHS方式

[汇编]《汇编语言》第17章 使用BIOS进行键盘输入和磁盘读写

BIOS int 13h 无法读取第一条轨道

BIOS INT 13H 问题(从驱动器读取扇区)