Unreal mode triggering exception?

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
Jubbens

Unreal mode triggering exception?

Post by Jubbens »

When I try to get into unreal mode, bochs returns this error

load_seg_reg(): not data or readable code
exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting

and it reboots. Apparently it's a segment overrun? Here's the offending code:

Code: Select all

; Move to unreal mode
cli
mov al,0xD1 ; Turn on A20 line
out 0x64,al
mov al,0x03
out 0x60,al
push ds       ; Save real mode data segment
lgdt [GDT]    ; Load GDT
mov eax,cr0 ; Jump to protected mode
inc ax
mov cr0,eax
mov bx,0x08 ; Select the first descriptor in GDT
mov ds,bx
dec ax          ; Get back to real mode
mov cr0,eax
pop ds
sti

GDT:
dw .point
dd GDT
dw 0
.cseg: dd 0x0000FFFF,0x00CF9800
.dseg: dd 0x0000FFFF,0x00CF9200
.cs16: dd 0x0000FFFF,0x00009800
.ds16: dd 0x0000FFFF,0x00009200
.point: gdt_limit equ $-GDT-1
AR

Re:Unreal mode triggering exception?

Post by AR »

Is that posted as is? Where's your end of program loop/hlt to stop the CPU from executing the GDT then continuing on to hit the end of the segment?
Jubbens

Re:Unreal mode triggering exception?

Post by Jubbens »

Ya, there's a halt at the end. And I know all the other code works. This was pretty much off the top of my head though, so are you sure this code is correct?
AR

Re:Unreal mode triggering exception?

Post by AR »

You're loading an invalid segment. You're trying to load 0x8 into DS, 0x8 is your code segment, try 0x10.
pini

Re:Unreal mode triggering exception?

Post by pini »

That's right, 0x8 is your code segment, while 0x10 is your data one.

I'd do something like this instead :
1) set DS to 0x10 (you can also set ES, FS and GS)
2) set bit for pmode in CR0
3) do a far jump to load CS, example :

Code: Select all

mov eax,cr0 ; Jump to protected mode
or eax,0x1
mov cr0,eax
jmp 0x8:pmode
pmode:
I think this has also something to deal with flushing the prefetch queue (the jmp, I mean) but I'm not sure if this is relevant here or not.

To go back to real mode, I would clear the bit and CR0 and do another far jump to reload CS with the correct value

And btw, I would use "dd 0x0,0x0" instead of
dw .point
dd GDT
dw 0x0

and make the GDT start at this to be sure you have a really null selector at 0x0
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Unreal mode triggering exception?

Post by Pype.Clicker »

iirc, the 'long jump' and even the code segment are not mandatory when enabling unreal mode: you'll have to keep a 16 bits code segment for unreal mode whatever you like it or not (e.g. only lower part of IP is used)

As long as you don't turn to a new code segment, the CPU continues interpreting instructions as if they were from a 16bits code segment, which is simply fine for what we have to do:

Code: Select all

;; from BabyStep 7
   cli      ; no interrupt
   push ds      ; save real mode

   lgdt [gdtinfo]   ; load gdt register

   mov  eax, cr0   ; switch to pmode by
   or al,1         ; set pmode bit
   mov  cr0, eax

   mov  bx, 0x08   ; select descriptor 1
   mov  ds, bx   ; 8h = 1000b

   and al,0xFE     ; back to realmode
   mov  cr0, eax   ; by toggling bit again

   pop ds      ; get back old segment
   sti

Post Reply