Assembly BIOS。LBA模式读数不';不读取扇区
我正在开发自己的引导加载程序,并将QEMU用作测试实验室来检查/调试它。现在我想练习使用BIOS扩展读取扇区。根据文档,QEMU使用SeaBIOS,它应该支持int 13h AH=42h。 我有这个密码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
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。@preciousbetineorg
指令对于所选的段选择器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
寄存器中获取。