【发布时间】: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 0x0000buf_off: dw 0x7E00应该是buf_off: dw 0x7E00buf_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