《linux內核完全註釋0.11》 讀書筆記 0

Read the Fucking Souce Code微笑

第三章 引導啓動程序(BOOT)

        打開電源---80x86結構cpu自動進入實模式從0xFFFF0【ROM-BIOS中地址】地址執行程序代碼----BIOS進行系統檢測在物理地址0處初始化中斷向量-----將可啓動設備的第一扇區(磁盤引導扇區512B)讀入到內存的絕對地址0x7c00處,並跳轉到這裏
bootsec.s 將由BIOS讀入到內存絕對地址0x7c00(31KB)處,當它被執行時會把自己移動到絕對地址爲0x90000(567KB)處,並把啓動設備中後2KB代碼(setup.s)讀到內存0x90200處,而內核的其他模塊(system)則被讀到從地址0x10000處【因此system模塊不會超過0x80000字節即512KB,不會覆蓋setup.s和bootset.s】;後面的setup程序將system模塊移動到內存初始處,這樣system模塊的地址等於實際的物理地址,然後將控制權交給了setup模塊,啓動模塊主要對主機的某些特性以及VGA卡的類型,然後將系統從0x10000移到0x0000處,進入保護模式並跳轉到0x0000.便於操作。移動過程如圖所示:
    疑問疑問:爲什麼不直接把系統模塊直接加載到0x0000處而要在setup裏面移動呢?這是因爲setup模塊需要ROMBIOS的中斷獲取機器的一些參數。當bios初始化時會在物理內存的開始處設置一個大小爲0x400字節的中斷向量表,因此需要在調用完成後將其覆蓋掉。

bootsect.s程序 

        功能描述:
是磁盤引導塊程序,駐留在磁盤第一個扇區(引導扇區,0磁道,0磁頭,1扇區)。pc加電後,BIOS把它加載0x7c00處,然後將自己移動到0x90000處。主要作用是首先將setup模塊從磁盤加載到內存,緊接着bootsect的後面位置(0x90200),然後使用BIOS中斷0x13取磁盤列表中當前引導盤的參數,接着在屏幕上顯示“Loading System”,再將System模塊從磁盤加載到0x10000開始的地址處,隨後確定根文件系統的設備號,若沒指定,據磁道扇區判別出盤的種類和類型並保存設備號與root_dev(引導塊的0x508),最後長跳到setup程序的開始處(0x90200)執行setup程序。
閱讀到的相關信息:
|------------SYSSIZE = 0x3000 =196KB 編譯連接後system模塊的大小,最大默認值。
|------------REP prefixesapply only to one string instruction at a time
|------------jmpi go,INITSEG 跳轉到INITSEG段,偏移go處==  CS的值設爲#BOOTSEG,IP的值設爲go ++jmpi是段間間接跳轉
|------------寄存器 ---
|-------------------------通用寄存器AX,BX,CX,DX(16b)
|-------------------------變址寄存器 SI(源)DI(目的) 串操作指令{DS與SI 尋址數據段的源操作數 ES與DI 尋址附加段中的目的操作數}
|-------------------------指針寄存器 BP與SP指向堆棧段的數據單元 SS指示堆棧段的開始位置 SP指向相對堆頂的開始位置的偏移位置}
|-------------------------指令寄存器 CS指示代碼段的開始位置 IP指示當前指令在代碼段的偏移位置
|-------------------------GS 附加段寄存器
|------------JNC 當CF=0 到指定標號執行
源碼閱讀相關問題:
|------------bootsect的堆棧設置SS指向了0x9000,SP指向0xFF00{SP大於0x200(bootsect大小) +0x200*4(setup大小)+堆棧大小} 
|------------load_setup其中的讀扇區到制定緩衝區   入口參數 AH=02H AL=扇區數 CH=柱面 CL=扇區
|----------------------------DH=磁頭  DL=驅動器,00H~7FH:軟盤;80H~0FFH:硬盤 ES:BX=緩衝區的地址 
|----------------------------出口參數:CF=0——操作成功AH=00H,AL=傳輸的扇區數,否則,AH=狀態代碼,
|------------ok_load_setup其中讀取磁盤驅動器的參數  入口參數:AH=08H  DL=驅動器,00H~7FH:軟盤;80H~0FFH
|----------------------------硬盤出口參數:CF=1——操作失敗,AH=狀態代碼

setup.s程序

功能描述:

        主要利用ROM-BIOS中斷讀取機器系統數據,並將這些數據保存到0x90000開始的位置(覆蓋bootsect程序所在的位置),所取的參數供其他程序使用如ttyio.c程序,然後將system模塊從0x10000~~0x8ffff(不會超過512KB)整塊移動到內存絕對地址0x00000處,接下來加載中斷描述符表寄存器和全局描述符表寄存器,並開啓A20地址線,重設中斷芯片8259A,將硬件的中斷號設置爲0x20~~0x2f。最後設置CPU控制寄存器CR0(也稱機器狀態字)從而進入32位保護模式運行,並跳轉到位於system模塊最前面的head.s程序繼續運行。

源碼閱讀相關問題:

|--------jmpi 0,8會跳轉到head.s程序開始繼續運行,8是段選擇符,用於制定所需使用的描述符項{是代碼段描述符項} 0 是代碼段偏移

setup程序執行完成後的內存中程序的示意圖:


head.s程序

功能描述:

首先加載各個數據段寄存器,重新設置中斷描述符表idt,共256項,並使每一個表項指向一個只報錯誤的啞中斷程序。然後重設全局描述符表gd,檢測A20地址線是否開啓{使用物理地址0與1MB開始處的內容相比較的方法},然後測試是否存在數學協處理芯片,並在控制寄存器CR0中設置相應的標誌位。接着管理內存的分頁處理機制,將頁目錄放在絕對物理地址0開始處,緊隨其後的是可尋址16MB的內存的四個頁表,並分別設置他們的表項。最後利用返回指令將預先放置到堆棧中的main.c程序的入口地址彈出,運行main程序。

閱讀到的相關信息:

|-----將堆棧放置到stack_start所指向的user_stack數組內

|-----中斷描述符表中的項由8B組成,也稱作門描述符(Gate Descriptor)

|-----設置每個頁表爲4KB,每個頁表項需要4B,一個頁表共可以存放1024個表項。

system模塊在內存的映像示意圖:




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章