Page 1 of 2

[SOLVED] Jumping into real from protected mode

Posted: Tue Apr 16, 2013 11:41 am
by HugeCode
Hi all. It's me with my GDT again. I met another problem when setting ES to my 16bit entry... Here is my code:

Code: Select all

; gdt real:				
	dw 0FFFFh 			; limit low
	dw 0 				; base low
	db 0 				; base middle
	db 10011010b 			; access, RW|EXE|Ring0
	db 00001111b 			; size = 0 (16bit), granularity = 0 (1B for everything in limit)
	db 0				; base high
Does anybody any idea where can be the problem? Please help.

Code: Select all

...
mov ax, 0x18
mov es, ax         ;after executing this instruction the GPF occurs

jmp es:0x8400
GPF occured
GPF occured

Re: Jumping into real from protected mode

Posted: Tue Apr 16, 2013 11:56 am
by Brendan
Hi,
HugeCode wrote:

Code: Select all

	db 10011010b 			; access, RW|EXE|Ring0
How can a segment be readable, writable and executable?

Note: This decodes as: present, DPL=0, system (not code or data), and "reserved".


Cheers,

Brendan

Re: Jumping into real from protected mode

Posted: Tue Apr 16, 2013 12:05 pm
by HugeCode
I've cleared that bit but it still isn't working.
Do I have to make two realmode descriptors? I don't think so because I'm not writing in it, after far jump I clear cr0:0 to turn pmode off and I make another far jump....
I don't think problem's there. I tried to clear executable bit and GPF still occurs.

Re: Jumping into real from protected mode

Posted: Tue Apr 16, 2013 1:15 pm
by Mikemk
HugeCode wrote:Do I have to make two realmode descriptors?.
There's no such thing as a real mode descriptor. Pmode requires 32-bit, V8086 requires 16-bit.

Also, your gpf is in the jump.

Re: Jumping into real from protected mode

Posted: Tue Apr 16, 2013 1:20 pm
by Brendan
Hi,

Doh - I got my "system" flag around the wrong way :oops:
HugeCode wrote:Do I have to make two realmode descriptors?
You can load an "executable, read-only" segment into ES, but you can't load an "executable, read-only" segment into SS, so you will need to make 2 descriptors.
HugeCode wrote:I don't think so because I'm not writing in it, after far jump I clear cr0:0 to turn pmode off and I make another far jump....
Are you sure that the "mov es, ax" causes the exception (and that the exception isn't caused by a different instruction afterwards)? If it's definitely the "mov es,ax" causing the exception then the only other thing is the GDT (e.g. dodgy GDT limit or something).

Also; I don't know which assembler you're using; and don't know what the "jmp es:0x8400" instruction is. Is it "jmp 0x8400" with an ignored segment override prefix, or is it "jmp [es:0x8400]" (near jump to the value stored at es:0x8400)? It looks like "jump to es:0x8400" but there is no such instruction.


Cheers,

Brendan

Re: Jumping into real from protected mode

Posted: Wed Apr 17, 2013 3:31 am
by HugeCode
I'm absolutely sure it's the GDT. I removed code with moving ax to es and manually wrote far jump instruction. When I come to that instruction, GPF occurs.
My jump code (gdb translates it as normal ljmp):

Code: Select all

_emit(0xEA);
_emit(0x00);   //offset
_emit(0x84);   
_emit(0x00);
_emit(0x00);
_emit(0x18);   //selector
_emit(0x00);
My newest GDT:

Code: Select all

; gdt real:				; data descriptor
dw 0FFFFh 			; limit low
dw 0 				; base low
db 0 				; base middle
db 10001000b 			; access, EXE|Ring0|Present
db 00100111b 			; granularity, size = 0 (16bit), granularity = 0 (1B for everything in limit)
db 0				; base high
BTW wiki says that:
RW: Readable bit/Writable bit.
Readable bit for code selectors: Whether read access for this segment is allowed. Write access is never allowed for code segments.
Writable bit for data selectors: Whether write access for this segment is allowed. Read access is always allowed for data segments.
So if I have RW bit set, it shouldn't be problem, will it?

EDIT: does anybody have some working code which switches OS to real mode? Maybe I can compare it with mine to see what's different.

Re: Jumping into real from protected mode

Posted: Wed Apr 17, 2013 5:14 am
by Brendan
Hi,
HugeCode wrote:I'm absolutely sure it's the GDT. I removed code with moving ax to es and manually wrote far jump instruction. When I come to that instruction, GPF occurs.
My jump code (gdb translates it as normal ljmp):

Code: Select all

_emit(0xEA);
_emit(0x00);   //offset
_emit(0x84);   
_emit(0x00);
_emit(0x00);
_emit(0x18);   //selector
_emit(0x00);
At least that answers one of my questions - the original jump was meant to be "jmp far 0x0018:0x8400" (assuming NASM - still don't know which assembler).
HugeCode wrote:My newest GDT:

Code: Select all

; gdt real:				; data descriptor
dw 0FFFFh 			; limit low
dw 0 				; base low
db 0 				; base middle
db 10001000b 			; access, EXE|Ring0|Present
db 00100111b 			; granularity, size = 0 (16bit), granularity = 0 (1B for everything in limit)
db 0				; base high
You're making random guesses and screwing things up more (this is worse than the original code). Sooner or later you'll realise it's easier to read the relevant part of the Intel manual.. ;)
HugeCode wrote:BTW wiki says that:
RW: Readable bit/Writable bit.
Readable bit for code selectors: Whether read access for this segment is allowed. Write access is never allowed for code segments.
Writable bit for data selectors: Whether write access for this segment is allowed. Read access is always allowed for data segments.
So if I have RW bit set, it shouldn't be problem, will it?
It also says that Bit 11 (the "Ex" bit) determines if the descriptor is executable (where the "RW" bit is actually a "readable or not readable" bit) or if the descriptor is data (where there RW bit is actually a "read only or read write" bit).

Basically:

Code: Select all

Ex RW
0  0 = read only data
0  1 = read/write data
1  0 = execute only
1  1 = execute/read
HugeCode wrote:EDIT: does anybody have some working code which switches OS to real mode? Maybe I can compare it with mine to see what's different.
Did you search the wiki?


Cheers,

Brendan

Re: Jumping into real from protected mode

Posted: Wed Apr 17, 2013 5:23 am
by HugeCode
Yes, I was following that tutorial. There isn't any GDT example....
BTW what's wrong with my GDT now? To make this descriptor I used osdev wiki.

Re: Jumping into real from protected mode

Posted: Wed Apr 17, 2013 6:58 am
by Mikemk
BTW, the table in the wiki is confusing, and nasm moves your stuff around anyway due to endianness. If you have windows 7/8, the programming calculator is an excellent tool for calculating GDTs (how ironic)

It'll be the first thing I produce in my OS.

Re: Jumping into real from protected mode

Posted: Wed Apr 17, 2013 7:32 am
by HugeCode
It's disease! Not GDT error. It looks like I don't have right to change segment registers... :?: :?: :?: :?: :?: :?:
Screenshot_1.png
Screenshot_1.png (11.4 KiB) Viewed 3013 times

Re: Jumping into real from protected mode

Posted: Wed Apr 17, 2013 8:20 am
by Combuster
It's disease!
In your brain, possibly. But again I only see "I think"'s rather than meaningful information. So you're getting a GPF and you're probably not even printing it correctly. What does that help us?

Learn to debug.

Re: Jumping into real from protected mode

Posted: Wed Apr 17, 2013 9:51 am
by HugeCode
I've debugged it with VMWare. It still occurs on the mov.

Re: Jumping into real from protected mode

Posted: Wed Apr 17, 2013 10:25 am
by HugeCode
Ok. I found out that the 0x10 as a selector works, but the descriptor doesn't.
I also tried to use usermode descriptor:

Code: Select all

; gdt data:				; data descriptor
dw 0FFFFh 			; limit low (Same as code)
dw 0 				; base low
db 0 				; base middle
db 11110010b 			; access
db 11001111b 			; granularity
db 0				; base high
This doesn't work either. Can you see any problem in it?

Re: Jumping into real from protected mode

Posted: Wed Apr 17, 2013 11:38 am
by Mikemk
HugeCode wrote:I also tried to use usermode descriptor:
You are still making random guesses. PS, VMWare doesn't have debugging capabilities, at least mine doesn't.
Let me ask you this:
Does it make any sense whatsoever to use a ring 3 descriptor for ring 0? If not, why even try?

Here's some hints. Hopefully, you'll use them to find your answer.
  1. The bit number x means, 2^x = value in bit x
  2. NASM knows that intel is little endian. Bit fields are typically big endian (I mixed big and little up, didn't I?)
  3. I recommend storing it as a single 64-bit hexadecimal number, that way NASM doesn't mess it up.

Re: Jumping into real from protected mode

Posted: Wed Apr 17, 2013 11:44 am
by DavidCooper
What are you actually trying to do? Are you trying to use real mode in protected mode; are you trying to use 16-bit protected mode (in addition to 32-bit protected mode); are you trying to set up unreal mode; or what?

In your older GDT thread you set up two descriptors for using 32-bit protected mode and you eventually got that to work. It should be a simple step from there to work out how to set up two descriptors for 16-bit protected mode and to jump into it in the normal way.

(You may be able to manage with just one descriptor depending on what you're trying to do - e.g. you might only be going through 16-bit protected mode as a momentary step on the way back into real mode, but you'd avoid loading data segment registers altogether.)