好了,跟著要做一個真的有載入功能的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 ----------
[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 ----------
[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 則留言:
請問骨仔大大是唸哪一科系,似乎不是單純會計師呀!-.-??
珍妮佛麥走
發佈留言