此次實驗的基本內容是:
1. 閱讀《Linux內核完全注釋》的第6章,對計算機和Linux 0.11的引導過程進行初步的了解;
1. 按照下面的要求改寫0.11的引導程序bootsect.s
1. 修改build.c,以便可以使用 make BootImage命令
改寫bootsect.s主要完成如下功能:
1. bootsect.s能在屏幕上打印一段提示信息“XXX is booting...”,其中XXX是你給自己的操作系統起的名字,例如LZJos、Sunix等(可以上論壇上秀秀誰的OS名字最帥,也可以顯示一個特色logo,以表示自己操作系統的與眾不同。)
### 完成bootsect.s的屏幕輸出功能
首先來看完成屏幕顯示的關鍵代碼如下:
~~~
! 首先讀入光標位置
mov ah,#0x03
xor bh,bh
int 0x10
! 顯示字符串“LZJos is running...”
mov cx,#25 ! 要顯示的字符串長度
mov bx,#0x0007 ! page 0, attribute 7 (normal)
mov bp,#msg1
mov ax,#0x1301 ! write string, move cursor
int 0x10
inf_loop:
jmp inf_loop ! 后面都不是正經代碼了,得往回跳呀
! msg1處放置字符串
msg1:
.byte 13,10 ! 換行+回車
.ascii "LZJos is running..."
.byte 13,10,13,10 ! 兩對換行+回車
!設置引導扇區標記0xAA55
.org 510
boot_flag:
.word 0xAA55 ! 必須有它,才能引導
~~~
接下來,將完成屏幕顯示的代碼在開發環境中編譯,并使用linux-0.11/tools/build.c將編譯后的目標文件做成Image文件。
**這里改動**
~~~
mov cx,#25 ! 要顯示的字符串長度
和
~~~
msg1:
~~~
.byte 13,10 ! 換行+回車
.ascii "LZJos is running..."
.byte 13,10,13,10 ! 兩對換行+回車
!設置引導扇區標記0xAA55
~~~
修改你要顯示的內容及計算長度,其中13算一個,10算一個,字母或空格算1個
修改bootsect.s
~~~
! Print some inane message
mov ah,#0x03 ! read cursor pos
xor bh,bh
int 0x10
mov cx,#27 !修改這里
mov bx,#0x0007 ! page 0, attribute 7 (normal)
mov bp,#msg1
mov ax,#0x1301 ! write string, move cursor
int 0x10
~~~
及(msg1可以改成很多種)
~~~
msg1:
.byte 13,10
.ascii "Jinux OS is booting ..."
.byte 13,10,13,10
~~~
### 修改build.c
build.c從命令行參數得到bootsect、setup和system內核的文件名,將三者做簡單的整理后一起寫入Image。其中system是第三個參數(argv[3])。當“make all”或者“makeall”的時候,這個參數傳過來的是正確的文件名,build.c會打開它,將內容寫入Image。而“make BootImage”時,傳過來的是字符串"none"。所以,改造build.c的思路就是當argv[3]是"none"的時候,只寫bootsect和setup,忽略所有與system有關的工作,或者在該寫system的位置都寫上“0”。
修改工作主要集中在build.c的尾部,請斟酌。
當按照前一節所講的編譯方法編譯成功后,run,就得到了如圖3所示的運行結果,和我們想得到的結果完全一樣。
因為傳過來的是字符串"none",所以只要在build.c判斷一下第三個值是否為none,修改最下面
bulid.c之前為
~~~
if ((id=open(argv[3],O_RDONLY,0))<0)
die("Unable to open 'system'");
// if (read(id,buf,GCC_HEADER) != GCC_HEADER)
// die("Unable to read header of 'system'");
// if (((long *) buf)[5] != 0)
// die("Non-GCC header of 'system'");
for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
if (write(1,buf,c)!=c)
die("Write call failed");
close(id);
fprintf(stderr,"System is %d bytes.\n",i);
if (i > SYS_SIZE*16)
die("System is too big");
return(0); </span></span>
~~~
改為
~~~
if(strcmp("none",argv[3]) == 0) //添加判斷
return 0;
if ((id=open(argv[3],O_RDONLY,0))<0)
die("Unable to open 'system'");
// if (read(id,buf,GCC_HEADER) != GCC_HEADER)
// die("Unable to read header of 'system'");
// if (((long *) buf)[5] != 0)
// die("Non-GCC header of 'system'");
for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
if (write(1,buf,c)!=c)
die("Write call failed");
close(id);
fprintf(stderr,"System is %d bytes.\n",i);
if (i > SYS_SIZE*16)
die("System is too big");
return(0);</span>
~~~
附report1:
1.有時,繼承傳統意味著別手蹩腳。x86計算機為了向下兼容,導致啟動過程比較復雜。請找出x86計算機啟動過程中,被硬件強制,軟件必須遵守的兩個“多此一舉”的步驟(多找幾個也無妨),說說它們為什么多此一舉,并設計更簡潔的替代方案。
答:1)x86CPU啟動時為了向下兼容16位使用實模式:純16位無保護執行環境。對于80286或以上的CPU通過A20 GATE來控制A20地址線。
技術發展到了80286,雖然系統的地址總線由原來的20根發展為24根,這樣能夠訪問的內存可以達到2^24=16M,但是Intel在設計80286時提出的目標是向下兼容,所以在實模式下,系統所表現的行為應該和8086/8088所表現的完全一樣,也就是說,在實模式下,80386以及后續系列應該和8086/8088完全兼容仍然使用A20地址線。
所以高級芯片為了運行以前的程序,不得不保留實模式。所以說80286芯片存在一個BUG:它開設A20地址線。
如果程序員訪問100000H-10FFEFH之間的內存,系統將實際訪問這塊內存。進入實模式多此一舉,可以直接進入保護模式。
解決方案:是不向下兼容直接進入32位的保護模式,經管在Intel 80286手冊中已經提出了虛地址保護模式,但實際上它只是一個指引,真正的32位地址出現在Intel 80386上。
保護模式本身是80286及以后兼容處理器序列之后產成的一種操作模式,它具有許多特性設計為提高系統的多道任務和系統的穩定性。
例如內存的保護,分頁機制和硬件虛擬存儲的支持。現代多數的x86處理器操作系統都運行在保護模式下。
2)當PC的電源打開后,80x86結構的CPU將自動進入實模式,并從地址0xFFFF0開始自動執行程序代碼,這個地址通常是ROM—BIOS中的地址。
PC機的BIOS將執行某些系統的檢測,并在物理地址0處開始初始化中斷向量。此后將啟動設備的第一個扇區512字節讀入內存絕對地址0x7C00處。
因為當時system模塊的長度不會超過0x80000字節大小512KB,所以bootsect程序把system模塊讀入物理地址0x10000開始位置處時并不會覆蓋在0x90000處開始的bootsect和setup模塊,多此一舉的是system模塊移到內存中相對靠后的位置,以便加載系統主模塊。
解決方案是在保證操作系統啟動引導成功的前提下盡量擴大ROM—BIOS的內存尋址范圍,以達到不需要讀入靠后的位置處。
2.操作系統的引導程序都完成哪些功能?你知道幾個操作系統引導程序?分別是什么?
1)操作系統的引導程序一般完成識別主機的某些特性,
2)確保內核被正確加載;
3)加載內核到內存;
4)將系統控制權交給內核;
5)通知內核所需要的根文件系統的位置;
6)確定根文件的設備號;
7)將CPU由實模式切換為保護模式等功能。
我知道的操作系統的引導程序有:
1)NTLDR,它是windows nt 4.0/windows 2000/windows xp/windows server 2003的引導文件
2)GNU GRUB,它是是一個來自GNU項目的多操作系統啟動程序。GRUB是多啟動規范的實現,它允許用戶可以在計算機內同時擁有多個操作系統,并在計算機啟動時選擇希望運行的操作系統。</span>
由于實驗簡化,setup.s的相關實驗已經不作要求,此處可參考往屆學長學姐實驗博客