本節内容源自《操作系統真象還原》,請大家支持正版
為什麼是0x7c00計算機執行到這份上,bios也即将完成自己的曆史使命了,完成之後,它又将睡去。想到這裡,心中不免一絲憂傷,甚至有些許挽留它的想法。可是,這就是它的命,它生來被設計成這樣,在它短暫的一生中已經為後人創造了足夠的精彩。何況,在下一次開機時,bios還會重複這段輪回,它并沒有消失。好了,讓傷感停止,讓夢想前行。
先說重點,bios最後一項工作校驗啟動盤中,位于0盤0道1扇區的内容。在此插播一段小告示:在計算機中是習慣以0做為起始索引的,因為人們已經習慣了偏移量的概念,無論是機器眼裡和程序員眼裡,用“相對”的概念,即偏移量來表示位置顯得很直觀,所以很多指令中的操作數都是用偏移量表示的。0盤0道1扇區本質上就相當于0盤0道0扇區。為什麼稱為1呢,因為硬盤扇區的表示法有兩種,我們描述0盤0道1扇區用的便是其中的一種:CHS方法,即柱面Cylinder 磁頭Header 扇區Sector(另外一種是LBA方式,暫不關心),“0盤”說的是0磁頭,因為一張盤是有上下兩個盤面的,一個盤面上對應一個磁頭,所以用磁頭Header來表示盤面。“0道”是指0柱面,柱面Cylinder指的是所有盤面上、編号相同的磁道的集合,形象一點描述就是把很多環疊摞在一起的樣子,組合在一起之後是一個立體的管狀。“1扇區”才是我們要解釋的部分,将磁道等距劃分成一段段的小區間,由于磁道是圓形,确切地說是圓環,所以這些被劃分出來的小區間便是扇形,所以稱為扇區。好了,背景交待完了,重點來了,在CHS方式中扇區的編号是從1開始的,不是0,不是0,原諒我說了兩次,良苦用心你懂的,所以0盤0道1扇區是其實就相當于0盤0道0扇區,它就是磁盤上最開始的那個扇區。而LBA方式中,扇區編号是從0開始的。關于硬盤的知識我會在以後章節專門來講,這裡我若沒表達清楚,大家先不要着急,隻要知道mbr所在的位置是磁盤上最開始的那個扇區就行了。繼續說,如果此扇區末尾的兩個字節分别是魔數0x55和0xaa,bios便認為此扇區中确實存在可執行的程序(在此先劇透一下,此程序便是久聞大名的主引導記錄MBR),便加載到物理地址0x7c00,随後跳轉到此地址,繼續執行。
這裡有個小細節,bios跳轉到0x7c00是用jmp 0:0x7c00實現的,這是jmp指令的直接絕對遠轉移用法,段寄存器cs會被替換,這裡的段基址是0,即cs由之前的0xf000變成了0。如果此扇區的最後2個不是0x55和0xaa,即使裡面有可執行代碼也無濟于事了,bios不認,它也許還認為此扇區是沒格幹淨呢,嘿嘿。
不過,這就又抛出兩個問題:
先回答第1個,我想這個問題不用官方解釋了,因為官方确實沒什麼好說的,不過他們出于尊重客戶,還是會像我一樣說出類似下面的話。
我就個人觀點給大家一個理由,未經核實,僅是自己一面之詞,請大家提高警惕,小心謹慎^—^。
在計算機中處處充滿了協議、約定,所以,将0盤0道1扇區做為mbr的栖身之地,我完全可以理解為規定。我們反證一下,如果不存在這個“規定”,會發生什麼。當然,此扇區最初是給bios使用的,咱們設想一下bios的工作将變成怎樣。
主引導記mbr是段程序,無論是位于軟盤、硬盤、或者其它介質,總該有個地方保存它。Ok,現在不告訴bios 它存儲在哪個位置了。bios隻好将所有檢測到的存儲設備上的每一個存儲單位都翻一遍,挨個對比,如果發現該存儲單位最後的兩個字節是0x55和0xaa,就認為它mbr。這就好比查字典一樣,不用偏旁部首和拼音檢索的方法,隻能一頁一頁翻了。
幾經花開花落,找到mbr的那一刻,bios滿臉疲憊地說:“你是我找了好久好久的那個人”。mbr擡起經不起歲月等待的臉:“難得你還認得我,我等你等到花兒都謝了”。其實bios的心聲是:“看我手忙腳亂的樣子,你們這是要鬧哪樣啊。就那麼512字節的内容,害我找遍全世界,我們是在跑接力賽啊,下一棒的選手我都不知道在哪裡……以後讓它站在固定的位置等我!”。
由于0盤0道1扇區是磁盤的第一個扇區,mbr選擇了離bios最近的位置站好了,從此以後再也不擔心被bios罵了。
計算機中處處有固定寫死的東西,還用舉個例子嗎?不用了吧?因為任何一個魔數都是啊^_^,有請下一個魔數0x7c00登場。
至于0x7c00,很久之前,比我好奇心大的人查遍了intel開發手冊都沒找到相關的說明。要想 知道事情的來龍去脈,還是要從個人電腦的老祖宗說起,同樣是很久很久以前……1981年8月,IBM公司生産了世界上第一台個人電腦PC 5150,所以它就是現代x86個人電腦兼容機的祖先。說到有關曆史的東西,不給來點真相就感覺氣場不足,上圖啦,這是IBM PC 5150,有沒有感受到計算機文化底蘊呢。
既然intel開發手冊中沒有相關說明,那咱們就朝其它方向找答案,換句話說,既然不是cpu的硬性規定,那很可能就是代碼中寫死的。為了搞清楚0x7c00是哪裡來的,咱們先探索下 "IBM PC 5150"的bios的秘密。請先深深呼吸一大口氣,“0x7C00”最早出現在IBM 公司出産的個人電腦PC5150的ROM BIOS的 INT19H中斷處理程序中,說了這麼多定語,感覺氣都喘不上來了。
通電開機之後,bios處理程序開始自檢,随後,調用bios中斷0x19h,即 call int 19h。在此中斷處理函數中,bios要檢測這台電腦有多少硬盤或軟盤,如果檢測到了任何可用的磁盤,bios就把它的第一個扇區加載到0x7c00.
現在應該搞清楚了為什麼在x86手冊裡找不到它的說明了,它是屬于bios中的規範。似乎這下好辦了,既然是bios中的規範,那肯定是IBM PC 5150 BIOS 開發團隊規定的這個數。
個人計算機肯定要運行操作系統,在這台計算機上,運行的操作系統是DOS 1.0,不清楚此系統要求的最小内存是16KB還是32KB,反正PC 5150 BIOS研發工程師就假定其是32K,所以此版本bios是按最小内存32KB研發的。
MBR不是随便放在哪裡都行的,首先不能覆蓋已有的數據,其次,不能過早的被其它數據覆蓋。不覆蓋已有數據,這個好理解。說一下後面這個“其次”。通常,MBR的任務是加載某個程序(這個程序一般是内核加載器,很少有直接加載内核的)到指定位置,并将控制權交給它。所謂的交控制權就是jmp過去而已。之後MBR就沒用了,被覆蓋也沒關系。我說的過早被覆蓋,是指不能讓mbr破壞自己,比如被加載的程序,如内核加載器,其放置的内存位置若是MBR自己所在的範圍,這不就是破壞自己了嗎,這就是我所說的“過早”了,怎麼也得等mbr執行完才行。
重現一下當時的内存使用情況:8086cpu要求物理地址0x0~0x3FF存放中斷向量表,所以此處不能動了,再選新的地方看看。按DOS 1.0要求的最小内存32KB來說,MBR希望給人家盡可能多的預留空間,這樣也是保全自己的作法,免得過早被覆蓋。所以MBR隻能放在32KB的末尾。MBR本身也是程序,是程序就要用到棧,棧也是在内存中的,所以MBR雖然本身隻有512字節,但還要為其所用的棧分配點空間,所以其實際所用的内存空間要大于512字節,估計1k内存夠用了。結合以上三點,選擇32KB中的最後1K最為合适,那此地址是多少呢。32KB換算為16進制為0x8000,減去1K(0x400)的話,等于0x7c00。這就是倍受質疑的0x7c00的由來,這下清楚了。可見,加載MBR的位置是取決于操作系統本身所占内存大小和内存布局。
我想大家現在都心癢癢了吧,說了這麼久,cpu中運行的都是bios的代碼,連自己一句代碼都沒跑起來呢。事不宜遲,馬上寫一個MBR,先讓它跑起來再說。
【再續】
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!