版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
如何編寫(xiě)自己的操作系統(tǒng)
2008年10月15日星期三09:51
如何編寫(xiě)自己的操作系統(tǒng)
有人可能擔(dān)心自己既沒(méi)有學(xué)過(guò)計(jì)算機(jī)原理,也沒(méi)有學(xué)過(guò)操作系統(tǒng)原理,更不懂匯編語(yǔ)言,
對(duì)C語(yǔ)言也一知半解,能寫(xiě)操作系統(tǒng)嗎?答案是沒(méi)問(wèn)題。我將帶大家一步一步完成自己的操作系統(tǒng)。
當(dāng)然如果學(xué)一學(xué)上述內(nèi)容再好不過(guò)。
首先要明確處理器(也就是CPU)控制著計(jì)算機(jī)。對(duì)PC而言,啟動(dòng)的時(shí)候,CPU都處在實(shí)模式狀態(tài),
相當(dāng)于只是一個(gè)Intel8086處理器。也就是說(shuō),即使你現(xiàn)在擁有一個(gè)奔騰處理器,它的功能也只能
是8086級(jí)別。從這一點(diǎn)上來(lái)講,可以使用一些軟件把處理器轉(zhuǎn)換到著名的保護(hù)模式。只有這樣,
我們才可以充分利用處理器的強(qiáng)大功能。
編寫(xiě)操作系統(tǒng)開(kāi)始是對(duì)BIOS控制,取出存儲(chǔ)在ROM里的程序。BIOS是用來(lái)執(zhí)行POST(PowerOnSelfTest,
自檢)的。自檢是檢查計(jì)算機(jī)的完整性(比如外設(shè)是否工作正常、鍵盤(pán)是否連接等)。這一切完成以后,
你就會(huì)聽(tīng)到PC喇叭發(fā)出一聲清脆的響聲。如果一切正常,BIOS就會(huì)選擇一個(gè)啟動(dòng)設(shè)備,
并且讀取該設(shè)備的第一扇區(qū)(即啟動(dòng)扇區(qū)),然后控制過(guò)程就會(huì)轉(zhuǎn)移到指定位置。
啟動(dòng)設(shè)備可能是一個(gè)軟盤(pán)、光盤(pán)、硬盤(pán),或者其它所選擇的設(shè)備。在此我們把軟盤(pán)作為啟動(dòng)設(shè)備。
如果我們已經(jīng)在軟盤(pán)的啟動(dòng)扇區(qū)里寫(xiě)了一些代碼,這時(shí)它就被執(zhí)行。因此,我們的目的很明確,
就是往軟盤(pán)的啟動(dòng)扇區(qū)寫(xiě)一些程序。
首先使用8086匯編來(lái)寫(xiě)一個(gè)小程序,然后將其拷貝至軟盤(pán)的啟動(dòng)扇區(qū)。為了實(shí)現(xiàn)拷貝,要寫(xiě)一個(gè)C程序。
最后,使用軟盤(pán)啟動(dòng)計(jì)算機(jī)。
需要的工具
●as86:這是一個(gè)匯編程序,它負(fù)責(zé)把寫(xiě)的代碼轉(zhuǎn)換成目標(biāo)文件。
●ld86:這是一個(gè)連接器,as86產(chǎn)生的目標(biāo)代碼由它來(lái)轉(zhuǎn)換成真正的機(jī)器語(yǔ)言。
機(jī)器語(yǔ)言是8086能夠解讀的形式。
●GCC:著名的C編程器。因?yàn)槲覀冃枰獙?xiě)一個(gè)C程序?qū)⒆约旱腛S轉(zhuǎn)移到軟盤(pán)中。
●一張空軟盤(pán):它用于存儲(chǔ)編寫(xiě)的操作系統(tǒng),也是啟動(dòng)設(shè)備。
●一臺(tái)裝有Linux的計(jì)算機(jī):這臺(tái)機(jī)器可以很舊,386、486都可以。
在大部分標(biāo)準(zhǔn)Linux發(fā)行版中都會(huì)帶有as86和ld86。在我使用的RedHat7.3中就包含有這兩個(gè)工具,
并且在默認(rèn)的情況下,它已經(jīng)安裝在機(jī)器里。如果使用的Linux沒(méi)有這兩個(gè)工具,可以從網(wǎng)上下載
(http://www.cix.co.uk/~mayday/),這兩個(gè)工具都包含在一個(gè)名為bin86的軟件包中。
此外,有關(guān)的文檔也可以在網(wǎng)上獲得(/docs/ldp/howto/Assembly-HOWTO/as86.html)。
開(kāi)始工作
使用一個(gè)你喜歡的編輯器輸入以下內(nèi)容:
entrystart
start:
movax,#0xb800
moves,ax
seges
mov[0],#0x41
seges
mov[1],#0x1f
loop1:jmploop1
這是as86可以讀懂的一段匯編程序。第一個(gè)句子指明了程序的入口點(diǎn),聲明整個(gè)過(guò)程從start處開(kāi)始。
第二行指明了start的位置,說(shuō)明整個(gè)程序要從start處開(kāi)始執(zhí)行。0xb800是顯存的開(kāi)始地址。
#表明其后是一個(gè)立即數(shù)。執(zhí)行語(yǔ)句:
movax,#oxb800
ax寄存器的值就變?yōu)?xb800,這就是顯存的地址。下面再將這個(gè)值移至es寄存器,es是附加段寄存器。
請(qǐng)記住8086有一個(gè)分段的體系結(jié)構(gòu)。它的各段寄存器為代碼段、數(shù)據(jù)段、堆棧段和附加段,
對(duì)應(yīng)的寄存器名稱(chēng)分別為cs、ds、ss和es。事實(shí)上,我們把顯存地址送入了附加段,因此,
任何送入附加段的東西都會(huì)被送到顯存中。
要在屏幕上顯示字符,就需要向顯存中寫(xiě)兩個(gè)字節(jié)。前一個(gè)是所要顯示字符的ASCⅡ值,
第二個(gè)字節(jié)表示該字符的屬性。屬性包括字符的前景色、背景色及是否閃爍等等。
seges指明下一個(gè)將要執(zhí)行的指令是指向es段的。所以,我們把值0x41(在ASCⅡ中表示的字符是A)送到
顯存的第一個(gè)字節(jié)中。接下來(lái)要把字符的屬性送到下一個(gè)字節(jié)當(dāng)中。在此輸入的是0x1f,
該屬性指的是在藍(lán)色背景下顯示白色的字符。因此,如果執(zhí)行這個(gè)程序,
就可以在屏幕上得到顯示在藍(lán)底上的一個(gè)白色的A。接著是一個(gè)循環(huán)。
因?yàn)樵趫?zhí)行完顯示字符的任務(wù)后,要么讓程序結(jié)束,要么使用一個(gè)循環(huán)使其永遠(yuǎn)運(yùn)行下去。
把該文件命名為boot.s,然后存盤(pán)。
--------------------------------------------------------------------------------
2如何編寫(xiě)自己的操作系統(tǒng)
此處顯存的概念說(shuō)得不是很清楚,有必要進(jìn)一步解釋一下。假設(shè)屏幕由80列×25行組成,
那么第一行就需要160字節(jié),其中一個(gè)字節(jié)用于表示字符,另外一個(gè)字節(jié)用于表示字符的屬性。
如果要在第三行顯示某一字符的話(huà),就要跳過(guò)顯存的第0和1字節(jié)(它們是用于顯示第1列的),
第2和3字節(jié)(它們是用于顯示第2列的),然后把需要顯示字符的ASCⅡ碼值入第4字節(jié),
把字符的屬性寫(xiě)入第5字節(jié)。
把程序?qū)懼羻?dòng)扇區(qū)
下面寫(xiě)一個(gè)C程序,把我的操作系統(tǒng)寫(xiě)入軟盤(pán)第一扇區(qū)。程序內(nèi)容如下:
#include/*unistd.h需要這個(gè)文件*/
#include/*包含有read和write函數(shù)*/
#include
intmain()
{
charboot_buf[512];
intfloppy_desc,file_desc;
file_desc=open("./boot",O_RDONLY);
read(file_desc,boot_buf,510);
close(file_desc);
boot_buf[510]=0x55;
boot_buf[511]=0xaa;
floppy_desc=open("/dev/fd0",O_RDWR);
lseek(floppy_desc,0,SEEK_CUR);
write(floppy_desc,boot_buf,512);
close(floppy_desc);
}
首先,以只讀模式打開(kāi)boot文件,然后在打開(kāi)文件時(shí)把文件描述符復(fù)制到file_desc變量中。
從文件中讀取510個(gè)字符,或者讀取直到文件結(jié)束。在本例中由于文件很小,所以是讀取至文件結(jié)束
。然后關(guān)閉文件。
最后4行代碼打開(kāi)軟盤(pán)驅(qū)動(dòng)設(shè)備(一般來(lái)說(shuō)是/dev/fd0)。使用lseek找到文件開(kāi)始處,
然后從緩沖中向軟盤(pán)寫(xiě)512個(gè)字節(jié)。
在read、write、open和lseek的幫助頁(yè)中,可以看到與函數(shù)所有有關(guān)的參數(shù)及其使用方法。
程序中有兩行比較難懂:
boot_buf[510]=0x55;
boot_buf[511]=0xaa;
該信息是用于BIOS的,如果它識(shí)別出該設(shè)備是一個(gè)可啟動(dòng)的設(shè)備,那么在第510和511的位置,
該值就應(yīng)該是0x55和0xaa。程序會(huì)把文件boot讀至名為boot_buf的緩沖中。
它要求改變第510和第511字節(jié),然后把boot_buf寫(xiě)至軟盤(pán)之上。如果執(zhí)行代碼,
軟盤(pán)上的前512字節(jié)就包含了啟動(dòng)代碼。最后,把文件存為write.c。
編譯運(yùn)行
使用下面的命令把文件變?yōu)榭蓤?zhí)行文件:
as86boot.s-oboot.o
ld86-dboot.o-oboot
ccwrite.c-owrite
首先將boot.s文件編譯成目標(biāo)文件boot.o,然后將該文件連接成最終的boot文件。
最后C程序編譯成可執(zhí)行的write文件。
插入一個(gè)空白軟盤(pán),運(yùn)行以下程序:
./write
重新啟動(dòng)電腦,進(jìn)行BIOS的界面設(shè)置,并且把軟盤(pán)設(shè)為第一個(gè)啟動(dòng)的設(shè)備。然后插入軟盤(pán),
電腦從軟盤(pán)上啟動(dòng)。
啟動(dòng)完成后,在屏幕上可以看到一個(gè)字母A(藍(lán)底白字),啟動(dòng)速度很快,幾乎是在瞬間完成。
這就意味著系統(tǒng)已經(jīng)從我們制作的軟盤(pán)上啟動(dòng)了,并且執(zhí)行了剛才寫(xiě)入啟動(dòng)扇區(qū)的程序。
現(xiàn)在,它正處在一個(gè)無(wú)限循環(huán)的狀態(tài)。所以,如果想進(jìn)入Linux,必需拿掉軟盤(pán),并且重啟機(jī)器。
至此,這個(gè)操作系統(tǒng)就算完成了,雖然它沒(méi)有實(shí)現(xiàn)什么功能,但是它已經(jīng)可以啟動(dòng)機(jī)器了。
下一期我將在這個(gè)啟動(dòng)扇區(qū)程序里加入一些代碼,使它可以做一些比較復(fù)雜的事情
(比如使用BIOS中斷、保護(hù)模式切換等等)。
自己動(dòng)手寫(xiě)操作系統(tǒng)(二)
作者:伊梅
上一期,我講述了如何在軟盤(pán)的啟動(dòng)扇區(qū)寫(xiě)一些代碼,然后再?gòu)能洷P(pán)啟動(dòng)的過(guò)程。
制作好一個(gè)啟動(dòng)扇區(qū),在切換到保護(hù)模式之前,我們還應(yīng)該知道如何使用BIOS中斷。
BIOS中斷是一些由BIOS提供的、為了使操作系統(tǒng)的創(chuàng)建更容易的低級(jí)程序。在本文中,
我們將學(xué)習(xí)處理BIOS的中斷。
為什么要用BIOS
BIOS會(huì)把啟動(dòng)扇區(qū)拷貝至RAM中,并且執(zhí)行這些代碼。除此之外,BIOS還要做很多其它的事情。
當(dāng)一個(gè)操作系統(tǒng)剛開(kāi)始啟動(dòng)時(shí),系統(tǒng)中并沒(méi)有顯卡驅(qū)動(dòng)、軟盤(pán)驅(qū)動(dòng)等任何驅(qū)動(dòng)程序。
因此,啟動(dòng)扇區(qū)中不可能包含任何一個(gè)驅(qū)動(dòng)程序,我們要采取其它的途徑。
這個(gè)時(shí)候,BIOS就可以幫助我們了。BIOS中包含有各種可以使用的程序,
包括檢測(cè)安裝的設(shè)備、控制打印機(jī)、計(jì)算內(nèi)存大小等用于各種目的的程序。
這些程序就是所說(shuō)的BIOS中斷。
--------------------------------------------------------------------------------
3如何編寫(xiě)自己的操作系統(tǒng)
如何調(diào)用BIOS中斷
在一般的程序設(shè)計(jì)語(yǔ)言中,函數(shù)的調(diào)用是一件非常容易的事情。比如在C語(yǔ)言中,
如果有一個(gè)名為display的程序,它帶有兩個(gè)參數(shù),其中參數(shù)noofchar表示顯示的字符數(shù),
參數(shù)attr表示顯示字符的屬性。那么要調(diào)用它,只需給出程序的名稱(chēng)即可。對(duì)于中斷的調(diào)用
,我們使用的是匯編語(yǔ)言中的int指令。
比如,在C語(yǔ)言中要顯示一些東西時(shí),使用的指令如下所示:
display(nofchar,attr);
而使用BIOS時(shí),要實(shí)現(xiàn)相同功能使用的指令如下:
int0x10
如何傳遞參數(shù)
在調(diào)用BIOS中斷之前,我們需要先往寄存器中送一些特定的值。假設(shè)要使用BIOS的中斷13h,
該中斷的功能是把數(shù)據(jù)從軟盤(pán)傳送至內(nèi)存之中。在調(diào)用該中斷之前,要先指定拷貝數(shù)據(jù)的段地址
,指定驅(qū)動(dòng)器號(hào)、磁道號(hào)、扇區(qū)號(hào),以及要傳送的扇區(qū)數(shù)等等。然后,就要往相應(yīng)的寄存器送入
相應(yīng)的值。在進(jìn)行下面的步驟前,讀者有必要對(duì)這一點(diǎn)有比較明確地認(rèn)識(shí)。
此外,一個(gè)比較重要的事實(shí)是同一個(gè)中斷往往可以實(shí)現(xiàn)各種不同的功能。中斷所實(shí)現(xiàn)的確切功
能取決于所選擇的功能號(hào),功能號(hào)一般都存在ah寄存器之中。比如中斷13h可以用于讀磁盤(pán)、
寫(xiě)磁盤(pán)等功能,如果把3送入ah寄存器中,那么中斷選擇的功能就是寫(xiě)磁盤(pán);如果把2送入ah寄存
器中,選擇的功能則是讀磁盤(pán)等。
我們要做的事情
這次我們的源代碼由兩個(gè)匯編語(yǔ)言程序和一個(gè)C程序組成。第一個(gè)匯編文件是引導(dǎo)扇區(qū)的代碼。
在引導(dǎo)扇區(qū)中,我們寫(xiě)的代碼是要把軟盤(pán)中第二扇區(qū)拷貝至內(nèi)存段的0x500處(地址是0x5000,
即偏移地址為0)。這時(shí)我們需要使用BIOS的中斷13h。這時(shí)啟動(dòng)扇區(qū)的代碼就會(huì)把控制權(quán)轉(zhuǎn)移至0x500處。
在第二個(gè)匯編文件中,代碼會(huì)使用BIOS中斷10h在屏幕上顯示一個(gè)信息。C程序?qū)崿F(xiàn)的功能則是把可
執(zhí)行的文件1拷貝至啟動(dòng)扇區(qū),把可執(zhí)行的文件2拷貝至軟盤(pán)的第二扇區(qū)。
啟動(dòng)扇區(qū)代碼
使用中斷13h,啟動(dòng)扇區(qū)把軟盤(pán)第二扇區(qū)里的內(nèi)容加載至內(nèi)存的0x5000處(段地址為0x500)。
下面的代碼是用于實(shí)現(xiàn)這一目的的代碼,將其保存至文件sbect.s中。
LOC1=0x500
entrystart
start:
movax,#LOC1
moves,ax
movbx,#0
movdl,#0
movdh,#0
movch,#0
movcl,#2
moval,#1
movah,#2
int0x13
jmpi0,#LOC1
上面代碼第一行類(lèi)似于一個(gè)宏。接下去的兩行則是把值0x500加載至es寄存器中,
這是軟盤(pán)上第二扇區(qū)代碼將拷貝到的地方(第一扇區(qū)是啟動(dòng)扇區(qū))。這時(shí),把段內(nèi)的偏移設(shè)為0。
接下來(lái)把驅(qū)動(dòng)器號(hào)送入dl寄存器中,其中磁頭號(hào)送入dl寄存器中,磁道號(hào)送入ch寄存器中,
扇區(qū)號(hào)送入cl寄存器中,扇區(qū)數(shù)送入al寄存器之中。我們想要實(shí)現(xiàn)的功能是把扇區(qū)2、磁道號(hào)為0、驅(qū)動(dòng)器號(hào)為0的內(nèi)容送至段地址0x500處。所有這些參數(shù)都和1.44MB的軟盤(pán)相對(duì)應(yīng)。
把2送入ah寄存器中,是選擇了由中斷13h提供的相應(yīng)功能,即實(shí)現(xiàn)從軟驅(qū)轉(zhuǎn)移數(shù)據(jù)的功能。
最后調(diào)用中斷13h,并且轉(zhuǎn)至偏移為0的段地址0x500處。
第二個(gè)扇區(qū)的代碼
第二個(gè)扇區(qū)中的代碼如下所示(把這些代碼保存至文件sbect2.s之中):
entrystart
start:
movah,#0x03
xorbh,bh
int0x10
movcx,#26
movbx,#0x0007
movbp,#mymsg
movax,#0x1301
int0x10
loop1:jmploop1
mymsg:
.byte13,10
.ascii"OperatingSystemisLoading......"
上面代碼將被加載至段地址為0x500處,并且被執(zhí)行。在這段代碼中,使用了中斷10h來(lái)獲取目前的光標(biāo)
位置,然后顯示信息。
從第3行到第5行用于得到目前光標(biāo)的位置,在此中斷10h選用的是功能3。然后,清除了bh寄存器的內(nèi)容,
并把字符串送至ch寄存器中。在bx中,我們送入了頁(yè)碼及顯示的屬性。此處,我們想要在黑背景上顯示
白色的字符。然后,把要顯示字符的地址送到bp之中,信息由兩個(gè)字節(jié)組成,其值分別為13的10,
它們分別對(duì)應(yīng)回車(chē)和LF(換行)的ASCⅡ值。接下來(lái)是一個(gè)由29個(gè)字符組成的串;在下面實(shí)現(xiàn)的功能是
輸出字符串然后移動(dòng)光標(biāo);最后是調(diào)用中斷,然后進(jìn)入循環(huán)。
--------------------------------------------------------------------------------
4如何編寫(xiě)自己的操作系統(tǒng)
C程序代碼
C程序的源代碼如下所示,將其存儲(chǔ)為write.c文件。
#include/*unistd.hneedsthis*/
#include/*containsread/write*/
#include
intmain()
{
charboot_buf[512];
intfloppy_desc,file_desc;
file_desc=open("./bsect",O_RDONLY);
read(file_desc,boot_buf,510);
close(file_desc);
boot_buf[510]=0x55;
boot_buf[511]=0xaa;
floppy_desc=open("/dev/fd0",O_RDWR);
lseek(floppy_desc,0,SEEK_SET);
write(floppy_desc,boot_buf,512);
file_desc=open("./sect2",O_RDONLY);
read(file_desc,boot_buf,512);
close(file_desc);
lseek(floppy_desc,512,SEEK_SET);
write(floppy_desc,boot_buf,512);
close(floppy_desc);
}
在上一期中,我曾經(jīng)介紹過(guò)如何操作能啟動(dòng)的軟盤(pán)?,F(xiàn)在這一個(gè)過(guò)程稍微有點(diǎn)不同,
首先把由bsect.s編譯出來(lái)的可執(zhí)行文件bsect拷貝至軟盤(pán)的啟動(dòng)扇區(qū)。然后再把由sect2.s產(chǎn)生的可執(zhí)行
文件sect2拷貝至軟盤(pán)的第二個(gè)扇區(qū)。
把上述文件置于同一目錄之下,然后分別對(duì)其進(jìn)行編譯,方法如下所示:
as86bsect.s-obsect.o
ld86-dbsect.o-obsect
對(duì)sect2.s文件重復(fù)以上的操作,得出可執(zhí)行文件sect2。編譯write.c,插入軟盤(pán)后執(zhí)行write文件,
命令如下所示:
ccwrite.c-owrite
./write
下一步我們要做的事情
從軟盤(pán)啟動(dòng)以后,可以看到顯示出來(lái)的字符串。這是使用了BIOS中斷來(lái)完成的。
下一期要做的事情是在這個(gè)操作系統(tǒng)中實(shí)現(xiàn)實(shí)模式向保護(hù)模式的轉(zhuǎn)換。
自己動(dòng)手寫(xiě)操作系統(tǒng)(三)
在上兩期中(自己動(dòng)手寫(xiě)操作系統(tǒng)1,2),我向大家講述了如何使用Linux提供的開(kāi)發(fā)工具在軟盤(pán)的啟動(dòng)
扇區(qū)寫(xiě)一些代碼,以及如何調(diào)用BIOS的問(wèn)題?,F(xiàn)在,這個(gè)操作系統(tǒng)已經(jīng)越來(lái)越接近當(dāng)年LinusTorvalds的
那個(gè)具有"歷史意義"的Linux內(nèi)核了。因此,要馬上把這個(gè)系統(tǒng)切換到保護(hù)模式之下。
什么是保護(hù)模式
自從1969年推出第一個(gè)微處理器以來(lái),Intel處理器就在不斷地更新?lián)Q代,從8086、8088、80286,
到80386、80486、奔騰、奔騰Ⅱ、奔騰4等,其體系結(jié)構(gòu)也在不斷變化。80386以后,
提供了一些新的功能,彌補(bǔ)了8086的一些缺陷。這其中包括內(nèi)存保護(hù)、多任務(wù)及使用640KB以上的內(nèi)存等,
并仍然保持和8086家族的兼容性。也就是說(shuō)80386仍然具備了8086和80286的所有功能,
但是在功能上有了很大的增強(qiáng)。早期的處理器是工作在實(shí)模式之下的,80286以后引入了保護(hù)模式,
而在80386以后保護(hù)模式又進(jìn)行了很大的改進(jìn)。在80386中,保護(hù)模式為程序員提供了更好的保護(hù),
提供了更多的內(nèi)存。事實(shí)上,保護(hù)模式的目的不是為了保護(hù)程序,而是要保護(hù)程序以外的所有程序
(包括操作系統(tǒng))。
簡(jiǎn)言之,保護(hù)模式是處理器的一種最自然的模式。在這種模式下,處理器的所有指令及體系結(jié)構(gòu)的所有
特色都是可用的,并且能夠達(dá)到最高的性能。
保護(hù)模式和實(shí)模式
從表面上看,保護(hù)模式和實(shí)模式并沒(méi)有太大的區(qū)別,二者都使用了內(nèi)存段、中斷和設(shè)備驅(qū)動(dòng)來(lái)處理硬件
,但二者有很多不同之處。我們知道,在實(shí)模式中內(nèi)存被劃分成段,每個(gè)段的大小為64KB,
而這樣的段地址可以用16位來(lái)表示。內(nèi)存段的處理是通過(guò)和段寄存器相關(guān)聯(lián)的內(nèi)部機(jī)制來(lái)處理的,
這些段寄存器(CS、DS、SS和ES)的內(nèi)容形成了物理地址的一部分。具體來(lái)說(shuō),最終的物理地址是由
16位的段地址和16位的段內(nèi)偏移地址組成的。用公式表示為:
物理地址=左移4位的段地址+偏移地址。
在保護(hù)模式下,段是通過(guò)一系列被稱(chēng)之為"描述符表"的表所定義的。段寄存器存儲(chǔ)的是指向這
些表的指針。用于定義內(nèi)存段的表有兩種:全局描述符表(GDT)和局部描述符表(LDT)。GDT是一個(gè)段描述
符數(shù)組,其中包含所有應(yīng)用程序都可以使用的基本描述符。在實(shí)模式中,段長(zhǎng)是固定的(為64KB),
而在保護(hù)模式中,段長(zhǎng)是可變的,其最大可達(dá)4GB。LDT也是段描述符的一個(gè)數(shù)組。與GDT不同,
LDT是一個(gè)段,其中存放的是局部的、不需要全局共享的段描述符。每一個(gè)操作系統(tǒng)都必須定義一個(gè)GDT,
而每一個(gè)正在運(yùn)行的任務(wù)都會(huì)有一個(gè)相應(yīng)的LDT。每一個(gè)描述符的長(zhǎng)度是8個(gè)字節(jié),格式如圖3所示。
當(dāng)段寄存器被加載的時(shí)候,段基地址就會(huì)從相應(yīng)的表入口獲得。描述符的內(nèi)容會(huì)被存儲(chǔ)在一個(gè)程序員不可
見(jiàn)的影像寄存器(shadowregister)之中,以便下一次同一個(gè)段可以使用該信息而不用每次都到表中提取
。物理地址由16位或者32位的偏移加上影像寄存器中的基址組成。實(shí)模式和保護(hù)模式的不同可以從圖1
和圖2中很清楚地看出來(lái)。
--------------------------------------------------------------------------------
5如何編寫(xiě)自己的操作系統(tǒng)
圖1實(shí)模式的尋址
圖2保護(hù)模式下的尋址
圖3段描述俯的格式
此外,還有一個(gè)中斷描述符表(IDT)。這些中斷描述符會(huì)告訴處理器到那里可以找到中斷處理程序。
和實(shí)模式一樣,每一個(gè)中斷都有一個(gè)入口,但是這些入口的格式卻完全不同。
因?yàn)樵谇袚Q到保護(hù)模式的過(guò)程中沒(méi)有使用到IDT,所以在此就不多做介紹了。
進(jìn)入保護(hù)模式
80386有4個(gè)32位控制寄存器,名字分別為CR0、CR1、CR2和CR3。CR1是保留在未來(lái)處理器中使用的,
在80386中沒(méi)有定義。CR0包含系統(tǒng)的控制標(biāo)志,用于控制處理器的操作模式和狀態(tài)。CR2和CR3是用于
控制分頁(yè)機(jī)制的。在此,我們關(guān)注的是CR0寄存器的PE位控制,它負(fù)責(zé)實(shí)模式和保護(hù)模式之間的切換。
當(dāng)PE=1時(shí),說(shuō)明處理器運(yùn)行于保護(hù)模式之下,其采用的段機(jī)制和前面所述的相應(yīng)內(nèi)容對(duì)應(yīng)。如果PE=0,
那么處理器就工作在實(shí)模式之下。
切換到保護(hù)模式,實(shí)際就是把PE位置為1。為了把系統(tǒng)切換到保護(hù)模式,還要做一些其它的事情。
程序必須要對(duì)系統(tǒng)的段寄存器和控制寄存器進(jìn)行初始化。把PE位置1后,還要執(zhí)行跳轉(zhuǎn)指令。
過(guò)程簡(jiǎn)述如下:
1.創(chuàng)建GDT表;
2.通過(guò)置PE位為1進(jìn)入保護(hù)模式;
3.執(zhí)行跳轉(zhuǎn)以清除在實(shí)模式下讀取的任何指令。
下面使用代碼來(lái)實(shí)現(xiàn)這個(gè)切換過(guò)程。
需要的東西
◆一張空白軟盤(pán)
◆NASM編譯器
下面是整個(gè)程序的源代碼:
org0x07c00;起始地址是0000:7c00
jmpshortbegin_boot;跳過(guò)其它的數(shù)據(jù),跳轉(zhuǎn)到引導(dǎo)程序的開(kāi)始處
bootmesgdb"OurOSbootsectorloading......"
pm_mesgdb"Switchingtoprotectedmode...."
dw512;每一扇區(qū)的字節(jié)數(shù)
db1;每一簇的扇區(qū)數(shù)
dw1;保留的扇區(qū)號(hào)
db2
dw0x00e0
dw0x0b40
db0x0f0
dw9
dw18
dw2;讀寫(xiě)扇區(qū)號(hào)
dw0;隱藏扇區(qū)號(hào)
print_mesg:
movah,0x13;使用中斷10h的功能13,在屏幕上寫(xiě)一個(gè)字符串
moval,0x00;決定調(diào)用函數(shù)后光標(biāo)所處的位置
movbx,0x0007;設(shè)置顯示屬性
movcx,0x20;在此字符串長(zhǎng)度為32
movdx,0x0000;光標(biāo)的起始行和列
int0x10;調(diào)用BIOS的中斷10h
ret;返回調(diào)用程序
get_key:
movah,0x00
int0x16;Get_key使用中斷16h的功能0,讀取下一個(gè)字符
ret
clrscr:
movax,0x0600;使用中斷10h的功能6,實(shí)現(xiàn)卷屏,如果al=0則清屏
movcx,0x0000;清屏
movdx,0x174f;卷屏至23,79
movbh,0;使用顏色0來(lái)填充
int0x10;調(diào)用10h中斷
ret
begin_boot:
callclrscr;先清屏
movbp,bootmesg;提供串地址
callprint_mesg;輸出信息
callget_key;等待用戶(hù)按下任一鍵
bits16
callclrscr;清屏
movax,0xb800;使gs指向顯示內(nèi)存
movgs,ax;在實(shí)模式下顯示一個(gè)棕色的A
movword[gs:0],0x641;顯示
callget_key;調(diào)用Get_key等待用戶(hù)按下任一鍵
movbp,pm_mesg;設(shè)置串指針
callprint_mesg;調(diào)用print_mesg子程序
callget_key;等待按鍵
callclrscr;清屏
cli;關(guān)中斷
lgdt[gdtr];加載GDT
moveax,cr0
oral,0x01;設(shè)置保護(hù)模式位
movcr0,eax;將更改后的字送至控制寄存器中
jmpcodesel:go_pm
bits32
go_pm:
movax,datasel
movds,ax;初始化ds和es,使其指向數(shù)據(jù)段
moves,ax
movax,videosel;初始化gs,使其指向顯示內(nèi)存
movgs,ax
movword[gs:0],0x741;在保護(hù)模式下顯示一個(gè)白色的字符A
spin:jmpspin;循環(huán)
bits16
gdtr:
dwgdt_end-gdt-1;gdt的長(zhǎng)度
ddgdt;gdt的物理地址
gdt
nullselequ$-gdt;$指向當(dāng)前位置,所以nullsel=0h
gdt0;空描述符
dd0
dd0;所有的段描述符都是64位的
codeselequ$-gdt;這是8h也就是gdt的第二個(gè)描述符
--------------------------------------------------------------------------------
6如何編寫(xiě)自己的操作系統(tǒng)
code_gdt
dw0x0ffff;段描述符的界限是4Gb
dw0x0000
db0x00
db0x09a
db0x0cf
db0x00
dataselequ$-gdt
data_gdt
dw0x0ffff
dw0x0000
db0x00
db0x092
db0x0cf
db0x00
videoselequ$-gdt
dw3999
dw0x8000;基址是0xb8000
db0x0b
db0x92
db0x00
db0x00
gdt_end
times510-($-$$)db0
dw0x0aa55
把上面的代碼存在一個(gè)名為abc.asm的文件之中,使用命令nasmabc.asm,將得出一個(gè)名為abc的文件。
然后插入軟盤(pán),輸入命令:ddif=abcof=/dev/fd0。該命令將把文件abc寫(xiě)入到軟盤(pán)的第一扇區(qū)之中。
然后重新啟動(dòng)系統(tǒng),就會(huì)看到如下的信息:
*Ourosbooting................
*A(棕色)
*Switchingtoprotectedmode....
*A(白色)
對(duì)代碼的解釋
上面給出了所有的代碼,下面我對(duì)上述代碼做一些解釋。
◆使用的函數(shù)
下面是代碼中一些函數(shù)的說(shuō)明:
print_mesg該子程序使用了BIOS中斷10h的功能13h,即向屏幕寫(xiě)一字符串。屬性控制是通過(guò)向一些寄
存器中送入不同的值來(lái)實(shí)現(xiàn)的。中斷10h是用于各種字符串操作,我們把子功能號(hào)13h送到ah中,
用于指明
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 感人的結(jié)婚致辭13篇
- 愚人節(jié)的日記(集錦11篇)
- 護(hù)士臨床能力考核總結(jié)
- 智研咨詢(xún)發(fā)布:2024年中國(guó)廢舊動(dòng)力電池梯次利用行業(yè)競(jìng)爭(zhēng)格局及發(fā)展前景研究報(bào)告
- 2024年中國(guó)三網(wǎng)融合行業(yè)市場(chǎng)集中度、市場(chǎng)規(guī)模及未來(lái)前景分析報(bào)告
- 無(wú)人機(jī)在火災(zāi)防控中的應(yīng)用培訓(xùn)
- 音樂(lè)學(xué)校前臺(tái)工作總結(jié)
- 二零二五年個(gè)人果園果樹(shù)種植與農(nóng)產(chǎn)品加工合作協(xié)議4篇
- 現(xiàn)代農(nóng)業(yè)產(chǎn)業(yè)園建設(shè)方案
- 能源供應(yīng)服務(wù)招標(biāo)合同三篇
- 第1課 隋朝統(tǒng)一與滅亡 課件(26張)2024-2025學(xué)年部編版七年級(jí)歷史下冊(cè)
- 2025-2030年中國(guó)糖醇市場(chǎng)運(yùn)行狀況及投資前景趨勢(shì)分析報(bào)告
- 【歷史】唐朝建立與“貞觀(guān)之治”課件-2024-2025學(xué)年統(tǒng)編版七年級(jí)歷史下冊(cè)
- 冬日暖陽(yáng)健康守護(hù)
- 產(chǎn)業(yè)園區(qū)招商合作協(xié)議書(shū)
- 2024年廣東省公務(wù)員錄用考試《行測(cè)》真題及答案解析
- 水處理藥劑采購(gòu)項(xiàng)目技術(shù)方案(技術(shù)方案)
- 2024級(jí)高一上期期中測(cè)試數(shù)學(xué)試題含答案
- 盾構(gòu)標(biāo)準(zhǔn)化施工手冊(cè)
- 天然氣脫硫完整版本
- 山東省2024-2025學(xué)年高三上學(xué)期新高考聯(lián)合質(zhì)量測(cè)評(píng)10月聯(lián)考英語(yǔ)試題
評(píng)論
0/150
提交評(píng)論