Contents

Usage

Unreal mode is recommended in the two following cases :

you're trying to extend a legacy 16-bits DOS program so that it can deal with larger data and neither vm86, nor xms is suitable for your needs

you're trying to load something that will run in 32 bits mode and which is larger than 640Kb (so you cannot load it in conventional memory) and you don't want to bother with a disk driver called from pmode yet, and you do not wish to switch between real and protected mode for copying chunks from the conventional memory buffer to the high 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 blocks will be unavailable.

Implementation

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 register are an index into the descriptor table. That's why in this code 0x08 = 1000b gets you the 1 entry.

When this register given a "selector", a "segment descriptor cache register" is filled with the descriptor 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 64k limit is no longer valid and 32-bit offsets can be used with the real-mode addressing rules (i.e. shift segment 4 bits, then add offset).

Big Unreal Mode

These will not have affected CS.
Therefore IP is unaffected by all this, so the code itself is still limited to 64 K.

Huge Unreal Mode

Huge Unreal Mode enables code over 64K. 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:

Compiler Support

Smaller C

The code and the stack are to be located below the 1MB mark and the stack size is limited by 64KB (IOW, there's nothing unusual about CS:(E)IP, SS:(E)SP, it's a natural setup for MZ executables in DOS). The DS and ES segment registers are set to 0, so C pointers can work as flat 32-bit physical addresses and address data or memory-mapped devices anywhere in the first 4GB of memory.

The startup code of these executables performs the necessary relocation (there are only custom relocations and no standard MZ relocations, which may simplify loading of the executables) and sets up unreal mode before passing control to the equivalent of main(). See srclib/c0du.asm and other C/assembly code under srclib in the compiler source tree for how to write bits of assembly code for unreal mode (look for asm("inline asm code") under #ifdef __UNREAL__).

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.