/**********第0天 著手開發(fā)之前**********/
所謂開發(fā)操作系統(tǒng),就是想辦法制作一張“含有操作系統(tǒng)的,能夠自啟動的磁盤”。
主要的學(xué)習(xí)內(nèi)容:
第一周:
1. 寫一個"一通電就能運行的程序“
2. 寫一個從磁盤讀取操作系統(tǒng)的程序
3. c語言來開發(fā)顯示畫面的程序
4. 實現(xiàn)”移動鼠標(biāo)“,對cpu進(jìn)行細(xì)致的設(shè)定,掌握中斷處理程序的寫法
第二周:
5. 算法的學(xué)習(xí)
第三周:
6. 支持多任務(wù)
7. 開發(fā)命令行窗口
8. 開發(fā)應(yīng)用程序
第四周:
9. 集中精力在編程上
10. 操作系統(tǒng)支持文字顯示
第五周:
11. 潤色加工
/**********第1天 從計算機結(jié)構(gòu)到匯編程序入門**********/
利用二進(jìn)制編輯工具編輯二進(jìn)制文件,二進(jìn)制文件包含cpu執(zhí)行的機器指令,文件中是裸的機器指令。
功能是用來啟動計算機,并在屏幕上顯示hello world。
通過匯編語言編寫上述程序,編譯后生成以上功能的二進(jìn)制文件,即啟動區(qū)的程序。
啟動區(qū)大小為512字節(jié),并以55 AA結(jié)束,以標(biāo)志是啟動區(qū)。
/**********第2天 匯編語言學(xué)習(xí)和Makefile入門**********/
在PC機加電ROM BIOS自檢后,引導(dǎo)扇區(qū)由BIOS加載到內(nèi)存0x7C00處.
因此引導(dǎo)扇區(qū)的代碼要用org偽指令:
ORG 0x7C00 偽指令說明其后面程序的目標(biāo)代碼在內(nèi)存中存放的起始地址是0x7C00
ORG偽指令:
ORG是Origin的縮寫:起始地址,源。
在匯編語言源程序的開始通常都用一條ORG偽指令來實現(xiàn)規(guī)定程序的起始地址。
如果不用ORG規(guī)定則匯編得到的目標(biāo)程序?qū)?000H開始。例如:
ORG 2000H
START:MOV AX,#00H
匯編語言源程序中若沒有ORG偽指令,則程序執(zhí)行時,指令代碼被放到自由內(nèi)存空間的CS:0處;
若有ORG偽指令,編譯器則把其后的指令代碼放到ORG偽指令指定的偏移地址。
兩個ORG偽指令之間,除了指令代碼,若有自由空間,則用0填充。
預(yù)處理-->編譯-->匯編-->鏈接,這是高級語言的編譯全過程。對于純匯編,就只有匯編和鏈接兩個步驟。
org指令是鏈接時使用的,不是匯編那一步使用的。即不是cpu的一條指令,而是給編譯器看的偽指令。
BIOS中斷服務(wù):
如INT 0x10用來顯示文字。
BIOS的功能非常多,可以看成是為操作系統(tǒng)開發(fā)人員準(zhǔn)備的各種函數(shù)集合。
/**********第3天 進(jìn)入32位模式并導(dǎo)入c語言**********/
為啟動區(qū)添加讀取軟盤數(shù)據(jù)的功能代碼,利用INT 0x13中斷來讀取軟盤10個柱面的數(shù)據(jù),并放到內(nèi)存中。
軟盤的數(shù)據(jù)將被加載到內(nèi)存中0x8200到0x83ff的地方。
有以上功能后,編寫匯編代碼文件haribote.nas(操作系統(tǒng)的功能),通過nask編譯成haribote.sys,
這個文件保存到磁盤映象haribote.img中,最后保存到軟盤中。
用二進(jìn)制編輯器查看haribote.img,可以發(fā)現(xiàn),一般向一個空軟盤保存文件時:
1. haribote.sys的文件名會寫在0x002600以后的地方
2. haribote.sys的內(nèi)容會寫在0x004200以后的地方
因此,我們將操作系統(tǒng)本身的內(nèi)容寫到名為haribote.sys文件中,再把它保存到磁盤映象里,然后我們從啟動區(qū)執(zhí)行這個haribote.sys就行了。
現(xiàn)在的程序是從啟動區(qū)開始,把磁盤上的內(nèi)容裝載到內(nèi)存0x8000號地址(第二扇區(qū)裝載在0x8200,除去第一個扇區(qū)的大小0x200,即0x8000,實際上,第一扇區(qū)啟動區(qū)裝載在0x7c00地址),
所以磁盤0x4200處的內(nèi)容就應(yīng)該位于內(nèi)存0x8000+0x4200=0xc200號地址。
這樣的話,往haribote.nas里加上ORG 0xc200。
切換到32位模式:
筆者準(zhǔn)備的c編譯器只能生成32位模式的機器語言,16位模式和32位模式中,機器語言的命令代碼不一樣。
32位模式的兩個優(yōu)點:1.內(nèi)存使用容量大于1MB 2.CPU的自我保護(hù)功能。
如果用32位模式就不能調(diào)用BIOS功能,因為BIOS是用16位機器語言寫的。
haribote.sys分拆成兩個文件:
1. asmhead.nas 切換到32位模式的準(zhǔn)備工作,后面詳解
- 設(shè)置顯示模式
- 用BIOS取得鍵盤上各種LED指示燈的狀態(tài)
- BOOT_INFO相關(guān)的內(nèi)容保存(畫面模式、分辨率、VRAM緩沖區(qū)地址)
- 進(jìn)入32位模式的設(shè)置(GDT/IDT初始化)
2. bootpack.c 操作系統(tǒng)的功能
/**********第4天 C語言與畫面顯示的練習(xí)**********/
往VRAM(video RAM)內(nèi)存中寫入像素數(shù)據(jù),可以顯示不同的畫面。
在asmhead.asm中,通過INT 0x13設(shè)置顯卡的顯示模式VGA 320x240x8位彩色。
此模式的VRAM的內(nèi)存地址空間為0xa0000~0xaffff的64KB。
為了顯示不同的顏色,需要設(shè)定色號,如何設(shè)定色號?
設(shè)定色號的步驟:
1. 記錄中斷許可標(biāo)志的值 eflags
2. 禁止中斷 io_cli
3. io_out8根據(jù)設(shè)備號PORT往設(shè)備發(fā)送命令或數(shù)據(jù),設(shè)置對應(yīng)的色號
3. 恢復(fù)中斷許可標(biāo)志
有了不同的顏色后,使用不同的色號往vram中寫不同顏色像素繪制矩形。
/**********第5天 結(jié)構(gòu)體、文字顯示與GDT/IDT初始化**********/
用結(jié)構(gòu)體來封裝BOOT_INFO相關(guān)的內(nèi)容(畫面模式、分辨率、VRAM緩沖區(qū)地址)
如何顯示字符?
1. 定義字體數(shù)據(jù)(像素點矩陣的方式)
2. 解析像素點矩陣
3. 繪制各個像素點
如何在屏幕上顯示變量值?
使用sprintf。
由于printf不管如何精心設(shè)計,都不可避免地要使用操作系統(tǒng)的功能。
而sprintf不同,它只對內(nèi)存進(jìn)行操作,所以可以應(yīng)用與所有操作系統(tǒng)。
如何顯示鼠標(biāo)指針?
準(zhǔn)備鼠標(biāo)指針的數(shù)據(jù)(像素點矩陣),往vram里繪制。
如果鼠標(biāo)需要移動的話,由于涉及到硬件的控制,需要利用中斷,所以前提是要初始化GDT、IDT。
GDT和IDT都是與CPU的設(shè)定有關(guān),為了讓操作系統(tǒng)能夠使用32位模式,需要對CPU做各種設(shè)定。
分段:
將4GB的內(nèi)存分成很多塊,每一塊一個段,每一塊的起始地址都看做0來處理。
分段在16位和32位中的區(qū)別:
16位中的段寄存器,在計算地址時,要將段地址乘以16;而在32位中,段寄存器表示的是段選擇符。
32位中的分段,為了表示一個段,需要有以下信息
為了表示一個段,需要有以下信息:
- 段的大小是多少
- 段的起始地址在哪里
- 段的管理屬性(禁止寫入,禁止執(zhí)行,系統(tǒng)專用等)
CPU用8個字節(jié)的數(shù)據(jù)來表示這些信息,而段寄存器只有16位,如何處理?
解決方法:
段寄存器作為段的索引,段的信息保存在內(nèi)存中,由于CPU設(shè)計上的原因,段寄存器的低3位不能使用。
因此能夠使用的段號只有13位,能夠處理的段號就只有0~8191,即可以定義8192個段。
內(nèi)存中需要8192x8 = 64KB的空間來保存每個段的信息,而這64KB的數(shù)據(jù)就稱為GDT(Global (segment) descriptor table)。
而GDTR中會保存GDT的內(nèi)存的起始地址和有效設(shè)定個數(shù)。
GDTR是個48位的寄存器,低16位是段上限,即GDT總共大??;剩下32位代表GDT的開始地址。
段信息的8個字節(jié)中:其中32位表示表示該段的基址,分為low(2個字節(jié)),mid(1個字節(jié)),high(1個字節(jié)),分為3段的目的是為了兼容80286的程序。
- 其中32位表示表示該段的基址,分為low(2個字節(jié)),mid(1個字節(jié)),high(1個字節(jié)),分為3段的目的是為了兼容80286的程序。
- 其中段上限只能使用20位,這樣只能使用1MB內(nèi)存,但是通過段屬性的標(biāo)志位Gbit設(shè)置成1的時候,limit的單位不解釋成byte,而解釋成page(4KB).
這樣,就能使用4GB的內(nèi)存空間。
- 剩下的12位段屬性稱為段的訪問權(quán)屬性
IDT記錄了0~255的中斷號碼與調(diào)用函數(shù)的對應(yīng)關(guān)系。
/**********第6天 分割編譯與中斷處理**********/
鼠標(biāo)指針的移動需要使用到中斷,而要使用中斷必須將GDT和IDT正確無誤的初始化。
使用中斷前,需要初始化PIC。
從CPU角度來看,PIC是外部設(shè)備,CPU使用OUT指令進(jìn)行操作。
聯(lián)系客服