聲明:本文為學習Codeproject文章的個人總結性文章,
? 原文:http://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part
?
本人開發環境:
操作系統:Ubuntu 32位(64位的會有pushl等指令的不能執行等問題,最好為32位)
工具:as ld dd bochs
語言:at&t 16位匯編
?
計算機啟動運行于real mode,ROM會讀取硬盤(或其他介質,如軟盤)的CHS模式的0柱面,0磁道,1扇區的的數據到內存0x7c00處,然后到此處執行。所以bootloader就是一段代碼,將這段代碼寫入0柱面,0磁道,1扇區中。
好了,原理簡單介紹完畢。
?
我的當前用戶目錄是/home/chao/,所以我要在~/Documents/目錄下來寫代碼和進行其他的操作。
創建test.S文件
1 .code16 2 .text 3 .global _start; 4 _start: 5 6 movb $'X' , %al 7 movb $0x0e, %ah 8 int $0x10 9 10 . = _start + 510 11 .byte 0x55 12 .byte 0xaa
解釋一下代碼的意義。
1 movb $'X' , %al 2 movb $0x0e, %ah 3 int $0x10
這是call BIOS interpret,調用號為0x10,查閱資料得知,0x10是Video Service,根據AH中的參數來調用不同的程序,這里AH中是0x0e,功能為Write Character in TTY Mode,也就是向終端寫入字符,寫入的字符從AL中獲取,也就是字符X。
1 . = _start + 510 2 .byte 0x55 3 .byte 0xaa
因為一個有效的啟動扇區最后的兩個字節內容必須是0x55,0xaa(這是延續下來的,如果不是這兩個字節內容,那么這個啟動扇區會被認為是無效的,不能啟動,所以這兩個字節我把它稱為驗證字節),所以會有地2,3行內容,至于. = _start + 510,這里的 . 代表當前位置,也就是說,把當前位置設置為從代碼開始增加510 bytes的位置,因為一個扇區大小為512 bytes(以前也有別的大小,但是后來512成為主流),所以兩個字節的大小留給驗證字節。
?
至此,我們的demo? bootloader代碼就寫好了,下面進行匯編,鏈接。
- as test.S -o test.o
- ld –Ttext 0x7c00 --oformat=binary test.o –o test.bin
-Ttext 0x7c00 告訴linker你想把代碼加載到內存0x7c00處(至于為什么是這個地方,可以百度,很有意思),我們生成的是test.bin,也就是二進制文件,可以直接執行。
好了,程序有了,還需要把它寫入存儲介質的啟動扇區,那我們就來創建一個。
- dd if=/dev/zero of=floppy.img bs=512 count=2880
- dd if=test.bin of=floppy.img
我們創建了一個512 bytes的img文件,然后把我們的程序寫入。
現在/home/chao/Documents/目錄下面應該是這個樣子的
?
好了,啟動設備已經就緒,我們還需要測試下它行不行,那就用到bochs了,它是一個虛擬機軟件,
安裝命令:
sudo apt-get install bochs bochs-sdl
有的地方說安裝bochs-x,但是會出現問題,保險起見還是用bochs-sdl.
現在我們為bochs寫一個配置文件
在/home/chao/Documents/目錄下創建bochsrc.txt
1 megs: 32 2 #romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000 3 #vgaromimage: /usr/share/bochs/VGABIOS-lgpl-latest 4 floppya: 1_44=floppy.img, status=inserted 5 boot: a 6 log: bochsout.txt 7 mouse: enabled=0 8 display_library: sdl
注意:2,3行中的路徑可能不同,根據自己的系統查找BIOS-bochs-latest和VGABIOS-lgpl-latest(也可能是其它的而不是VGA,根據自己的情況設置)。
為了方便,可以創建一個build.sh腳本
?
1 as test.S -o test.o 2 ld -Ttext 0x7c00 --oformat=binary test.o -o test.bin 3 dd if=/dev/zero of=floppy.img bs=512 count=2880 4 dd if=test.bin of=floppy.img
?
如果把創建img文件的步驟放入腳本中,那么/home/chao/Documents/目錄下現在有3個文件
?
?
?
打開終端,切換到此目錄,執行build.sh,然后所需要的文件都有了
然后執行命令
bochs
可以看到在bochs中顯示字符 X
至此,一個demo bootloader就寫完了。
這段代碼并沒有干什么事情,只是解釋了如何在計算機啟動時執行我們的代碼,真正的bootloader會加載內核程序(或者加載其他的程序,通過其他的程序來加載內核)。