假設我的API是從一個只能在實模式或大實模式下工作的系統調用的。我的API應該顯示當前的系統模式。那麼它怎麼能知道當前模式是實模式還是大實模?如何知道當前模式是真實模式還是大實模?
注:
- 在大實模式保護模式啓用
CR0
位被禁止的,因此檢查它沒有任何區別。 - 儘管A20地址線已啓用,但並不表示它處於大實模式。
假設我的API是從一個只能在實模式或大實模式下工作的系統調用的。我的API應該顯示當前的系統模式。那麼它怎麼能知道當前模式是實模式還是大實模?如何知道當前模式是真實模式還是大實模?
注:
CR0
位被禁止的,因此檢查它沒有任何區別。在大實模式下,實模式地址別名會失敗。假設您處於大實模式,並且您的DS的值爲0x6000。由於DS的描述符緩存已被重載(大實模式的定義),因此DS:0的物理地址不是0x60000。如果用另一個段寄存器命中0x60000,那將不會是相同的內存位置。
所以這是一個配方。在數據段中創建一個臨時變量。請注意其相對於DS的offset
。使用DS-1的值加載ES,更改變量的值,並查看ES(offset
+ 0x10)上是否有相同的值。爲了防止誤報,請做兩次。
這不會檢測虛擬86模式。另外,如果ES通過緩存描述符指向高內存,那麼當您重新加載ES時,這將會丟失。確保調用者代碼不會依賴ES保持不變。
大實模式本身不是CPU模式 - 沒有寄存器位表示「我們現在處於大真實狀態」。這只是一種使用香草實模式的i386特定邏輯來訪問高內存的方法。上述程序只檢查DS是否已經這樣處理;根據實現情況,DOS擴展器可能通過ES描述符重新加載實現了大實數,同時保持DS vanilla。維基百科說,有時甚至CS也會以這種方式造成混淆,儘管這是一個棘手的命題,因爲中斷。
如果執行此:
mov ebx, 0x10000
mov al, [ebx]
,並得到一個#GP
,然後DS
段描述符具有0xFFFF的原有限制,這是正常的真實地址模式和虛擬8086模式的情況下。
如果您沒有從mov al, [ebx]
得到#GP
,原始限制已經擴展到0xFFFF以上(通常爲0xFFFFFFFF,但不一定如此)。
順便說一句,檢查v86模式可能也可能應該在嘗試上述之前完成(如果您的主機操作系統沒有正確地反映您的處理程序異常)。執行smsw
即可獲得cr0.pe
。它將在v86模式下設置爲1,在實際地址模式下設爲0。直接用mov
讀取cr0
將在v86模式下生成#GP
,這就是爲什麼smsw
是首選方法。
在90年代初期,我們使用了一種未公開的方法讓我們能夠以真實模式訪問4Gig(現在可以稱爲BIG REAL MODE)。該方法將進入保護模式,將粒度位更改爲1(意味着4K粒度而不是1個字節的粒度),然後返回實模式並將所有段寄存器設置爲0.然後可以使用ebx等訪問4Gig的內存。
所以如果這就是你所說的,試着去保護模式並檢查粒度位的設置。對不起,我所有的舊手冊都在閣樓上。如果你需要這些信息,我可以把它們挖出來。
BRM與別名無關。段基地址保持相等'段值* 0x10'。但是,段限制設置爲大於0xFFFF的值,允許偏移量> = 0x10000。這就是BRM的重點。 – 2013-03-11 22:23:16