星期三

有載入功能的Boot Loader

想不到寫一個 Hello World OS 是這麼容易的 ^^v (如何做? 請看這 -> 製造 Boot Loader)

好了,跟著要做一個真的有載入功能的Boot Loader,以及一個 Hello World Kernel。(Kernel用在OS上,就是OS最核心的程式,其他所有的程式,都是建立在其之上,最基本/主要的功能是管理CPU、記憶體及對外其他的硬體)

為了簡單起見,我暫時會在真實模式(Real Mode)操作的,了解更多之後,才轉到比較先進的保護模式(Protected Mode)。

先說一下我現在要做的事:
1. 製作一個 Hello World Kernel
2. 製作一個有載入功能Boot Loader: (1)把Kernel載入記憶體;(2)把程序的控制權交給Kernel

1. 製作一個 Hello World Kernel
這個簡單,只是把上次的Boot Loader改動一點,這一次會出現 Kernel Loaded. 的字樣:
---------- kernel.asm ----------
[BITS 16] ;tell the assembler that its a 16 bit code

   MOV AL, 10
   CALL PrintCharacter
   MOV AL, 75
   CALL PrintCharacter
   MOV AL, 101
   CALL PrintCharacter
   MOV AL, 114
   CALL PrintCharacter
   MOV AL, 110
   CALL PrintCharacter
   MOV AL, 101
   CALL PrintCharacter
   MOV AL, 108
   CALL PrintCharacter
   MOV AL, 32
   CALL PrintCharacter
   MOV AL, 108
   CALL PrintCharacter
   MOV AL, 111
   CALL PrintCharacter
   MOV AL, 97
   CALL PrintCharacter
   MOV AL, 100
   CALL PrintCharacter
   MOV AL, 101
   CALL PrintCharacter
   MOV AL, 100
   CALL PrintCharacter
   MOV AL, 46
   CALL PrintCharacter
   MOV AL, 10
   CALL PrintCharacter
   MOV AL, 13
   CALL PrintCharacter

   JMP $ ;infinite loop

PrintCharacter: ;Procedure to print character on screen
;Assume that ASCII value is in register AL
   MOV AH, 0x0E ;Tell BIOS that we need to print one charater on screen.
   MOV BH, 0x00 ;Page no.
   MOV BL, 0x07 ;Text attribute 0x07 is lightgrey font on black background
   INT 0x10 ;Call video interrupt
   RET ;Return to calling procedure
---------- kernel.asm ----------

我把她名為 kernel.asm

2. 製作一個有載入功能Boot Loader
先說說我在 PC模擬器 Bochs 上的設定,這模擬的PC上面只有一個floppy碟,開機的時候會找找看floppy碟上的boot sector有沒有boot loader,有的話就執行。

而一般floppy的sector容量都是512bytes (我想這也是為什麼Boot Loader的長度也定為512bytes),我會把Kernel放在boot loader之後的 (即第2個sector)。

只要用一個INT 13h(ah=02h)指令就可以把floppy上特定位置的內容複製到記憶體上指定的位置 (es:bx)。

之後,把程式跳去指定位置就行了。
---------- loader.asm ----------
[BITS 16] ;tell the assembler that its a 16 bit code
[ORG 0x7C00] ;Origin, tell the assembler that where the code will
;be in memory after it is been loaded

reset_drive:
   mov ah, 0 ;not very sure why i need this ^^"
   int 13h
   or ah, ah
   jnz reset_drive

   mov ax, 0
   mov es, ax
   mov bx, 0x1000 ;copy the kernel to 0000:1000

   mov ah, 02h ;Command - 02h for 'Read sector from disk'
   mov al, 02h ;Number of sectors to read
   mov ch, 0 ;Disk cylinder
   mov cl, 02h ;Disk sector (starts with 1, not 0)
   mov dh, 0 ;Disk head
   int 13h
   or ah, ah
   jnz reset_drive ;any problem, back to reset_drive label

   jmp 0:01000h ;jump to start of the kernel

   TIMES 510 - ($ - $$) db 0 ;fill the rest of sector with 0
   DW 0xAA55 ; add boot signature at the end of bootloade
---------- loader.asm ----------

改了名,把她叫作loader.asm吧。

很好,到了測試時間。先編譯兩個.asm:

> nasm d:\os\loader.asm -f bin -o d:\os\loader.bin
> nasm d:\os\kernel.asm -f bin -o d:\os\kernel.bin

再把兩個.bin一前一後的放在一起,成為floppy的.img:

> copy /b loader.bin+kernel.bin boot.img

運行Bochs,「Kernel Loaded.」,Bango!

跟著試試把Kernel變成C吧~

Reference:
Mixing Assembly and C-code

1 則留言:

匿名 說...

請問骨仔大大是唸哪一科系,似乎不是單純會計師呀!-.-??

珍妮佛麥走