官术网_书友最值得收藏!

1.3 第一個內核程序

學習一門編程語言往往會從打印Hello World開始,開發操作系統也同樣如此。讀者在本節將會看到一個最簡單的操作系統雛形,它的唯一作用就是在屏幕上顯示“Hello World!”。

1.3.1 打印Hello World

首先創建文件bootsect.S,這是一個基于匯編語言的源文件。系統的引導就是從這個文件開始的,使用匯編語言與硬件打交道是最方便的。本書選擇的匯編編譯器是GNU的as,采用的是AT & T語法。編輯文件內容,如代碼清單1-1所示。

代碼清單1-1 bootsect.S源代碼

1  BOOTSEG=0x7c0

2

3  .code16

4  .text

5

6  .global_start

7  _start:

8   jmpl$BOOTSEG,$start2

9

10 start2:

11   movw $BOOTSEG,%ax

12   movw %ax,%ds

13   movw %ax,%es

14   movw %ax,%fs

15   movw %ax,%gs

16

17   movw $msg,%ax

18   movw %ax,%bp

19   movw $0x01301,%ax

20   movw $0x0c,%bx  #文字為紅色

21   movw $12,%cx   #字符串長度

22   movb $0,%dl

23   int $0x010    #通知顯卡刷新內容

24

25 loop:

26   jmp loop

27

28 msg:

29 .ascii"Hello World!"

30

31 .org 510

32 boot_flag:

33   .word 0xaa55

在控制臺編譯bootsect.S,命令如下:

1 #as-o bootsect.o bootsect.S

2 #ld-m elf_x86_64-Ttext 0x0-s--oformat binary-o linux.img bootsect.o

如果一切順利,則在當前目錄下可以看到linux.img文件已創建。將這個文件復制到Bochs的linux011目錄下,并在這個目錄下執行run.bat文件,則會看到Bochs虛擬機運行起來以后在屏幕上打印了紅色的“Hello World!”,如圖1-1所示。

圖1-1 在屏幕上打印“Hello World!”

如果使用QEMU運行,則需要將linux.img復制到QEMU所在的目錄中,然后在QEMU文件路徑中打開PowerShell或者cmd,并執行如下命令:

.\qemu-system-i386.exe-boot a-fda linux.img

則同樣可以看到,QEMU虛擬機運行起來后在屏幕中打印了紅色的“Hello World!”,如圖1-2所示。

圖1-2 在QEMU中顯示“Hello World!”

代碼清單1-1第11~15行是設置寄存器的值:將cs寄存器中的值設置到ds和es寄存器。第17~18行是將要打印的字符串的首地址放到bp寄存器。第23行是一條中斷觸發指令,中斷號是0x10,表示和顯示器相關的服務。中斷功能號保存在ah中。在第19行,ax被賦值為0x1301,那么對應的ah值為0x13。0x13表示在teletype模式下顯示字符串。同時al的值為0x01,表示顯示輸出方式為字符串中含顯示字符和顯示屬性,并且顯示后光標位置不變。第20行將0x0c放入bx,在中斷號為0x10、功能號為0x13的情況下,bh寄存器存放的是頁碼,bl寄存器用于設置文字顏色,其中0xc代表紅色。第21行將字符串長度送入cx寄存器。第22行表示輸出光標的位置,dh表示行號、dl表示列號,這里都為0,表示光標在屏幕的左上角。

1.3.2 開機引導程序

BIOS(Basic Input/Output System,基本輸入/輸出系統)是計算機接通電源后執行的第一個程序。BIOS首先會做硬件檢查,判斷是否滿足計算機運行的條件,例如,內存條如果沒插好,BIOS會提示錯誤信息,某些情況下主板會發出蜂鳴聲警告等。

做完硬件檢查之后要確定啟動順序,當選中某塊磁盤之后,控制權限就會交給這塊磁盤上的MBR(Master Boot Record,主引導記錄)。MBR位于磁盤的第一個扇區,一個扇區只有512字節,其中最后兩個字節是0x55和0xAA,表明這個設備可以啟動。

回顧1.3.1節的bootsect.S的ld選項,-Ttext 0x0的含義正是將目標文件bootsect.o的代碼段放到linux.img的開頭,也就是在第一個扇區。同時我們可以用如下命令查看第一個扇區的最后兩個字節為0x55AA,可以用來啟動。

xxd-s 510 linux.img

1981年8月,IBM公司最早的個人電腦IBM PC 5150上市,使用的是Intel的第一代個人電腦芯片8088。8088芯片本身需要占用0x0000~0x03FF的地址空間,用來保存各種中斷處理程序(引導程序本身就是中斷信號INT 19h的處理程序)。所以,內存只剩下0x0400至0x7FFF的地址空間可以使用。為了把盡量多的連續內存留給操作系統,引導程序就被放到了內存地址的尾部。因為一個扇區是512(十六進制為0x200)字節,引導程序本身也需要一段內存保存數據,系統就另外給它留出512字節。所以,引導扇區的預留位置就變成了0x7FFF?512?512+1=0x7FFF?0x200?0x200+0x1=0x7C00。

在1.3.1節的例子中,bootsect.S中定義了BOOTSEG=0x7c0,匯編代碼將被加載到內存地址0x7C00執行。需要注意的是,早期的8086處理器的寄存器都是16位的,地址線是20位,這就意味著CPU的尋址能力是1MB(2的20次方),但是只采用一個寄存器只能尋址64KB(2的16次方),所以它采用了基地址加偏移的方式尋址,也就是使用兩個寄存器的值拼接一個真實的物理地址。它的計算方式是物理地址等于基地址左移4位加上偏移值,例如下面的代碼:

mov %ds:(%ax),%bx

上述代碼表示以ds寄存器為基地址,以ax寄存器為偏移值計算一個地址,然后取這個內存地址處的值,送入bx寄存器。其中,真實物理地址的值是ds的值左移4位再加上ax寄存器的值。

主站蜘蛛池模板: 罗定市| 广丰县| 海丰县| 台中市| 水富县| 洪泽县| 晴隆县| 廊坊市| 江源县| 长沙市| 翁牛特旗| 银川市| 教育| 黔南| 西吉县| 榆林市| 文化| 辽阳市| 铅山县| 龙江县| 栾城县| 礼泉县| 监利县| 凌海市| 金沙县| 噶尔县| 米易县| 文成县| 东光县| 朝阳市| 明光市| 太康县| 历史| 平湖市| 千阳县| 洛阳市| 阿尔山市| 宿迁市| 华阴市| 商河县| 栾城县|