2017-01-04 35 views
6

原因我的問題是,Starman seems to believe the GRUB Legacy author's explanation(參見下面莫名其妙的代碼:是不是07C0:0000,x86機器上的物理地址與0000:7C00相同?

7C4B EA507C0000 JMP  0000:7C50 ; Long Jump to the next instruction 
             ; because some bogus BIOSes jump to 
             ; 07C0:0000 instead of 0000:7C00. 

當我執行Intel的指定的算法用於對所述第一存儲器的參考構造有效地址,我乘07C0:由16(有效左移四位或半個字節)然後我加上0000的偏移量並得到十進制地址31,744

如果我左移了第二個內存引用四位的段,我仍然有0000:偏移量爲:7C00仍然是地址31,744,所以我的直覺反應是這個GRUB的作者Legacy引導扇區代碼正在拉動我們的腿。如果有效地址計算爲十進制31,744,那麼看起來沒有任何問題,這是跳遠解決的問題。

假設代碼的作者只是用一種似乎與正確的物理位置相同的方式表示僞造的物理內存位置,我開始考慮如何處理一個BIOS,它將一個寄給錯誤的地址。五字節跳遠似乎不是解決任何問題的方法。五個NOP將用於相同的目的(事實上,簡單地, 以較早的五個字節開始引導扇區代碼,並且消除長跳將具有與跳至下一條指令的跳轉相同的效果)。

如果BIOS跳轉到正確的位置(7C00),沒問題。如果BIOS跳轉到7C00以上的位置,那麼在7C00加載的代碼無法解決該問題。如果BIOS跳轉到7C00和7C4B之間的某個位置,那麼存儲在該區域的數據(或者解釋器中的數據會丟失字節)可能會導致崩潰。如果BIOS跳轉到7C4B,測試指令將被覆蓋(通過跳轉),JNZ到7C54將根據BIOS中執行的最後一次數學運算執行。

對於7C4B以下的BIOS跳轉,再次錯誤對齊的指令可能會導致崩潰。祝你好運,引導扇區代碼的一部分將被執行。這種執行的結果將取決於BIOS確實跳到了什麼「假」內存地址。那麼這個引導扇區代碼的作者是否會拉動我們的故事,講述一個關於「虛假BIOS跳到錯誤位置」的故事?

我在Luke Luo的BLOG中注意到,GRUB2引導扇區儘管不同於GRUB Legacy引導扇區retains this inexplicable Long Jump。因此,如果GRUB Legacy引導扇區的原作者正在爲我們開玩笑,這是一個相當成功的笑話(它已經完全重寫了GRUB)。我剩下的選擇是相信對某些未命名的BIOS有一種令人難以置信的斷言,並且這種問題的解決方案似乎實際上什麼都不做,認爲原始引導扇區的作者在爲我們開玩笑。

Luke Luo似乎接受了將NOP指令寫入7C66和7C67,作爲他沒有跳到錯誤位置的BIOS的證據。由Linux Mint 13寫入我的閃存驅動器的GRUB2引導扇區具有相同的NOP。然而,寫在筆記本電腦硬盤驅動器(由Debian Etch開發)的GRUB2引導扇區只有很短的時間才能跳到以7C66和7C67編寫的下一條指令(請注意,Luke Luo向我們展示了原始引導扇區存儲在/ usr/lib/grub/i386-pc/boot.img具有Debian值)。兩種替代方案都具有相同的效果(執行後面的指令),因此兩個引導扇區都可以工作。在引導扇區中,只有大約450個字節可用於代碼,這些代碼必須加載另一個扇區並執行它(包括錯誤消息,以便在出現該簡單操作出現問題時的錯誤消息以及該操作的八字節地址部門本身)。

所以我錯過了什麼,或者我確定了一個應該從GRUB引導扇區中刪除的kludge(爲更有意義的代碼騰出空間)?

+2

前段時間我寫了一篇關於一種情況的文章[Stackoverflow Q&A](http://stackoverflow.com/questions/34548325/near-call-jump-tables-dont-always-work-in-a-bootloader)沒有那麼遠的跳轉可能會在引導加載程序中產生錯誤的結果。這實際上取決於如何編寫引導加載程序代碼。一些引導加載程序開發人員在注意力不足的情況下添加了FAR JMP,以明確地將_CS_設置爲他們想要的值,以便它們不會遇到問題,但如果它們的代碼從不依賴於_CS_ –

+0

中的特定值認爲「豐富的謹慎」涵蓋了它。如果沒有進一步確定BIOS有這個問題,甚至不能證實它仍然存在。在我們別無選擇的情況下,只有使用我們的硬件才能使用我們的BIOS,這將成爲不知道如何編寫代碼的BIOS供應商的解決方案。今天我希望解決方案是更換BIOS。 –

+1

情況發生了什麼變化,BIOS沒有配備硬件?我在過去幾年中購買的每塊主板都配有內置的BIOS。即使在使用虛擬機的情況下,VM供應商仍然在寫BIOS實現。 –

回答

6

你錯過了CPU實際狀態的差異(而物理地址是同一個,這是正確的)。

當BIOS確實JMP 0000:7C00

您的第一個指令位於cs=0000, ip=7C00,和你的機器代碼必須被編譯爲這種搬遷的,只要它的任何絕對地址,例如像mov ax,cs:[myTable](當時myTable能像0x7F00)。

當BIOS確實JMP 07C0:0000

您的第一個指令位於cs=07C0, ip=0000,所以像myTable會更喜歡0x0300

因此,在代碼開始處的第一次跳轉會將相同的物理地址31,744「歸一化爲預期的cs:ip」形式,使得引導加載程序代碼中的其餘絕對地址正常工作。

+1

這就是我的想法,但我沒有在彙編代碼中找到任何段覆蓋前綴。接下來的指令將DS初始化爲[0000]。你有沒有發現它在代碼中的作用?也許這只是先前代碼的遺留... – fjardon

+0

@fjardon我沒有檢查特定的源代碼,因爲即使特定的引導加載程序只能用'ds:'和相對跳轉操作,對於將來嘗試修改它的人來說,它仍然有點「有毒」陷阱。所以即使對於不依賴'cs'值的代碼,我仍然會推薦這種做法。 – Ped7g

+0

@fjardon現在我看了一下,沒有發現任何問題。所以看起來在這種情況下,跳躍確實只是預防措施(我只用了5分鐘左右的時間,沒有嚴肅的代碼審查)。然後我再次不確定額外的5B是否值得*任何風險。在某些特殊情況下肯定是的,但通常可能不會。 – Ped7g

相關問題