Page 1 of 2
I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 2:52 pm
by ThatGuy2244
I have tried to switch to 32-bit protected mode by setting up my GDT:
Code: Select all
GDTStart:
dd 0x00000000 ;Descriptor 0 Null
dd 0x00000000
dw 0xffff ;Descriptor 1 Code
dw 0x0000
db 0x00
db 10011010b
db 11001111b
db 0x00
dw 0xffff ;Descriptor 2 Data
dw 0x0000
db 0x00
db 10010010b
db 11001111b
db 0x00
GDTEnd:
and then setting up GTDInfo:
Code: Select all
GDTInfo:
dw GDTEnd - GDTStart - 1
dd GDTStart
Then switching to pmode:
Code: Select all
lgdt [GDTInfo]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x08:pmode
My entire code is:
Code: Select all
[BITS 16]
org 0x100 ;this is a .COM file
lgdt [GDTInfo]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x08:pmode
GDTInfo:
dw GDTEnd - GDTStart - 1
dd GDTStart
GDTStart:
dd 0x00000000 ;Descriptor 0 Null
dd 0x00000000
dw 0xffff ;Descriptor 1 Code
dw 0x0000
db 0x00
db 10011010b
db 11001111b
db 0x00
dw 0xffff ;Descriptor 2 Data
dw 0x0000
db 0x00
db 10010010b
db 11001111b
db 0x00
GDTEnd:
[BITS 32]
pmode:
This code every time I run it in DOSbox it gives me the error "JMP to Illegal Descriptor type 0" and then crashes. I have tried many things to try to get it to work be with no successes, any ideas on what could be wrong?
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 2:57 pm
by Combuster
dd GDTStart
That is a virtual address, not a 32-bit linear address as required. You still need to add segment * 16 to it before it points to the right location
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 4:13 pm
by ThatGuy2244
I tried writing it as seg:offset but it got an error when I tried to assemble it.
Code: Select all
GDTInfo:
dw GDTEnd - GDTStart - 1
dd 0x00:GDTStart
I think it has something to do with the way I formatted it -- I don't know how to format a seg:offset in memory I assume it is something like when I use it in an instruction "mov [
es:si], al".
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 4:33 pm
by miker00lz
granted, i havent really done any 32-bit assembly (not much anyway, i've dicked around with a lot of 16-bit assembly on ancient machines) but shouldnt you do:
or something similar?
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 5:39 pm
by Owen
ThatGuy2244 wrote:I tried writing it as seg:offset but it got an error when I tried to assemble it.
Code: Select all
GDTInfo:
dw GDTEnd - GDTStart - 1
dd 0x00:GDTStart
I think it has something to do with the way I formatted it -- I don't know how to format a seg:offset in memory I assume it is something like when I use it in an instruction "mov [
es:si], al".
You write seg:off addresses as
Regardless, the information you place in the GDTR is a
linear address, not a segment address
Because you're writing a DOS COM file, you don't know what your segment is at link time... therefore, its your job to work that out.
And just to check: The DOS you're running this under needs to be vary plain. EMS, XMS, VCPI or DCPI servers are likely to prevent you from switching to protected mode this way.
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 5:57 pm
by gerryg400
The DOS you're running this under needs to be vary plain. EMS, XMS, VCPI or DCPI servers are likely to prevent you from switching to protected mode this way.
You should be able to boot and run a protected mode kernel using XMS. Just use XMS services to allocate and lock all the memory above 1M and use it. If you're very careful you ought to be able to free the memory and return to DOS when you're done without rebooting.
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 6:27 pm
by ThatGuy2244
I have tried to do the formatting of the seg:off as "dw GDTStart, 0x00"and it still didn't work and gave me the same error. So what should I do to make it work?
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 6:37 pm
by gerryg400
I dunno much about assembler or com files but I think you'll need to read a segment register to find out where your program has been loaded. Then as Combuster said, calculate the linear address to give to LGDT. I don't think your assembler will know the segment value.
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 7:01 pm
by ThatGuy2244
gerryg400 wrote:I dunno much about assembler or com files but I think you'll need to read a segment register to find out where your program has been loaded. Then as Combuster said, calculate the linear address to give to LGDT. I don't think your assembler will know the segment value.
Well I do know were the program is loaded and then told the assembler were it will be loaded so it should work, that's what the "org 0x100" is for, it tells the assembler (nasm) that the program will be loaded at the linear address 0x100. I know this is correct because I have done different programs with this, as a .COM files, and they have all worked.
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 7:04 pm
by gerryg400
So does that mean that your CS and DS registers both contain 0 while you are in real mode ? If they are not 0 (and I suspect that they are not) then your code will not work.
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 7:28 pm
by ThatGuy2244
gerryg400 wrote:So does that mean that your CS and DS registers both contain 0 while you are in real mode ? If they are not 0 (and I suspect that they are not) then your code will not work.
Well they are what ever DOS sets them to by default which I assume is 0, but all I know is, that my program is loaded to 0x100 and when I use that as the base address my code works.
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 7:47 pm
by gerryg400
My apologies. If your code is working add "[Solved]" to the subject line of the thread and we can consider the thread closed.
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 9:08 pm
by Owen
COM files are loaded with whatever segment DOS chooses for them. That segment will never be zero.
The ORG directive gives a virtual, not linear address. When doing OS development you would be wise to learn the distinction
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 10:58 pm
by Chandra
Hi,
Then switching to pmode:
Code: Select all
Code:
lgdt [GDTInfo]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x08:pmode
All references to the memory locations are made via
ds:offset so, just set the data segment to 0 before you execute the
lgdt instruction and that should work(IMO).
Re: I can't switch to 32-bit protected mode.
Posted: Sun Jun 19, 2011 11:14 pm
by gerryg400
The solution is, as Combuter posted just 5 minutes after the question was asked and that Owen clarified shortly after, this ....
Code: Select all
GDTInfo:
dw GDTEnd - GDTStart - 1
dd GDTStart ; <<===== This should be a linear address calculated at RUNTIME equal to GDTStart + (DS << 4) NOT a segment relative value
It's very frustrating that the answer when given was simply ignored.
[Edit] Changed (DS >>4) to (DS << 4)