Reputation: 21
Suppose my API is to be called from a system which may work in real mode or big real mode only. My API is supposed to display the current system mode. Then how could it know whether the current mode is real mode or big real mode?
Note:
CR0
is disabled, hence checking it doesn't make any difference.Upvotes: 1
Views: 1180
Reputation: 909
In the early 90's we used an undocumented method to give us access to 4Gig in REAL mode (may now be called BIG REAL MODE). The method was to go into protected mode, change the granularity bit to 1 (means 4K granularity as opposed to 1 byte granularity) then go back to real mode and set all segment registers to 0. You can then use the ebx, etc to access 4Gig of memory.
So if that is what you are talking about, try going to protected mode and check the setting of the granularity bit. I'm sorry but all of my old manuals are in the attic. If you need that information I could dig them out.
Upvotes: 0
Reputation: 62106
If you execute this:
mov ebx, 0x10000
mov al, [ebx]
and get a #GP
, then the segment descriptor for DS
has the original limit of 0xFFFF, which is the case for the normal real address mode and for the virtual 8086 mode.
If you don't get a #GP
from mov al, [ebx]
, the original limit has been extended beyond 0xFFFF (usually to 0xFFFFFFFF, but not necessarily so).
Btw, checking for the v86 mode can and probably should be done prior to trying the above (in case your host OS doesn't properly reflect exceptions to your handlers). Execute smsw
to obtain cr0.pe
. It will be set to 1 in the v86 mode and to 0 in the real address mode. Reading cr0
directly with mov
will generate a #GP
in the v86 mode, which is why smsw
is a preferred method.
Upvotes: 1
Reputation: 61386
In the big real mode, real mode address aliasing would fail. Let's imagine you're in big real mode, and your DS has the value of 0x6000. Since the descriptor cache for DS has been reloaded (the very definition of big real mode), the physical address of DS:0 is not 0x60000. If you hit 0x60000 with another segment register, that won't be the same memory location.
So here's a recipe. Create a scratch variable in the data segment. Note its offset
relative to DS. Load ES with the value of DS-1, change the value of the variable, and see if you get the same value at ES:(offset
+0x10). To protect against false negatives, do it twice.
This won't detect the virtual 86 mode. Also, if ES was pointing at high memory via a cached descriptor, too, this will be lost when you reload ES. Make sure the caller code won't rely on ES staying intact.
The big real mode is not a CPU mode per se - there's no register bit that says "we're in big real now". It's just a way to access high memory using the i386-specific logic of the vanilla real mode. The procedure above only checks if DS has been treated that way; depending on implementation, a DOS extender might've implemented big real via ES descriptor reloading while keeping DS vanilla. Wikipedia says that sometimes even CS is aliased in this way, albeit this is a tricky proposition because of interrupts.
Upvotes: 0