2011-08-02 41 views
5

在研究一些簡單的os源代碼時,我對一個簡單的彙編問題感到困惑。是否可以在實模式下使用32位寄存器/指令?

在這個網站:http://wiki.osdev.org/Babystep7下面的代碼是切換從實模式到保護模式

mov eax, cr0 
or al,1 
mov cr0, eax 

我知道如何從實模式到保護模式切換。
但我的問題是,因爲程序仍處於實模式,它如何使用32位寄存器或指令?

是否可以在實模式下使用32位寄存器/指令?

+1

我想你還需要清除預取程序(通常使用jmp到下一個內存位置)。 –

回答

4

當處理器以實模式運行時(因爲它在啓動後立即運行),它默認爲16位代碼。但是,而不是意味着您無法使用32位指令。

有一個「操作數大小覆蓋」前綴(66h),它改變了單個指令的默認模式。當該前綴與在16位實模式下執行的指令一起使用時,它會將指令切換爲32位。相反,當這個前綴與在32位保護模式下執行的指令一起使用時,它將把指令切換到16位。 (類似的前綴67h可以覆蓋地址大小。)

然後,使用此前綴可以在16位實模式下使用32位寄存器。當您在彙編16位代碼時嘗試使用帶指令的32位操作數時,彙編器幾乎肯定會自動發出此前綴。

不幸的是,64位指令沒有這樣的覆蓋前綴,所以這些不能用於實模式。您需要切換到「長模式」以允許這些。

+0

謝謝,這解決了我的問題 – mike820324

+0

你也可以在實模式下使用64位寄存器嗎? –

4

據我所知,實模式不會影響您可以在CPU上運行的命令,但它會影響CPU內存參考命令的解釋方式。

所以,是的,你可以使用eax,但你將無法得到[eax]存儲單元。

查看Intel's Manual的相關部分。

+0

我相信「......但是你將無法獲得[eax]存儲單元。」是不正確的。我的理解是,在實模式下,如果eax的值小於或等於0x0000FFFF,那麼[eax]是完全有效的訪問。當您嘗試訪問[eax]時,較大的eax值會產生保護錯誤(但如果[eax]會顯着[ax]不需要產生保護錯誤)。 – Orby

0

據我所知,在實模式下,你不能使用32位寄存器。 在32位控制寄存器CR0中,通過查看CR0(PE)的第一位來確定實模式和保護模式。在此代碼中,更改最後一行(mov cr0,eax)中的PE。 我想,在這一行之後,你不能再使用32位寄存器引用。

+1

這是不正確的,您可以使用0x66前綴訪問16位/實模式下的32位寄存器。 –

0

對於簡單的尋址操作數和指令大小的前綴工作得很好。我曾經爲Windows編寫過的16位保護(初始真實)模式應用程序(3.1和更高版本)可以使用Windows內存API分配大於64K的內存區域,問題是如何使用它。在任何情況下,使用(遠)指針插入和前綴提到我的應用程序使用40MB的區域很好,即使它運行在16位模式。

如果您嘗試類似的操作,請記住指令大小前綴將啓用與16位不兼容的32位指令集。除非你在做分段算術,否則16位通常不關心你是否處於真實或保護模式。所以你需要手動編寫代碼(至少我是這樣做的)使用發射的32位操作,因爲你的編譯器可能不會在沒有大喊血腥謀殺的情況下生成它們。

0

存在一個32位實模式,它被稱爲unreal mode。在那些時代,它被用來訪問整個地址空間,沒有使用選擇器和整個保護模式開銷的麻煩。

0

您或許可以使用LOADALL 操作碼0F07h,讓你在16位實模式的32次訪問。

+0

這個操作碼幾乎沒有記錄,在大多數現代CPU上,其編碼的語義已被指令'sysret'取代。 – minmaxavg

相關問題