雖然目前 hypervisor 大部分功能尚未實作,但我想可先以簡易 boot loader 作為目標。目前的 boot loader 先不涉及模式切換,以實作 Real mode 需要的基礎功能為主,如:中斷服務程式(僅做骨架驗證)、啟用 A20 位址線(使實模式可越過 1 MB 記憶體限制)、配置 GDT/TSS(只完成佈局,不啟用),為後續切換至 Protected mode 做準備。
當系統完成電自檢後, BIOS 會把啟動扇區的 512 bytes 載入至實體地址 0x0000:0x7C00。啟動扇區末兩個位元組必須是 0x55、0xAA 的簽名,否則不被視為可開機扇區。此外,BIOS 會透過暫存器 DL 傳遞開機裝置編號(例如 0x80 代表第一顆硬碟),後續若要以 int 13h 載入更多內容必須保留此值(int 13h 可操作磁碟)。由於開機扇區僅有 512 bytes,可用空間相當有限,因此此階段將用於做最小驗證,並將 loader 載入記憶體中,再進行更完整的初始化。
今天的實作目標是讓最小 boot sector 在 QEMU 上正常啟動並輸出訊息,驗證 BIOS -> 0x7C00 -> 螢幕輸出這條路徑。程式進入點會統一段暫存器與 stack,保存 DL,並以 INT 10h(teletype)輸出文字,成功後停在迴圈等待後續擴充。另外這裡先處理簡單的軟碟開機,範例如下:
.code16
.intel_syntax noprefix
.globl _start
.equ STACK_TOP, 0x7C00
.equ DEBUG_PORT, 0x00E9
_start:
cli
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, STACK_TOP
sti
mov byte ptr [boot_drive], dl
lea si, msg
mov dx, DEBUG_PORT
print_next:
lodsb
test al, al
jz hang
mov ah, 0x0E
mov bx, 0x0007
int 0x10
out dx, al
jmp print_next
hang:
jmp hang
boot_drive:
.byte 0
msg:
.ascii "BOOT OK\r\n"
.byte 0
.org 510
.word 0xAA55
由於目前僅驗證是否打印信息到 qemu 中,因此這裡暫不使用 dd 去生成 img 直接在 qemu 指定。
qemu-system-i386 \
-drive if=floppy,format=raw,file=boot.bin \
-device isa-debugcon,iobase=0xE9 \
-debugcon stdio