PE doesn't get set

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
The Pro

PE doesn't get set

Post by The Pro »

hello all,
   i am a newbie to osd. the coding,

mov   eax, cr0
or    ax, 1h
mov   cr0, eax
  

     doesn't set the pe bit. so, i could not jump to the protected mode. i'm helpless. plz, help me.

thanks in advance
HOS

RE:PE doesn't get set

Post by HOS »

your section of code looks fine, you may want to provide us with some context to help you with your problem
The Pro

RE:PE doesn't get set

Post by The Pro »

     I have provided with the GDT structure and the coding needed to set the PE bit and install GDT. I use Nasm for windows.


cli
mov eax, cr0 ;
or ax, 1 ;   Sets the PE bit
mov cr0, eax ;

xor ax, ax
mov ds, ax
lgdt [gdt_descriptor]

gdt:

null_descriptor:
    
dw 0 ; seg_length1_15
dw 0 ; base_addr0_15
db 0 ; base_addr16_23
db 0 ; dflags
db 0 ; access
db 0 ; base_addr24_31

code_descriptor:

dw 0xFFFF ; seg_length1_15
dw 0 ; base_addr0_15
db 0 ; base_addr16_23
db 0x9A ; dflags
db 0xCF ; access
db 0 ; base_addr24_31

data_descriptor:

dw 0xFFFF
dw 0
db 0
db 0x92
db 0xCF
db 0

gdt_end:

gdt_descriptor:
db gdt_end - gdt - 1
dw gdt
rexlunae

RE:PE doesn't get set

Post by rexlunae »

You set ds to segment 0 (which makes sense) but did you use org to set the base address of your code bock so that 0:gdt_descriptor and 0:gdt is actually right?  It would be helpful if you posted the entire program (bootsector?).  What do you do after "lgdt [gdt_descriptor]"?  Do you actually load new segment descriptors?
Xenos

RE:PE doesn't get set

Post by Xenos »

AFAIK, the GDT should be loaded before setting the PE bit. Everything else looks fine.
HOS

RE:PE doesn't get set

Post by HOS »

yes, the gdt needs to be loaded before switching the PE bit on. also, correct me if i am wrong but i believe you need to load the segment registers (ds included) after switching to pmode for the processor to load the correct base and limit information. the order i follow is:
-cli
-lgdt
-set PE bit
-far jump to pmode code selector
switch to bits 32 if running in a 32 bit code segment
-reload all segment registers
-...
DaveHK

RE:PE doesn't get set

Post by DaveHK »

it doesn't really matter which order you do it in, setting the PE bit CR0 activates a king of deferred pmode, the CPU does not actually switch into pmode until you perform a far jump into your 32-bit code segment
Jamethiel

RE:PE doesn't get set

Post by Jamethiel »

I've been wondering about that, actually.

What would happen if you (in real mode) set up a pmode IDT and GDT, arranged for your code segment to be something that would be valid in both pmode and real mode, set the PE bit, didn't jump, and took an interrupt?

Seriously, what would happen?

My best guess is that it would either blow up because it tried to privelidge transition without a TSS or it would actually take the interrupt and return properly.

Now I'm curious, and may actually try to set this up this weekend...

--Jamethiel
rexlunae

RE:PE doesn't get set

Post by rexlunae »

"My best guess is that it would either blow up because it tried to privelidge transition without a TSS or it would actually take the interrupt and return properly."

The TSS thing wouldn't be an issue because you would be int'ing from priv0 to priv0 code (real mode segments are all priv0), so it doesn't reference the TSS to switch stacks.

However, when an interrupt is serviced, the 16-bit visible portion is backed up on the stack, and when the iret is done it reloads CS with the stored value, which would be unlikely to be right or even valid when looked up in the [GL]DT.  Aside from the documented issues, it is also likely that in some cases the interrupt handler would not be designed to work in pmode, and as it does change the addressing substantially, I would guess that it would not work.
Jamethiel

RE:PE doesn't get set

Post by Jamethiel »

Which is why I said to load a pmode IDT and set up the real mode code segment to line up with a matching descriptor in the GDT.

It would certianly put the lie to the statement that you don't actually enter pmode until after that first jump.
rexlunae

RE:PE doesn't get set

Post by rexlunae »

You enter pmode after setting bit 0 in cr0.  Being in pmode means that whenever a segment register is loader, it is done with the [GL]DT rather then by a simple computation.  However, you need to actually load new values in the segment registers in order to see the change.

"Which is why I said to load a pmode IDT and set up the real mode code segment to line up with a matching descriptor in the GDT."

The problem with trying to set up your pmode segments as equivalent to real mode is that for each pmode segment descriptor table entry there are 8 real mode segments with distinct physical addresses.  That will be a problem if you just vector to a real mode interrupt handler which (for example) uses several contiguous segments for its operation.

I do encourage you to post any interesting results from you experimenting.
Post Reply