文章目錄
一、工作環境和準備工作
學習環境:
Windows(原機) + Ubuntu 12.04.5(Oracle VM VirtualBox虛擬機) + Bochs.2.6.8 + NASM + GCC
環境搭建:
- 我們要在
windows
系統下安裝virtualbox
軟件; - 之後要用
virtualbox
創建一個虛擬機,併爲這個虛擬機安裝ubuntu
系統; - 接着啓動剛裝好的
ubuntu
虛擬機,在其中安裝bochs
(注意編譯時的配置選項,書中有說明,不然將無法進行調試); - 最終運行書中的第一個示例
軟件& Linux Distribution
版本要求:
virtualbox:6.0.12
ubuntu
鏡像:ubuntu-12.04.5-desktop-i386.iso
bochs
:bochs-2.6.8.tar.gz
簡要的參考步驟:
-
卸載系統中已有的
virtualbox
,安裝最新版本的
https://www.virtualbox.org/wiki/Downloads
; -
用
virtualbox
創建並安裝Ubuntu
系統,從http://mirrors.163.com/ubuntu-releases
下載ubuntu-12.04.5-desktop-i386.iso
鏡像進行安裝; -
從
http://bochs.sourceforge.net/getcurrent.html
下載bochs
源碼bochs-2.6.8.tar.gz
,在ubuntu
中編譯安裝bochs
軟件 -
使用
bximage
創建軟驅,調試書上第一個例子。具體書中已經寫了。同時參考http://bbs.21ic.com/blog-1423056-134746.html
書的第一章是簡要開頭,第二章是準備工作。
二、第一章 馬上動手寫一個最小的“操作系統”
1. 第一章筆記
書中給出的代碼如下:
org 07c00h ; 告訴編譯器程序加載到7c00處
mov ax, cs
mov ds, ax ; 使ds,es段寄存器指向與cs相同的段
mov es, ax
call DispStr ; 調用顯示字符串例程
jmp $ ; 無限循環
DispStr:
mov ax, BootMessage
mov bp, ax ; ES:BP = 串地址
mov cx, 16 ; CX = 串長度
mov ax, 01301h ; AH = 13, AL = 01h
mov bx, 000ch ; 頁號爲0(BH = 0) 黑底紅字(BL = 0Ch,高亮)
mov dl, 0
int 10h ; 10h 號中斷
ret
BootMessage: db "Hello, OS world!"
times 510-($-$$) db 0 ; 填充剩下的空間,使生成的二進制代碼恰好爲512字節
dw 0xaa55 ; 結束標誌
上述代碼實際上是一個引導扇區 boot sector
,它直接在裸機上運行,不依賴於其他軟件。當計算機電源被打開後:
- 計算機先進行加電自檢
POST
; - 然後尋找啓動盤,如果是選擇從軟盤打開,BIOS會檢查軟盤的
0
面0
磁道1
扇區,如果發現該扇區是以0xaa55
結束,則BIOS認爲它是一個boot sector
; - 一旦BIOS發現了引導扇區,就會將這
512
字節的內容裝載到內存地址0000:7c00
處,然後跳轉到0000:7c00
處將控制權徹底交給這段引導代碼; - 此後,計算機不再由BIOS控制,而是由操作系統的一部分來控制。
部分指令說明:
org
僞指令,用來規定程序存放單元的偏移量,如果在源程序的第一條指令使用了這樣的指令如org 2000h
,則彙編程序會把ip
設爲2000h
,程序的第一個字節存放到2000h
處,然後依次順序存放後面的內容,直到遇到另一個org
。times 510-($-$$) db 0
將0
字節重複510-($-$$)
次。
2. nasm學習
本書使用的是 nasm
的語法(The Netwide Assembler
) ,NASM是目前唯一開源免費的彙編器,和MASM一樣遵從Intel語法,指令集、語法規則幾乎完全相同。
實模式編程:Linux和Windows運行在x86的機器上,都是運行在保護模式下的,因此我們需要將編譯好的實模式程序寫進虛擬硬盤的主引導扇區,然後由虛擬機啓動來觀察程序運行效果。
和 masm
的區別在於:
nasm
中任何不被方括號[]
括起來的標籤和變量名都是地址;訪問標籤中的內容必須用[]
;因此不需要offset
關鍵字;nasm
中,變量和標籤是一樣的,下面兩條語句是等價的:foo dw 1 foo : dw 1
nasm
中的$
是當前語句的地址;$$
是本節section
的起始語句的地址。nasm
中使用section
表示一段代碼,後面跟一個段的名稱(自定義)和段屬性。nasm
的標準段包括section .data
/section .text
/section .bss
,它們默認包含vstart = 0
的語義,即段內的指令和標號的彙編地址都是段內偏移地址。
先安裝 nasm
,然後使用 nasm
編譯上述的代碼,我們就得到了一個 512
字節的 boot.bin
代碼:
sudo apt-get install nasm
nasm boot.asm -o boot.bin
其他nasm指令參見nasm中文手冊。
3. 實際操作
我的機器沒有軟驅,所以要創建一個虛擬軟盤。由於 VirtualBox
不能像創建虛擬空白硬盤一樣創建虛擬軟盤,而只能選擇一個已有的虛擬軟驅 .img
,所以要先創建一個基於編譯得到的 boot.bin
的虛擬軟盤。 命令如下:
dd if=boot.bin of=floppy.img bs=512 count=1
這條命令創建出一個大小爲 512B
,名爲 floppy.img
,寫入了 boot.bin
的虛擬軟盤鏡像。其中 boot.bin
是讀取位置,floppy.img
是寫入位置。
爲了實現像書中一樣的效果,可以在 VirtualBox
裏創建一個 MyOS
虛擬機。點擊新建後,過程中要改動的默認設置有:操作系統和版本都選擇 Other
,內存大小選 4 mb
,不創建虛擬硬盤。
建成後不要啓動,還需要進行設置:
- 選中建好的
MyOS
,點擊設置 ,在系統中啓動順序只在軟驅上打√
; - 存儲中,選擇添加軟盤控制器,然後添加虛擬軟驅,選擇文件夾下的
floppy.img
,點擊OK;
- 這時虛擬機
MyOS
就完成了,啓動後畫面如下:
這樣,第一章就完成了。
三、第二章 搭建你的工作環境
如果一直使用虛擬軟盤,太麻煩了,所以我們需要使用 bochs
搭建工作環境。
書中分別介紹了 windows
和 linux
的安裝過程,我這裏雖然是 windows
的機器,但是全部過程都在 linux
虛擬機中完成。
儘管如此,爲了使用實驗提供的環境和程序源代碼,我開啓了VGA增強功能,創建了一個共享文件夾,用於主機和虛擬機的信息交換。
1. bochs安裝和使用步驟
這一部分折騰了我許久,書中的一些配置現在已經不適合了,出現了許多錯誤。
① 預裝相關程序和庫:
sudo apt-get install build-essential xorg-dev libgtk2.0-dev
② 安裝前的配置命令:(在 root
用戶下)
./configure --with-x11 --with-wx --enable-debugger --enable-disasm --enable-all-optimizations --enable-readline --enable-long-phy-address --enable-debugger-gui
③ 編譯安裝
make
make install
④ 將 bochs2.6.8
目錄下的 bios
文件夾中的全部內容複製到 /usr/share/bochs
目錄中,沒有 bochs
文件夾的話需要自己創建。
⑤ 設置配置文件。這一步相當重要,如果沒有設置好的話,就會出現各種各樣的錯誤:
###############################################################
# Configuration file for Bochs
###############################################################
# how much memory the emulated machine will have
megs: 32
# filename of ROM images
romimage: file=/usr/local/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest
# what disk images will be used
floppya: 1_44=a.img, status=inserted
# choose the boot disk.
boot: floppy
# where do we send log messages?
log: bochsout.txt
# disable the mouse
mouse: enabled=0
# enable key mapping, using US layout as default.
keyboard: keymap=/usr/local/share/bochs/keymaps/x11-pc-us.map
上面是我的配置文件 bochsrc
。如果照着書中的配置的話,會出現一些錯誤:
- 運行bochsrc時,出現錯誤
ROM: couldn't open ROM image file '/usr/share/bochs/BIOS-bochs-latest'
,要將第9
行的romimage: file=/usr/share/bochs/BIOS-bochs-latest
改爲romimage: file=/usr/local/share/bochs/BIOS-bochs-latest
; - 運行bochsrc時,出現錯誤
bochsrc:10: vgaromimage directive malformed
,要將bochsrc
文件中第10
行的vgaromimage: /usr/share/vgabios/vgabios.bin
改爲vgaromimage: file=/usr/share/vgabios/vgabios.bin
或者改爲我給出的配置文件中的形式,具體視bochs/bios
中的內容和自己的文件夾組織方式而定; - 運行時出現關於
keymap
的錯誤如:
需要將文件最後一行的keyboard_mapping: enabled=1, map=/usr/share/bochs/keymaps/x11-pc-us.map
改爲keyboard: keymap=/usr/local/share/bochs/keymaps/x11-pc-us.map
。
⑥ 利用 bximage
生成軟盤映像,在第一步提示中輸入 fd
即可。具體可以參照書中描述。
⑦ 將引導扇區 boot.bin
寫入虛擬軟盤:
dd if=boot.bin of=a.img bs=512 count=1 conv=notrunc
⑧ 運行 bochs
:
- 啓動
bochs
:bochs
- 默認選擇
[6]
,因此回車即可,然後彈出一個黑框,無內容:
- 此時在終端中鍵入
c
並回車就會執行:
2. bochs調試操作系統
運行的是一個有調試功能的 bochs
,啓動後會出現若干選項,一般默認爲 6. Begin simulation
,直接按回車鍵就可以了。不過之後 bochs
沒有直接進入運轉,而是給出了一個提示符,等待輸入。
此時,如果要調試的話,可以設置斷點、查看CPU寄存器、查看某個內存地址的內容等。具體過程見書。
一些常用的命令如下: