can't re-enter realmode

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.
ich_will

can't re-enter realmode

Post by ich_will »

I try to re-enter realmode so I can shutdown my PC (Power Off), but the cpu triple faults

Code: Select all

__shutdown:
   cli           ; disable interrupts

   ;------ clear the PG bit ------
   mov eax, cr0
   xor eax, 0x80000000
   mov cr0, eax

   ;------ clear the paging cache ------
   xor eax, eax
   mov cr3, eax

   ;------ do a far jump to a 16-bit code segment ------
   jmp dword real_mode
[BITS 16]
    real_mode:
   ;------ clear the PE bit ------   
   mov eax, cr0
   xor eax, 1
   mov cr0, eax

   ;------ do a far jump ------
   jmp dword real2
    real2:
   hlt ; halts the CPU later it will really shutdown
   jmp real2
pini

Re:can't re-enter realmode

Post by pini »

You must clear the PM bit (bit 0 of cr0) to go back from protected mode.
Maybe you should use a "and" bitmask rather than a "xor", to ensure the bits are correctly cleared
ich_will

Re:can't re-enter realmode

Post by ich_will »

you mean the PE (protection enable) bit of cr0, see Intel Manuel 4.1.3, i do it
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:can't re-enter realmode

Post by Candy »

ich_will wrote: you mean the PE (protection enable) bit of cr0, see Intel Manuel 4.1.3, i do it
clear it before the jump not after, and probably apply a segment prefix (realmode segment) and a 16-bit offset, not a 32-bit offset.
ich_will

Re:can't re-enter realmode

Post by ich_will »

I clear it now before the jump and it seems to work.
I know its a stupid question but do you mean with:
and probably apply a segment prefix (realmode segment) and a 16-bit offset, not a 32-bit offset.
the jump introduction have to look like this:
jmp seg:offset ???????

But what should I write in seg and what in offset. I think I have to have an 16 Bit entry in the GDT or.
tom1000000

Re:can't re-enter realmode

Post by tom1000000 »

Hello,


I hate to say this but it seems you are doing it all wrong.


I have written code that returns to real mode. IIRC this is what I did:

1) Setup a 16 bit protected mode code descriptor in your GDT, and ensure the page is identity mapped. You may also need a 16 bit data descriptor, I can't remember

2) Jump to 16 bit protected mode using a far jump
3) Turn off paging (reload CR3 to flush pages then clear PG bit)
4) Turn off protected mode (clear PE bit)
5) Far jump to 16 bit real mode code
6) Set DS etc

Also it is described in the Intel manuals how to return to real mode. Go read them.

Tom
ich_will

Re:can't re-enter realmode

Post by ich_will »

i read it but it doesn't work, see the code at the top of that thread, it makes the things in steps like the intel manuel describes, without setting up stack etc.

1. How can I setup a GDT entry while I'm in pmode? For example if the bootloader which load my kernel don't do this.

2. I think I do a far jump (jmp 'dword' ...) or ??? If I write jmp far ... nasm outs: "error: a.out format does not support segment base references"

3. The intel manuel says: clear PG bit of cr0 than clear cr3

4. I do

5. see 2.
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:can't re-enter realmode

Post by Pype.Clicker »

you're not doing a far jump: just a long jump ...
You should try harder to have the far jump encoded by NASM, (should be jmp far SELECTOR:dword offset)
ich_will

Re:can't re-enter realmode

Post by ich_will »

Ok, but how can I setup a GDT entry while I'm in pmode? Or what should I do (f.e. if I don't know the GDT set up by the bootloader)?
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:can't re-enter realmode

Post by Pype.Clicker »

the GDT setup process is exactly the same when you're in rmode or pmode: fill your GDT, write its *linear* address and size in a chunk of memory that you'll load with LDGT [...]
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:can't re-enter realmode

Post by Candy »

short comment on the short-sightedness of some people in this thread, you don't need a new GDT entry. The point of making a new 16-bit segment, jumping to that, and then continuing with going to realmode in that segment is that you don't have to worry about prefixing properly. The point is, you should *always* prefix properly. Just like you can jump from 16-bit realmode to 32-bit protected mode (which even Intel and AMD don't seem to understand), you can jump from 32-bit protected mode back to 16-bit realmode. Just make sure you do a 66 EA <offset> <segment> and nothing else. Note also both the offset and segment are 16-bit.

If you like that more, you can always opt for the 16-bit code. If you want to be /REALLY/ sure you don't mess up, try taking the 512th GDT entry for the 16-bit code and identity-map it to 0x10000. This way, even the segments remain the same (of course, the hidden parts don't, so you need a reload anyway).
ich_will

Re:can't re-enter realmode

Post by ich_will »

1. What do you mean with "66 EA <offset> <segment>"?

2. If I understood all right, I only have to jump to an 16 Bit
codesegment like:

Code: Select all

.
.
.
jmp real_mode
[Bits 16]
real_mode

How can I set the cs register to 16 Bit? If I only jump the cs register is still 32 bit. And it have to be 16 if I want use interrupts. And what else should I do?
DennisCGc

Re:can't re-enter realmode

Post by DennisCGc »

1. What do you mean with "66 EA <offset> <segment>"?
Jmp dword segment:offset
when in real mode
And when in pmode:
Jmp word segment:offset
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:can't re-enter realmode

Post by Candy »

ich_will wrote: 1. What do you mean with "66 EA <offset> <segment>"?
That the jump, after being assembled, should look like 0110011011101010xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyy as a bit pattern, or 66EAxxxxyyyy as nibble pattern. xxxx == offset, yyyy == segment. At the moment it probably assembles to 11101001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (E9xxxxxxxx)which makes for an in-segment jump. One that doesn't change the bit size for instance.
2. If I understood all right, I only have to jump to an 16 Bit
codesegment like:

Code: Select all

.
.
.
jmp real_mode
[Bits 16]
real_mode

How can I set the cs register to 16 Bit? If I only jump the cs register is still 32 bit. And it have to be 16 if I want use interrupts. And what else should I do?
The CS register is 16-bits all the time. The descriptor loaded in the CS register is always 64-bits. The segment pointed to by the descriptor loaded in the CS register can be 32 or 16 bits (or 64-bits on amd64). By reloading the CS register, and you do that by jumping with a far jump (encoded as EA), which in the case of a jump to a 16-bit segment should be prefixed with 66, and in the case of a jump to a 32-bit segment should be prefixed with 66, and must be prefixed with 66 if you want to jump beyond 0xFFFF.
ich_will

Re:can't re-enter realmode

Post by ich_will »

i think this is nearly correct:

Code: Select all

__shutdown:
   cli            ; disable interrupts

   ;------ clear the PG bit ------
   mov eax, cr0
   xor eax, 0x80000000
   mov cr0, eax

   ;------ clear the paging cache ------
   xor eax, eax
   mov cr3, eax

   ;------ clear the PE bit ------   
   mov eax, cr0
   xor eax, 1
   mov cr0, eax

   ;------ do a far jump to a 16-bit code segment ------
   jmp word real_mode ;<---- something incorrect
[BITS 16]
    real_mode:
   hlt
please send me the correct line! :'( :-\
and please don't write

jmp word segment:offset

or

jmp word segment:real_mode

no! please help me. I make a pause, by me at home its 20:00pm. I read all the posts tomorrow and hop that i can correct it. :( ??? :P :-\ :'(
Post Reply