以上是個非常簡單的操作系統helloworld源碼,用bochs載入後如下圖(bochs是個虛擬機,模擬操作系統載入),顯示了紅色的Hello,OS world,實際上是系統載入起來的樣子: 源碼解析: 1.org 07c00h和dw 0xaa55和times 510-($-$$) db 0 當計算 ...
org 07c00h ;偽指令,告訴編譯器程式會被載入到7c00處 mov ax, cs mov ds, ax 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 ;pop IP BootMessage: db "Hello, OS world!" times 510-($-$$)db 0 ;填充剩下的空間,使生成的二進位代碼恰好為512位元組 dw 0xaa55 ;結束標誌
以上是個非常簡單的操作系統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位元組。