直接看代碼,即使已經理解了代碼,但是還是會有種沒有學到手的感覺.真正的掌握來自實踐,來自己動手做出來.“簡單AB任務切換程式”系列文章的目的是,在bochs下,實踐出簡單AB兩個任務的切換.
1. bochs安裝或者編譯參考
Ubuntu10.04搭建linux-0.11編譯環境(1.bochs安裝和使用)
Ubuntu10.04搭建linux-0.11編譯環境(2.bochs編譯)
2. 實現一個最簡單的bootloader
(1)bootloader,顧名思義boot + loader,我們現在只實現boot,loader其實就是簡單bios中斷調用,後面接觸.
(2)此處使用組合語言,彙編和連接器分別為as86和ld86,ubuntu下sudo apt-get install bin86即可
(3)代碼boot.s
.globl begtext,begdata,begbss,endtext,enddata,endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
BOOTSEG = 0x07c0
entry start
start:
jmpi go,BOOTSEG
go:
mov ax,cs
mov ds,ax
mov es,ax
mov ax,#0x0600
mov cx,#0x0000
mov dx,#0xFFFF
int 0x10
mov cx,#20
mov dx,#0x0000
mov bx,#0x000c
mov bp,#msg1
mov ax,#0x1301
int 0x10
loop0: jmp loop0
msg1: .ascii "Loading system ..."
.byte 13,10
.org 510
.word 0xAA55
(4)分析
.globl begtext,begdata,begbss,endtext,enddata,endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
以上幾句告訴彙編器和連接器要聲明的全域符號,同時說明程式的所有段都從一個基地址開始.
BOOTSEG = 0x07c0
entry start
start:
jmpi go,BOOTSEG
go:
entry start告訴彙編器程式的入口是start符號
因為我們這段是引導代碼,引導代碼在引導盤的指定位置處,bios會預設讀出來放到記憶體0x7c00:0x0處,所以所有的段基地址其實都是0x7c00.
jmpi do,BOOTSEG是跳轉到0x7c00:go處執行,go其實是個相對當前jmpi do,BOOTSEG這條指令的一個位移,假設是5,這句話其實是跳到了0x7c00:0x5處執行,同時一個作用是隱含地設定了cs為0x7c00,這句話可以不用直接替換後邊的mov ax,cs:
mov ax,#BOOTSEG或者mov ax,0x7c00
mov ax,cs
mov ds,ax
mov es,ax
以上幾句設定了ds和es段與cs保持相同,因為程式中聲明了代碼資料附加段都是一個基地址的
mov ax,#0x0600
mov cx,#0x0000
mov dx,#0xFFFF
int 0x10
以上幾句調用bios的0x10中斷,清屏.關於bios中斷不用瞭解許多,知道用法能查手冊即可,手冊網路上有很多.
mov cx,#20
mov dx,#0x0000
mov bx,#0x000c
mov bp,#msg1
mov ax,#0x1301
int 0x10
以上幾句調用了bios的0x10中斷,顯示一個字串msg1
loop0: jmp loop0
看以看出來是無限迴圈
msg1: .ascii "Loading system ..."
.byte 13,10
定義字串
.org 510
.word 0xAA55
在510位置後定義0xAA55,開機磁區標誌.
3.編譯調試bootloader
前邊說過使用的as86彙編器和ld86連接器,使用bochs模擬器.
bochs支援虛擬磁碟片和硬碟,因為磁碟片簡單一些,所以我們把程式編譯後少些到磁碟片上即可啟動了.
(1)編譯boot.s
as86 -0 -a -o boot.o boot.s
boot.s是源碼,boot.o是編譯輸出
(2)連結boot.o
ld86 -0 -s -o boot boot.o
boot.o是(1)的輸出,boot是連結輸出
(3)製作虛擬磁碟
dd bs=32 if=boot of=boot.img skip=1
因為boot前32位元組是檔案頭,所以要跳過不寫,把後邊的所有內容寫進boot.img
至此boot.img就是做好的可開機虛擬磁碟了
4. 運行與bochs調試
(1)bochs配置
bochs設定檔bochsrc.txt如下:
config_interface: textconfig
romimage: file=/usr/local/share/bochs/BIOS-bochs-latest
megs: 16
vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest
floppya: 1_44="boot.img", status=inserted
boot: a
vga_update_interval: 300000
keyboard_paste_delay: 100000
keyboard_serial_delay: 200
cpu: count=1, ips=1000000
mouse: enabled=0
private_colormap: enabled=0
fullscreen: enabled=0
screenmode: name="sample"
i440fxsupport: enabled=0
(2)運行
目前的目錄下執行bochs
(3)bochs調試命令
c - 繼續
pb 0x7c00 - 在0x7c00處設定斷點
n - 執行下一步
u 0x10000 - 反組譯碼0x10000地區
本文完.