【问题标题】:BIOS. LBA mode reading doesn't read sectorsBIOS。 LBA 模式读取不读取扇区
【发布时间】:2019-04-25 15:13:56
【问题描述】:

我正在开发自己的引导加载程序,并且正在使用 QEMU 作为测试实验室来检查/调试它。现在我想练习使用 BIOS 扩展读取扇区。根据文档,QEMU 使用 SeaBIOS,它应该支持 int 13h AH=42h。 我有这个代码

bits    16                      ; we are in 16 bit real mode

org 0                       ; we will set regisers later

start:  jmp main                    ; jump to start of bootloader


Print:
        lodsb               ; load next byte from string from SI to AL
        or  al, al          ; Does AL=0?
        jz  PrintDone       ; Yep, null terminator found-bail out
        mov ah, 0eh         ; Nope-Print the character
        int 10h
        jmp Print           ; Repeat until null terminator found
PrintDone:
        ret             ; we are done, so return


ReadSectors:

         mov ah,0x42
         mov dl,0x80
         mov si,dap
         int 0x13  
         jc .error
         jmp .exit
.error:
         mov si,msgFailure
         call Print
         cli
         hlt
.exit:  
    ret


 main:

 ;----------------------------------------------------
 ; code located at 0000:7C00, adjust segment registers
 ;----------------------------------------------------

    cli                     ; disable interrupts
    mov     ax, 0x07C0              ; setup registers to point to our segment
    mov     ds, ax
    mov     es, ax
    mov     fs, ax
    mov     gs, ax

 ;----------------------------------------------------
 ; create stack
 ;----------------------------------------------------

    mov     ax, 0x0000              ; set the stack
    mov     ss, ax
    mov     sp, 0xFFFF
    sti                     ; restore interrupts
    xor ax,ax
    mov ah,0x41
    xor dx,dx
    mov dl,0x80
    mov bx,0xAA55
    int 0x13
 ;----------------------------------------------------
 ; Display loading message
 ;----------------------------------------------------

    mov     si, msgLoading
    call    Print
    call ReadSectors
    mov si,0x200
    call Print
    cli
    hlt               
dap:
packetSize: db 0x10
reserved:   db 0x0
sectorsNumber:  dw 0x1
buf_seg:    dw 0x0000
buf_off:    dw 0x7E00
lba:        dd 0x0
            dd 0x0

msgLoading  db 0x0D, 0x0A, "Loading Boot Image ", 0x0D, 0x0A, 0x00
msgCRLF     db 0x0D, 0x0A, 0x00
msgProgress db ".", 0x00
msgFailure  db 0x0D, 0x0A, "ERROR : Press Any Key to Reboot", 0x0A, 0x00

TIMES 510-($-$$) DB 0
DW 0xAA55

它使用 AH=41h 函数检查是否支持扩展,然后从 LBA=0h 开始读取 1 个扇区到内存 0000:7E00。 我正在使用 gdb 连接到 qemu 机器以检查寄存器和内存。所以我看到的是

  • int 13h AH=42 返回CF=0,所以没有错误
  • int 13h AH=41h 返回CF=0,CX=7,表示BIOS支持扩展。 但随后我检查地址 7E00 的内存,我只看到零,但我希望看到引导加载程序的代码,因为它存储在 LBA=0h 扇区中。

这就是我创建磁盘映像的方式

nasm bootloader.asm -o ./bin/bootloader.bin
dd if=/dev/zero of=./floppy/floppy.img bs=1024 count=1440
dd if=./bin/bootloader.bin of=./floppy/floppy.img conv=notrunc 

这就是我运行 qemu 的方式

qemu-system-x86_64 -s -S -hda ./floppy/floppy.img

请您帮助理解我做错了什么。 谢谢!

【问题讨论】:

  • 在磁盘地址包(DAP)中的偏移量首先是segment。所以 buf_seg: dw 0x0000 buf_off: dw 0x7E00 应该是 buf_off: dw 0x7E00 buf_seg: dw 0x0000 。这样做的原因是因为 x86 是一个小端处理器,所以 segment:offset 首先存储为偏移量,然后存储为段。
  • @preciousbetine org 指令对于 OP 选择的段选择器来说似乎是正确的。
  • @preciousbetine :他拥有它的org 0 是正确的,他也正确地加载了 0x07c0 的段寄存器。这是因为 0x07c0:0x0000 的段:偏移量对是物理地址 0x07c0org 0x7c00 并将段设置为 0x0000,因为 0x0000
  • @preciousbetine :使用 NASM(使用 BIN 格式)otg 的位置无关紧要。不管你把它放在哪里,它的作用就像是一开始一样。
  • @Michael Petch 非常感谢!它有帮助。而且现在我将 DL 存储在内存中,然后在所有 int 13h 函数中使用它。并感谢您推荐如何设置 SP。

标签: assembly x86 bootloader bios osdev


【解决方案1】:

在磁盘访问数据包 (DAP) 中,segment:offset 对以先偏移后segment 的形式存储。这是因为 x86 是一个小端处理器,并且该对以相反的顺序存储。您的 DAP 应更改为:

dap:
packetSize: db 0x10
reserved:   db 0x0
sectorsNumber:  dw 0x1
buf_off:    dw 0x7E00              ; Place offset before segment
buf_seg:    dw 0x0000
lba:        dd 0x0
            dd 0x0

【讨论】:

  • 我还看到一些(错误?)BIOS 需要ES 寄存器来包含存储在 DAP 中的段值。这些 BIOS 忽略 DAP 中的段值并从ES 寄存器中获取它。
猜你喜欢
  • 2015-09-29
  • 2020-02-22
  • 2020-09-06
  • 2012-07-20
  • 1970-01-01
  • 2013-07-16
  • 1970-01-01
  • 2011-04-08
相关资源
最近更新 更多