本書依靠的教材是於淵的《Orange'S:一個操作系統的實現》
實驗環境及工具
- ArchLinux(windows也可以)
- 代碼編輯器Emacs(你盡情使用自己喜歡的編輯器)
- nasm (一個開源的匯編器,可以從sourceforge下載,也可以從Linux發行版的軟件倉庫安裝)
思路:
- 寫一段匯編代碼,輸出
Hello, World
- 將該段代碼寫入軟盤鏡像的第一個扇區
- 安裝virtualbox創建一個操作系統,從軟盤鏡像引導,查看結果
引導區代碼
;; BIOS會把512字節的引導扇區加載到 0000:7c00 處,
;; 然后跳轉到0000:7c00處,將控制權交給引導代碼。
org 07c00h ;這一行告訴編譯器,我們的代碼將被加載到7c00處。
mov ax, cs ;將代碼段寄存器的值送入AX
mov ds, ax ;將數據段的地址置為代碼段的地址?
mov es, ax ;將附加段的地址置為代碼段的地址?
call DispStr ;調用顯示字符串例程
jmp $ ;無限循環, $表示當前行編譯后的地址
;; 以上就是整個程序的執行過程了
;; 下面是DispStr子程序
DispStr:
mov ax, BootMessage ;將字符串首地址傳給寄存器ax
mov bp, ax ;CPU將用ES:BP來尋址字符串
mov cx, 16 ;通過CX,CPU知道字符串的長度
mov ax, 01301h ;AH=13表示13號中斷, AL=01H,表示目標字符串僅僅包含字符,屬性在BL中包含,移動光標
mov bx, 000ch ;黑底紅字, BL=0CH,高亮
mov dl, 0 ;dh表示在第幾行顯示,dl表示第幾列顯示
int 10h ;BIOS的10H中斷的13號中斷用於顯示字符串
ret
BootMessage: db "Hello, OS world!" ;對NASM來講,標號和變量的作用一樣, db表示define byte
;; $當前行被匯編后的地址,$$表示一個section開始處的地址,本程序只有一個section,所以指0x7c00
times 510-($-$$) db 0 ;填充剩下空間,使生成的二進制恰好為512字節
dw 0xaa55 ;結束標志,如果發現扇區以0xAA55結束,則BIOS認為它是一個引導扇區,dw表示define word
關於中斷顯示字符串的細節,可參見使用BIOS中斷顯示字符串筆記(int 10h 13號中斷)。
編譯生成二進制
需要nasm
。如果你使用Linux,可以直接從軟件倉庫安裝。
nasm
即可以從匯編代碼生成目標代碼,也帶了一個反匯編工具ndisasm
, 可以從目標代碼生成匯編代碼。
編譯我們的扇區代碼生成二進制:
nasm boot.asm -o boot.bin
寫入軟盤的第一個扇區
我們用軟盤鏡像來模擬軟盤。
dd if=/dev/zero of=emptydisk.img bs=512 count=2880 #生成空白軟盤鏡像文件
dd if=boot.bin of=boot.img bs=512 count=1 #用 bin file 生成對應的鏡像文件
dd if=emptydisk.img of=boot.img skip=1 seek=1 bs=512 count=2879 #在 bin 生成的鏡像文件后補上空白,成為合適大小的軟盤鏡像
這樣,我們引導系統用的虛擬軟盤就准備好了。
安裝virtualbox,建立系統
可以直接從Linux軟件倉庫安裝virtualbox。
把當前用戶加入vboxusers
組:gpasswd -a <username> vboxusers
。
啟動virtualbox,可能提示vboxdrv未能成功加載。如果發生這種情況,需要重新編譯vboxdrv模塊。安裝linux-headers
和dkms
,然后sudo dkms autoinstall
就會編譯生成vboxdrv模塊。
手動執行sudo modprobe vboxdrv
加載vboxdrv模塊,啟動virtualbox應該不會有問題了。
建立一個虛擬機,有沒有硬盤都可以,增加一個軟驅,把我們的boot.img
加載到軟驅中,啟動虛擬機,成功的話,可以看到:
virtualbox可能出現的問題:
-
Failed to open a session for the virtual machine a. Failed to load VMMR0.r0 (VERR_SUPLIB_OWNER_NOT_ROOT). Unknown error creating VM (VERR_SUPLIB_OWNER_NOT_ROOT).
解決方法:sudo chown -R root:root /usr/lib/virtualbox
-
Effective UID is not root
. 解決方法:sudo chmod 4711 /usr/lib/virtualbox/VirtualBox
。
參見: https://www.virtualbox.org/ticket/7889