'''Unreal mode''' consistconsists of breaking the '64Kb'64KiB limit of real mode segments, but(while still keepingretaining 16-bit bits instructioninstructions and the <tt>segment * 16 + offset</tt> addressaddressing formationmode) by tweaking the [[Descriptor Cache|descriptor caches]].
==Usage==
Unreal mode is usually recommended in the two following cases :
* youYou're trying to extend a legacy 16-bitsbit DOS program so that it can deal with larger data and neither vm86[[Virtual 8086 Mode]], nor xms isare suitable for your needs.
* youYou're trying to load something that will run in 32 bits-bit mode and which is larger than 640Kb640K (sotherefore you cannot load it in conventional memory) and you don't want to bother withwriting a protected mode disk driver called from pmode yet, andbut you doalso notwant wishto toavoid switchswitching between real and protected mode forto copyingcopy chunks from the conventional memory buffer tointo the highextended memory areas...
You still will not have full access to all physical RAM if you do not have have the [[A20 Line]] enabled; all the "odd" 1-megabyte MiB blocks will be unavailable.
==Implementation==
To do this, you need to set the descriptor cache's limits for your segment register(s) to any value higher than 64KiB (usually a full 4GiB (<tt>0xffffffff</tt>)).
The reason for doing this is to enable 32-bit offsets in real mode. However, you won't be able to go past 1 meg quite yet.
In protected mode, the bits 3-15 in the segment registerregisters arerepresent an index into [[GDT|the global descriptor table]]. That's why in thisthe following code 0x08 = 1000b gets you theentry #1 (entry #0 is ALWAYS a null descriptor).
When this(in protected mode) a segment register givenis loaded with a "selector", a "segment descriptor cache register" is filled with the descriptor's values, including the size (or limit). After the switch back to real mode, these values are not modified, regardless of what value is in the 16-bit segment register. So the 64k64KiB limit is no longer valid and 32-bit offsets can be used within theReal real-modeMode addressingto rulesactually (i.e.access shiftareas above 64KiB (<tt>segment 4* bits,16 then+ add32-bit offset</tt>).
===Big Unreal Mode===
TheseThis willwon't not have affectedtouch CS. <br />
Therefore IP is unaffected by all this, soand the code itself is still limited to 64 K64KiB.
<sourcesyntaxhighlight lang="asm">
; Assembly example
; nasmwnasm boot.asm -o boot.bin
; partcopy boot.bin 0 200 -f0
[ORG 0x7c00] ; add to offsets
start:
start: xor ax, ax ; make it zero
mov ds, ax ; DS=0
mov ss, ax ; stack starts at seg 0
or al,1 ; set pmode bit
mov cr0, eax
jmp 0x8:pmode
pmode:
jmp $+2 ; tell 386/486 to not crash
mov dsbx, bx 0x10 ; 8hselect =descriptor 1000b2▼
mov bxds, 0x08bx ; select10h descriptor= 110000b
▲ mov ds, bx ; 8h = 1000b
and al,0xFE ; back to realmode
mov cr0, eax ; by toggling bit again
jmp 0x0:unreal
unreal:
pop ds ; get back old segment
sti
dd gdt ;start of table
gdt : dd 0,0 ; entry 0 is always unused
flatdesc codedesc: db 0xff, 0xff, 0, 0, 0, 10010010b10011010b, 11001111b00000000b, 0
flatdesc: db 0xff, 0xff, 0, 0, 0, 10010010b, 11001111b, 0
gdt_end:
times 510-($-$$) db 0 ; fill sector w/ 0's
db 0x55 dw 0xAA55 ; req'dRequired by some BIOSes
</syntaxhighlight>
db 0xAA
</source>
===Huge Unreal Mode===
Huge Unreal Mode enables code over 64K64KiB. However, it is more difficult to implement as real mode interrupts do not automatically save the high 16 bits of EIP. Initialization is simple though, you just load a 32 bit code segment with a 4GiB limit:
<sourcesyntaxhighlight lang="asm">
; Assembly example
; nasmwnasm boot.asm -o boot.bin
; partcopy boot.bin 0 200 -f0
[ ORG 0x7c00] ; add to offsets
start: xor ax, ax ; make it zero
times 510-($-$$) db 0 ; fill sector w/ 0's
db 0x55 dw 0xAA55 ; req'dRequired by some BIOSes
</syntaxhighlight>
db 0xAA
</source>
WARNING: this may not work on some emulators or some hardware. This is because of direct 32bit PMODE -> (Un)real mode.
==Compiler Support==
You can try out unreal mode in DOS (e.g. in DOSBox, VirtualBox + FreeDOS) as the compiler fully supports the DOS + unreal mode combo in its C library. ''tests/vesalfb.c'' is a simple example of setting up a [[VESA]] graphics mode with the linear frame buffer enabled and drawing something on the screen in unreal mode.
For an example of an Unreal Mode [[bootloader]] implementation with Smaller C, look at [https://github.com/fysnet/FYSOS/tree/master/loader FYSOS].
[[Category:X86 CPU]]
[[Category:Operating Modes]]
[[Category:FAQ]]
|