Linux核心系列—作業系統開發之HelloWorld,linuxhelloworld
org 07c00h ;偽指令,告訴編譯器程式會被載入到7c00處mov ax, csmov ds, axmov es, axcall DispStr ;調用顯示字串常式jmp $;無限迴圈DispStr:mov ax, BootMessagemov bp, ax;ES:BP=字串地址mov cx, 16;CX=字串長度mov ax, 01301h;AH=13,AL=01hmov bx, 000ch;頁號為0(BH=0)黑底紅字(BL=0Ch,高亮)mov dl, 0int 10h;10h號中斷ret ;pop IPBootMessage:db "Hello, OS world!"times 510-($-$$)db 0 ;填充剩下的空間,使產生的二進位代碼恰好為512位元組dw0xaa55;結束標誌
以上是個非常簡單的作業系統helloworld源碼,用bochs載入後如(bochs是個虛擬機器,類比作業系統載入),顯示了紅色的Hello,OS world,實際上是系統載入起來的樣子:
源碼解析:
1.org 07c00h和dw 0xaa55和times 510-($-$$) db 0
當電腦電源開啟,會先進行加電自檢(POST),然後尋找啟動盤,如果是選擇從磁碟片啟動,電腦會檢查磁碟片的0面0磁軌1扇區,如果發現它以0xaa55結束,則BIOS認為它是一個開機磁區。一個正確的開機磁區除了以0xaa55結束之外,還應該包含一段512位元組的執行碼。一旦BIOS發現了開機磁區,就會將這512位元組的內容裝載到記憶體位址0000:7c00處,然後跳轉到0000:7c00處將控制權徹底交給這段引導代碼。
org 07c00h就是告訴編譯器,這段代碼是要被載入到這個地址的。所以BootMessage的位移地址是相對於07c00h處開始的。BootMessage實際上也是一個地址,不是相對量
2.mov ax, cs、mov ds, ax、mov es, ax
讓ds和es指向cs的段,也就是07c00h。因為程式會被載入到07c00h處,所以執行到這一步的時候CS指向07c00h
3.call DispStr
調用顯示字串的函數,在NASM中,任何不被[]括起來的標籤或變數名都被認為是地址,如果是訪問標籤中的內容則必須使用[]。所以mov ax, BootMessage會把"Hello,OS world!"這個字串的首地址傳給寄存器ax。然後mov bp, ax賦給bp,如果沒寫org指令,則BootMessage編譯的時候就是相對於本程式載入到地址0的位移地址,但是這裡是相對於07c00h為基址的位移地址,所以這裡顯示了org的作用。
4.int 10h
10H中斷是由BIOS對顯示器和螢幕所提供的服務程式。使用int 10h服務程式時,必須先指定ah寄存器。
功能13h:
功能描述:在Teletype模式下顯示字串
入口參數:AH=13H
BH=頁碼
BL=屬性(若AL=00H或 01H)
CX=顯示字串長度
(DH、DL)=座標(行、列)
ES:BP=顯示字串的地址
AL=顯示輸出方式
0—— 字串中只含顯示字元,其顯示內容在BL中。顯示後,游標位置不變
1——字串中只含顯示字元,其顯示內容在BL中。顯示後,游標位置改變
2 ——字串中含顯示字元和顯示內容。顯示後,游標位置不變
3——字串中含顯示字元和顯示內容。顯示後,游標位置改變
出口參數:無
5.$和$$
$-$$表示本行距離程式開始處的相對距離。times 510-($-$$) db 0表示將0這個位元組重複510-($-$$)遍,也就是在剩下的空間中不停地填充0,直到程式有510位元組為止。這樣,加上結束標誌0xaa55佔用的2位元組,恰好是512位元組。