Page 1 of 1

Unreal mode triggering exception?

Posted: Sun Jul 03, 2005 12:58 pm
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

Re:Unreal mode triggering exception?

Posted: Sun Jul 03, 2005 1:39 pm
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?

Re:Unreal mode triggering exception?

Posted: Sun Jul 03, 2005 6:49 pm
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?

Re:Unreal mode triggering exception?

Posted: Sun Jul 03, 2005 9:36 pm
by AR
You're loading an invalid segment. You're trying to load 0x8 into DS, 0x8 is your code segment, try 0x10.

Re:Unreal mode triggering exception?

Posted: Mon Jul 04, 2005 1:23 am
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

Re:Unreal mode triggering exception?

Posted: Mon Jul 04, 2005 1:50 am
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