Assembly BIOS。LBA模式读数不';不读取扇区

Assembly BIOS。LBA模式读数不';不读取扇区,assembly,x86,bootloader,bios,osdev,Assembly,X86,Bootloader,Bios,Osdev,我正在开发自己的引导加载程序,并将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

我正在开发自己的引导加载程序,并将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的内存,只看到了零,但我希望看到bootloader的代码,因为它存储在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)中,段:偏移量对存储在偏移量之前,然后是段。这是因为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

在磁盘地址包(DAP)中,偏移量首先跟在段之后。所以
buf_seg:dw 0x0000
buf_off:dw 0x7E00
应该是
buf_off:dw 0x7E00
buf_seg:dw 0x0000
。这是因为x86是一个小的endian处理器,所以段:offset存储为offset first和segment second。@preciousbetine
org
指令对于所选的段选择器OP似乎是正确的。@preciousbetine:org 0的位置是正确的,他还正确地加载了带有0x07c0的段寄存器。这是因为0x07c0:0x0000的段:偏移量对是物理地址0x07c0@preciousbetine:对于NASM(BIN格式),otg的位置无关紧要。不管你把它放在哪里,它的行为就像是在一开始。@Michael Petch非常感谢!这有帮助。现在我将DL存储在内存中,然后在所有int 13h函数中使用它。感谢您推荐如何设置SP。我还看到一些(buggy?)BIOSE要求
ES
寄存器包含存储在DAP中的段值。这些BIOS忽略DAP中的段值,并从
ES
寄存器中获取。