第0天
在銀行干了這么多年我終于決定要辭職了跟衅。為了辭職這個(gè)事情特地學(xué)習(xí)了銀行的客戶經(jīng)理離職管理辦法别惦。
這個(gè)管理辦法規(guī)定:辭職要至少提前一個(gè)月提交辭職報(bào)告潭枣,然后再走固定的辭職流程绞蹦。我覺得這一個(gè)月應(yīng)該會(huì)很輕松拳恋,我會(huì)做好自己的交接工作之余是不是應(yīng)該再找點(diǎn)其他事情呢氮发?
正在為提高業(yè)務(wù)生活質(zhì)量煩惱的時(shí)候突然發(fā)現(xiàn)書架上一本30天自制操作系統(tǒng)渴肉。這本書是在2013年買的,竟然從來沒有翻過爽冕。這都是上天注定的啊仇祭,三年前買了這本書就是為了這一個(gè)月。
那么我這三十天寫操作系統(tǒng)的生活開始了颈畸。
第1天
計(jì)算機(jī)開機(jī)的時(shí)候如果從軟盤啟動(dòng)是如何識別這是不是一個(gè)啟動(dòng)盤呢乌奇?這是學(xué)習(xí)計(jì)算機(jī)的第一個(gè)問題。從看過兩本學(xué)習(xí)操作系統(tǒng)的書都是從軟盤講起的眯娱,其實(shí)現(xiàn)在的主流是從U盤啟動(dòng)礁苗,不過原理肯定都差不多。
如果軟盤的第一個(gè)柱面徙缴,第一個(gè)盤頭试伙,第一個(gè)扇區(qū)的最后兩個(gè)字節(jié)是0x55AA,那個(gè)BIOS的啟動(dòng)程序會(huì)自動(dòng)打這個(gè)扇區(qū)的512個(gè)字節(jié)寫入內(nèi)存中的0x7c00-0x7dff這512個(gè)字節(jié)的內(nèi)存中娜搂。
第2天
一個(gè)軟盤一共有80個(gè)柱面迁霎,編號分別從0-79;每個(gè)柱面有18個(gè)扇區(qū)百宇,編號從1-18考廉,軟盤還有2個(gè)面,每次計(jì)算機(jī)從軟盤讀的最小單位不是字節(jié)携御,而是扇區(qū)昌粤,所以每次都會(huì)一次性讀512個(gè)字節(jié)既绕。軟盤的大小也可以計(jì)算出來,80*2*18*512 = 1440KB涮坐。
調(diào)用BIOS顯示一個(gè)字符凄贩,這里使用第16號中BIOS中斷,也就是 int 0x10
:
ah = 0x0e;
al = 要顯示字符ASCII;
bh = 0;
bl = color code;基本設(shè)置為0x0f
第3天
計(jì)算機(jī)自動(dòng)讀入0x7c00的512個(gè)字節(jié)對于操作系統(tǒng)來說是遠(yuǎn)遠(yuǎn)不夠的袱讹,我們還要在這512個(gè)字節(jié)中加入讀取軟盤的指令疲扎。
調(diào)用BIOS讀取軟盤的指令,這里使用的是第19號中斷捷雕,也就是int 0x13
:
ah = 0x02(讀盤) | 0x03(寫盤)| 0x04(校驗(yàn)) | 0x0c(尋道)
al = 處理對象的扇區(qū)數(shù) 為了兼容基本為 1
ch = 柱面號(0-79)
cl = 扇區(qū)號(1-18)
dh = 磁頭號(0-1)
dl = 驅(qū)動(dòng)器號椒丧,基本為0
es : bx = 緩沖區(qū)地址
flags.cf == 0 : 沒有錯(cuò)誤
flags.cf == 1 : 有錯(cuò)誤,錯(cuò)誤碼放在ah中
通過循環(huán)把10個(gè)軟盤中10個(gè)柱面的數(shù)據(jù)讀入內(nèi)存中救巷。
10個(gè)柱面的數(shù)據(jù)大小(正反兩面):10 * 2 * 18 * 512 = 184320個(gè)字節(jié),也就是180KB壶熏。啟動(dòng)區(qū)的程序是從0x8200開始裝載的,裝載了360個(gè)扇區(qū)浦译,其中第1個(gè)扇區(qū)是BIOS自動(dòng)裝載到0x7c00中棒假。因此寫的啟動(dòng)區(qū)程序運(yùn)行完畢之后占滿的內(nèi)存空間實(shí)際上是從0x8200~0x34fff。
從這里已經(jīng)用到了很多匯編的跳轉(zhuǎn)指令了精盅,這里總結(jié)一下
- je, jump if equal, 如果相等就跳轉(zhuǎn)
- jnc, jump if not carry, 進(jìn)位標(biāo)志是0就跳轉(zhuǎn)
- jae, jump if above or equal, 大于等于時(shí)跳轉(zhuǎn)
- jb, jump if below, 如果小于的話帽哑,就跳轉(zhuǎn)
試驗(yàn):往空軟盤里存入一個(gè)文件,發(fā)現(xiàn)文件內(nèi)容總是保存到0x4200這個(gè)位置叹俏。
結(jié)論:接下來可以寫兩個(gè)匯編文件祝拯,第一個(gè)就是之前一直寫的啟動(dòng)區(qū)程序(ipl),第二個(gè)才是操作系統(tǒng)直正的功能程序(haribote)她肯。啟動(dòng)區(qū)程序的功能就是把軟盤里的10個(gè)柱面讀入內(nèi)存,然后跳到磁盤0x4200位置所在的內(nèi)存鹰贵。接下來就是計(jì)算磁盤0x4200的數(shù)據(jù)被讀入到哪個(gè)內(nèi)存地址中晴氨。
計(jì)算過程:磁盤中的第二個(gè)扇區(qū)復(fù)制到0x8200中,為了計(jì)算方便假設(shè)第一扇區(qū)存入到0x8000中(實(shí)際上被BIOS復(fù)制到0x7c00中)碉输。那么0x8000 + 0x4200 = 0xc200籽前。只要在啟動(dòng)區(qū)程序復(fù)制完10個(gè)扇區(qū)之后,執(zhí)行jmp 0xc200
指令敷钾,就可以開始執(zhí)行操作系統(tǒng)的功能枝哄。
調(diào)用BIOS中切換顯示模式的中斷程序,設(shè)置顯卡模式int 0x10
:
ah = 0x00;
al = 模式:
0x03:16色字符模式阻荒,80*25
0x12:VGA圖形模式挠锥,640*480*4位彩色模式,獨(dú)特的4面存儲(chǔ)模式
0x13:VGA圖形模式侨赡,320*200*8位彩色模式蓖租,調(diào)色板模式
0x6a:擴(kuò)展VGA模式粱侣,800*600*4位彩色模式,獨(dú)特的4面存諸模式
啟動(dòng)區(qū)程序已經(jīng)完成蓖宦,接下來開始寫操作系統(tǒng)程序齐婴,操作系統(tǒng)程序要CPU進(jìn)入32位模式,那么BIOS中斷就不能用了稠茂,所在要在進(jìn)入32位模式之前柠偶,把想要用BIOS程序做的事情要先給做完。
調(diào)用BIOS中斷程序睬关,取得鍵盤各種LED指示燈的狀態(tài),int 16
:
ah = 0x02
在進(jìn)入32位之前诱担,haribote匯編程序中把讀取的柱面數(shù)(10),橫向分辨率(320)共螺,縱向分辨率(200)该肴,還有圖像緩沖區(qū)起始地址(0xa0000)寫到內(nèi)存的0xff0~0xffc中。
這本書的作都在haribote匯編程序文件中加入了100多行匯編程序藐不,直接從CPU16位模式跳入到32位模式匀哄,而且增加了使用C語言的部份,接下來就可以使用C語言編寫程序了雏蛮。
C語言源文件經(jīng)過C語言編譯器涎嚼,翻譯成匯編語言,然后從匯編語言經(jīng)過匯編號翻譯成機(jī)器語言挑秉,這個(gè)機(jī)器語言文件就是目標(biāo)文件法梯,基本上用.obj作為后綴。但是這個(gè)機(jī)器語言還不能直接執(zhí)行犀概,在各個(gè)操作系統(tǒng)中還是鏈接成各個(gè)操作系統(tǒng)認(rèn)可的可執(zhí)行文件立哑。目前為止這里的鏈接,只是把目標(biāo)文件和haribote文件復(fù)制在一起姻灶,作成一個(gè)完整的機(jī)器語言文件铛绰。但是具體作了什么操作,這本書的作者應(yīng)該會(huì)下接下來的學(xué)習(xí)中講产喉。
用匯編語言編寫函數(shù)供C語言調(diào)用:用匯編寫了函數(shù)之后捂掰,還要與主函數(shù)鏈接,輸出的目標(biāo)文件設(shè)置成WCOFF格式曾沈,設(shè)置成32位这嚣。函數(shù)名加下劃線。
第4天將使用C語言編寫畫面顯示程序嘍塞俱。