Big Real/Unreal Mode

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
TripleFault

Big Real/Unreal Mode

Post by TripleFault »

How do I enable Unreal Mode? I know that you must go to 32-bit PMODE with A20 enabled and switch back to real mode but I'm not sure how. What method do I use to switch back to real mode and keep 4GB linear memory access? Also, if anyone could explain Unreal Mode a little to me it would be greatly appreciated.
Thanks for your help!
-TripleFault
TripleFault

Re:Big Real/Unreal Mode

Post by TripleFault »

Thanks for the info df! Do you guys know if Unreal Mode is compatible with newer processors and emulators such as Bochs, VMWARE, VirtualPC, etc? (since it is "just a party trick")
Tim

Re:Big Real/Unreal Mode

Post by Tim »

Although originally it was seen by Intel as a bug, they have since acknowledged it, since so many applications used it. So it is now documented, and future processors are obliged to support it.
Karig

Re:Big Real/Unreal Mode

Post by Karig »

I just posted this chunk of code on the OSDev.org message board; I might as well post it here.

This code starts out in real mode and ends up in unreal mode. Code and stack segments are still 16-bit/64KB, but data segments are all 32-bit/4GB.

I just tested this on my laptop and it seems to work fine. I haven't done extensive stress-testing on this or anything, so no warranties. ;D I think it's complete, though, and takes into consideration everything that needs to be considered. You'll need NASM to assemble this.

[pre]
[BITS 16] ; We start in pure real mode.

cli ; Disable interrupts.
mov dx, 0x70 ; Disable NMIs.
in al, dx
or al, 0x80
out dx, al

lgdt [GDT] ; Load the new segment descriptors.
mov eax, cr0 ; Turn on protected mode.
or al, 1
mov cr0, eax
jmp dword 0x08:.1 ; Set CS by jumping to the 32-bit code segment.

[BITS 32] ; Once we've jumped, we're now running 32-bit
; code.
.1: mov eax, dseg-GDT ; Change data-segment limits to 4GB (for all
mov ds, eax ; four data-segment registers).
mov es, eax
mov fs, eax
mov gs, eax

mov eax, ds16-GDT ; Ensure that the stack-segment limit remains
mov ss, eax ; 64KB! (Stack pointer in unreal mode is
; IP -- *not* EIP!)

jmp dword 0x18:.2 ; Ensure that the code-segment limit remains
; 64KB -- jump to the 16-bit code segment.

[BITS 16]
.2: mov eax, cr0 ; Turn off protected mode. Now the CPU will
and al, 0xFE ; interpret all code as 16-bit.
mov cr0, eax
jmp word 0x00:.3 ; Set CS to real-mode segment -- load it with
; zero. (THIS MEANS THAT THIS CODE MUST BE
; IN THE FIRST 64KB OF MEMORY.)

.3: xor ax, ax ; Set all segments to a proper real-mode value
mov ds, ax ; (in this case zero). The unreal-mode limits
mov es, ax ; set for DS, ES, FS, and GS while in protected
mov fs, ax ; mode will not be changed.
mov gs, ax
mov ss, ax

mov dx, 0x70 ; Re-enable NMIs.
in al, dx
and al, 0x7F
out dx, al
sti ; Re-enable interrupts.
[/pre]

And here's the GDT:

[pre]
;-------------------------------------------------------------------------------
; GLOBAL DESCRIPTOR TABLE
;-------------------------------------------------------------------------------

align 8

GDT: dw gdt_limit ; null segment, used to store GDT
dd GDT ; metadata
dw 0

cseg: dd 0x0000FFFF, 0x00CF9800 ; code segment, 32-bit, 0 to 4GB
dseg: dd 0x0000FFFF, 0x00CF9200 ; data segment, 32-bit, 0 to 4GB
cs16: dd 0x0000FFFF, 0x00009800 ; code segment, 16-bit, 0 to 64KB
ds16: dd 0x0000FFFF, 0x00009200 ; data segment, 16-bit, 0 to 64KB

gdt_limit equ $-GDT-1
[/pre]
Post Reply