本系列將以一種新奇的閱讀心態(tài)閱讀和欣賞Linux 0.11的所有核心代碼,從啟動后的代碼執(zhí)行序列中了解操作系統(tǒng)的技術(shù)細(xì)節(jié)和設(shè)計思路。
你會跟著我,看著一個操作系統(tǒng)從無到有,最后一步一步實現(xiàn)它復(fù)雜而精致的設(shè)計看完這個系列,希望你能感嘆原來操作系統(tǒng)源代碼就是這個蠢東西
以下是已發(fā)表文章的列表想詳細(xì)了解這個系列,可以從開篇的話開始
開場白
前兩行代碼
給自己挪個位置。
做好最基本的準(zhǔn)備工作。
將硬盤的其他部分放入內(nèi)存。
這個系列的GitHub地址如下:
—正文開始—
上一次,上一次,我們說操作系統(tǒng)已經(jīng)完成了從硬盤到內(nèi)存的各種加載,從內(nèi)存到內(nèi)存的復(fù)制。
至此,bootsect.s的整個使命已經(jīng)完成,也是我們看完的第一個操作系統(tǒng)源文件然后跳轉(zhuǎn)到0x90200,這里的代碼在安裝程序的開始處
start:movax,# 0x9000thisisdoneinbootsectalready,butmovds,axmovah,# 0x03readcursorposxorbh,BH,saveitinknownplace,con_initfetchesmov,dx,itfrom0x90000。
還有一個int指令。
如果你仔細(xì)閱讀前面的文章,你就能猜到它要做什么還記得有一個int 0x13觸發(fā)了BIOS提供的磁盤讀取中斷嗎這個int 0x10也是如此,同樣觸發(fā)BIOS提供的顯示服務(wù)中斷處理程序,ah寄存器賦給0x03,表示顯示服務(wù)中具體的光標(biāo)位置讀取功能
具體來說,BIOS提供了哪些中斷服務(wù),如何調(diào)用并獲取返回值請自行尋找資料,這里只說結(jié)果
當(dāng)int 0x10中斷程序完成并返回時,dx寄存器中的值指示光標(biāo)的位置具體地說,高八位dh存儲行號,低八位dl存儲列號
這里說明一下:電腦開機(jī)自檢后會自動初始化為文本模式在這種模式下,屏幕可以顯示25行,每行80個字符,即80列
下一個mov,dx將在這個內(nèi)存地址存儲這個光標(biāo)位置注意,我們前面說過,這個內(nèi)存地址只是一個偏移地址,需要加上ds寄存器中存儲的段基址最終的內(nèi)存地址是0x90000,其中存儲了光標(biāo)位置,供以后初始化控制臺時使用
所以從這里可以看出,這和平時調(diào)用一個方法沒什么區(qū)別,只不過這里寄存器的用法相當(dāng)于參數(shù)和返回值,這里的0x10中斷號相當(dāng)于方法名。
這里應(yīng)該是之前說過的一句話操作系統(tǒng)內(nèi)核初期,到處都是BIOS調(diào)試器如果有現(xiàn)成的,就用吧
接下來幾行代碼的邏輯和剛才一樣調(diào)用BIOS中斷來獲取一些信息,然后將其存儲在內(nèi)存中的某個位置讓我們快速瀏覽一下
例如獲得存儲器信息Getmemorysemovah,# 0x88int 0x15mov ,ax獲取顯卡的顯示模式Getvideo—carddata:movah,#0x0fint0x10mov,bx,bh=displaypagemov,ax,Al=videomode,ah=windowwidth檢查顯示模式,獲取參數(shù),檢查forega/vgaandsomeconfigparametersmovah,# 0x12movbl,# 0x10int 0x10mov ,axmov ,bxmov ,CX得到第一塊硬盤的信息Gethd0datamovax,# 0x0000movds,axldssi, movax,# initsegmoves,axmovdi,# 0x0080movcx,# 0x10repmovsb獲取第二塊硬盤的信息
以上原理都一樣。
我們沒有必要去思考理解操作系統(tǒng)沒多大區(qū)別我們只需要知道存儲在內(nèi)存中的信息是什么,在哪里,然后我們就會使用它們
內(nèi)存長度名稱0x900002光標(biāo)位置0x90022
擴(kuò)展內(nèi)存號0x900042顯示頁面0x900061。
顯示模式0x900071字符列數(shù)0x900082未知0x9000A1
顯示內(nèi)存0x9000B1。
顯示狀態(tài)0x9000C2顯卡特性參數(shù)0x9000E1。
屏幕行0x9000F1屏幕列0x9008016
1硬盤參數(shù)表0x9009016硬盤2參數(shù)表0x901FC2
根號
由于之后很快就會使用C語言進(jìn)行編程,雖然匯編和C語言也可以以變量的形式傳遞數(shù)據(jù),但這需要編譯器在鏈接時做一些額外的工作,所以雙方約定一個內(nèi)存地址會更方便我把它放在這里,你可以從這里拿走,它就完成了這恐怕是最原始最直觀的變量傳遞方式了
存儲了這些信息之后,操作系統(tǒng)會做什么我們繼續(xù)往下看
cli不允許中斷,
只有一行cli,意思是關(guān)閉中斷。
后來因為要重寫原來寫在BIOS里的中斷向量表,也就是銷毀它,自己寫中斷向量表,這時候就不允許中斷了。
繼續(xù)看。
firstwemovethesystemtoit ' srightfulplacemovax,#0x0000cld'direction'=0,movsmovesforwarddo_move:moves,axdestinationsegmentaddax,#0x1000cmpax,#0x9000jzend_movemovds,axsourcesegmentsubdi,disubsi,simovcx,# 0x8000jmpdo _ move然后weloadthesegmentdescriptorsend _ move:...
你熟悉后面的代表movsw嗎最初,我們在將操作系統(tǒng)代碼從0x7c00移動到0x90000時使用了這條指令我們來回憶一下
與前面的原理一樣,也要進(jìn)行內(nèi)存復(fù)制操作最后的結(jié)果就是從內(nèi)存地址0x10000到0x90000的所有內(nèi)容都被復(fù)制到內(nèi)存的初始0位置,大概就是這樣的效果
由于之前的各種加載復(fù)制,內(nèi)存看起來很亂又到了一波取舍和排序的時候了現(xiàn)在我們重新安排一下內(nèi)存布局
棧頂?shù)刂啡匀皇?x9FF00,沒有改變。
0x90000向上開始的位置原來是bootsect和setup程序的代碼現(xiàn)在,為了記錄內(nèi)存,硬盤,顯卡等一些臨時存儲的數(shù)據(jù),bootsect的部分代碼已經(jīng)被操作系統(tǒng)部分覆蓋
內(nèi)存512K的前0到0x80000由系統(tǒng)模塊占用如前所述,這個系統(tǒng)模塊是鏈接除bootsect和setup之外的所有程序的結(jié)果,可以理解為操作系統(tǒng)的整體
所以現(xiàn)在的內(nèi)存布局是這樣的。
好了,記住上圖就行了這次又清楚了嗎
接下來要做一些技術(shù)工作,就是模式轉(zhuǎn)換,需要從現(xiàn)在的16位實模式轉(zhuǎn)換到下一個32位保護(hù)模式這是一個大工程!我認(rèn)為這也是操作系統(tǒng)源代碼之旅的第一個精彩之處
我們身后的世界越來越精彩欲知后事如何,且聽下回分解
。鄭重聲明:此文內(nèi)容為本網(wǎng)站轉(zhuǎn)載企業(yè)宣傳資訊,目的在于傳播更多信息,與本站立場無關(guān)。僅供讀者參考,并請自行核實相關(guān)內(nèi)容。