在研究一些簡單的os源代碼時,我對一個簡單的彙編問題感到困惑。是否可以在實模式下使用32位寄存器/指令?
在這個網站:http://wiki.osdev.org/Babystep7下面的代碼是切換從實模式到保護模式
mov eax, cr0
or al,1
mov cr0, eax
我知道如何從實模式到保護模式切換。
但我的問題是,因爲程序仍處於實模式,它如何使用32位寄存器或指令?
是否可以在實模式下使用32位寄存器/指令?
在研究一些簡單的os源代碼時,我對一個簡單的彙編問題感到困惑。是否可以在實模式下使用32位寄存器/指令?
在這個網站:http://wiki.osdev.org/Babystep7下面的代碼是切換從實模式到保護模式
mov eax, cr0
or al,1
mov cr0, eax
我知道如何從實模式到保護模式切換。
但我的問題是,因爲程序仍處於實模式,它如何使用32位寄存器或指令?
是否可以在實模式下使用32位寄存器/指令?
當處理器以實模式運行時(因爲它在啓動後立即運行),它默認爲16位代碼。但是,而不是意味着您無法使用32位指令。
有一個「操作數大小覆蓋」前綴(66h),它改變了單個指令的默認模式。當該前綴與在16位實模式下執行的指令一起使用時,它會將指令切換爲32位。相反,當這個前綴與在32位保護模式下執行的指令一起使用時,它將把指令切換到16位。 (類似的前綴67h可以覆蓋地址大小。)
然後,使用此前綴可以在16位實模式下使用32位寄存器。當您在彙編16位代碼時嘗試使用帶指令的32位操作數時,彙編器幾乎肯定會自動發出此前綴。
不幸的是,64位指令沒有這樣的覆蓋前綴,所以這些不能用於實模式。您需要切換到「長模式」以允許這些。
謝謝,這解決了我的問題 – mike820324
你也可以在實模式下使用64位寄存器嗎? –
據我所知,實模式不會影響您可以在CPU上運行的命令,但它會影響CPU內存參考命令的解釋方式。
所以,是的,你可以使用eax
,但你將無法得到[eax]
存儲單元。
查看Intel's Manual的相關部分。
我相信「......但是你將無法獲得[eax]存儲單元。」是不正確的。我的理解是,在實模式下,如果eax的值小於或等於0x0000FFFF,那麼[eax]是完全有效的訪問。當您嘗試訪問[eax]時,較大的eax值會產生保護錯誤(但如果[eax]會顯着[ax]不需要產生保護錯誤)。 – Orby
據我所知,在實模式下,你不能使用32位寄存器。 在32位控制寄存器CR0中,通過查看CR0(PE)的第一位來確定實模式和保護模式。在此代碼中,更改最後一行(mov cr0,eax)中的PE。 我想,在這一行之後,你不能再使用32位寄存器引用。
這是不正確的,您可以使用0x66前綴訪問16位/實模式下的32位寄存器。 –
我也在這個網站找到答案: http://forum.nasm.us/index.php?topic=991.0。
這正是ninjalj所說的,但更詳細。
對於簡單的尋址操作數和指令大小的前綴工作得很好。我曾經爲Windows編寫過的16位保護(初始真實)模式應用程序(3.1和更高版本)可以使用Windows內存API分配大於64K的內存區域,問題是如何使用它。在任何情況下,使用(遠)指針插入和前綴提到我的應用程序使用40MB的區域很好,即使它運行在16位模式。
如果您嘗試類似的操作,請記住指令大小前綴將啓用與16位不兼容的32位指令集。除非你在做分段算術,否則16位通常不關心你是否處於真實或保護模式。所以你需要手動編寫代碼(至少我是這樣做的)使用發射的32位操作,因爲你的編譯器可能不會在沒有大喊血腥謀殺的情況下生成它們。
存在一個32位實模式,它被稱爲unreal mode。在那些時代,它被用來訪問整個地址空間,沒有使用選擇器和整個保護模式開銷的麻煩。
您或許可以使用LOADALL 操作碼0F07h,讓你在16位實模式的32次訪問。
這個操作碼幾乎沒有記錄,在大多數現代CPU上,其編碼的語義已被指令'sysret'取代。 – minmaxavg
我想你還需要清除預取程序(通常使用jmp到下一個內存位置)。 –