MIT 6.828 JOS學習筆記9. Exercise 1.5


Lab 1 Exercise 5

  再一次追蹤一下boot loader的一開始的幾句指令,找到第一條滿足如下條件的指令處:

  當我修改了boot loader的鏈接地址,這個指令就會出現錯誤。

  找到這樣的指令后,把boot loader的鏈接地址修改一下,我們要在boot/Makefrag文件中修改它的鏈接地址,修改完成后運行  make clean, 然后通過make指令重新編譯內核,再找到那條指令看看會發生什么。 最后別忘了改回來。

  

  答:

  這道題希望我們能夠去修改boot loader的鏈接地址,在Lab 1中,作者引入了兩個概念,一個是鏈接地址,一個是加載地址。鏈接地址可以理解為通過編譯器鏈接器處理形成的可執行程序中指令的地址,即邏輯地址。加載地址則是可執行文件真正被裝入內存后運行的地址,即物理地址。

  那么在boot loader中,由於在boot loader運行時還沒有任何的分段處理機制,或分頁處理機制,所以boot loader可執行程序中的鏈接地址就應該等於加載地址。在Lab中作者說,BIOS默認把boot loader加載到0x7C00內存地址處,所以就要求boot loader的鏈接地址也要在0x7C00處。boot loader地址的設定是在boot/Makefrag中完成的,所以根據題目的要求,我們需要改動這個文件的值。

  首先按照題目要求,在lab目錄下輸入make clean,清除掉之前編譯出來的內核可執行文件,在清除之前你可以先把 obj/boot/boot.asm文件拷貝出來,之后可以用來比較。然后打開這個boot/Makefrag文件,我們會發現下列語句:

  

  其中的-Ttext 0x7C00,就是指定鏈接地址,我們可以把它修改為0x7E00,然后保存退出。

  然后在lab下輸入make,重新編譯內核,首先查看一下obj/boot/boot.asm,並且和之前的那個obj/boot/boot.asm文件做比較。下圖是新編譯出來的boot.asm:

  

  下圖是修改之前的boot.asm

  

  可以看出,二者區別在於可執行文件中的鏈接地址不同了,原來是從0x7C00開始,現在則是從0x7E00開始。

  然后我們還是按照原來的方式,調試一下內核:

  由於BIOS會把boot loader程序默認裝入到0x7c00處,所以我們還是再0x7C00處設置斷點,並且運行到那里,結果發現如下:

  

  可見第一條執行的指令仍舊是正確的,所以我們接着往下一步步運行。

  接下來的幾步仍舊是正常的,但是直到運行到一條指令:

  

  圖中的0x7c1e處指令,

     lgdtw 0x7e64

  這條指令我們之前講述過,是把指令后面的值所指定內存地址處后6個字節的值輸入全局描述符表寄存器GDTR,但是當前這條指令讀取的內存地址是0x7e64,我們在圖中也展示了一下這個地址處后面6個單元存放的值,發現是全部是0。這肯定是不對的,正確的應該是在0x7c64處存放的值,即圖中最下面一樣的值。可見,問題出在這里,GDTR表的值讀取不正確,這是實現從實模式到保護模式轉換的非常重要的一步。

   我們可以繼續運行,知道發現下面這句:

  

  正常來說,0x7c2d處的指令

      ljmp $0x08m $0x7e32

  應該跳轉到的地址應該就是ljmp的下一條指令地址,即0x7c32,但是這里給的值是0x7e32,所以造成錯誤,此時下條指令變成了0xfe05b。自此程序走向了不歸路~

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM