上篇說明如何撰寫小型Boot Loader將作業系統載入至記憶體並執行該作業系統程式碼,並利用qemu實現。為了更真實性,本篇將boot loader及作業系統安裝在CF card並利用CF card開機,用以證明該boot loader及作業系統可以正確地在實體機器上運行。
由於上篇是使用軟碟機開機,因此在使用BIOS中斷服務0x13時 (AH=02 Read Sectors from Driver),需將DL暫存器設定為0(0代表軟碟機0,1代表軟碟機1),但因為現在要從硬碟讀取,所以需將DL設定為0x80,即底下範例程式紅色部份。
/* boot_loader.S
*
* Copyright (C) 2010 Adrian Huang (adrianhuang0701@gmail.com)
*
* This code is intended to simulate a simplified boot loader. This boot
* loader loads 3 sectors into the physical memory and jumps the entry
* point of OS.
*
*/
BOOT_SEG = 0x07C0 /* starting code segment (CS) of boot loader */
OS_SEG = 0x0800 /* code segment address of OS entry point */
OS_OFFSET = 0x0000 /* the offset address of OS entry point */
.code16
.section .text
.global _start
_start:
# FAT12 file system format
ljmp $BOOT_SEG, $start_prog # jmp instruction
.byte 0x90
.ascii "ADRIAN " # OEM name (8 bytes)
.word 512 # Bytes per sector
.byte 1 # Sector per cluster
.word 32 # Reserved sector count: should be 32 for FAT32
.byte 2 # Number of file allocation tables.
.word 0 # Maximum number of root directory entries. 0 for FAT32
.word 0 # Total sectors
.byte 0xf8 # Media descriptor: fix disk
.word 9 # Sectors per File Allocation Table
.word 18 # Sectors per track
.word 2 # Number of heads
.long 0 # Count of hidden sectors
.long 2030112 # Total sectors
.byte 0 # Physical driver number
.byte 0 # Reserved
.byte 0x29 # Extended boot signature
.long 0x12345678 # Serial Number
.ascii "HELLO-OS " # Volume Label
.ascii "FAT12 " # FAT file system type
.fill 18, 1, 0 # fill 18 characters with zero
start_prog:
# initialize the register with cs register
movw %cs, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
xorw %sp, %sp
cld # clear direction flag
sti # set interrupt flag
# The following code is loaded three sectors (2-4th sectors from boot.bin)
# into the physical memory 0x8000-0x85FF.
movw $OS_SEG, %ax
mov %ax, %es # ES:BX-> destination buffer address pointer
movb $2, %cl # sector
cont:
movw $0, %bx
movb $0x02, %ah # Read sectors from drive
movb $0x1, %al # Sectors to read count
movb $0x0, %ch # track
movb $0x0, %dh # head
movb $0x80, %dl # drive
int $0x13 # trigger a interrupt 0x13 service
jc fail # the clear flag is set if the operation is failed
mov %es, %ax
addw $0x20, %ax # move to the next sector
movw %ax, %es # move to the next sector
incb %cl
cmpb $3, %cl # has finished reading 3 sectors?
jbe cont # continue to read the sector
jmp os_entry # jump to OS entry point
fail:
movw $err_msg, %si
fail_loop:
lodsb
andb %al, %al
jz end
movb $0x0e, %ah
int $0x10
jmp fail_loop
os_entry:
ljmp $OS_SEG, $OS_OFFSET # jump to os context
end:
hlt
err_msg:
.ascii "Reading sectors operation is failed!"
.byte 0
.org 0x1FE, 0x41 # fill the rest of characters with zero until the 254th character
# Boot sector signature
.byte 0x55
.byte 0xaa
請參照這篇的"作業系統程式碼"與"編譯程式碼"。
adrian@adrian-mem1:~/img$ sudo dd if=./boot_loader.bin of=/dev/sda
將該系統重開並選擇CF Card開機,其畫面如下: