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.
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 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?
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
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
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".
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:
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".
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.
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.
If a trainstation is where trains stop, what is a workstation ?
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?
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.
If a trainstation is where trains stop, what is a workstation ?
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.
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.
If a trainstation is where trains stop, what is a workstation ?
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.
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).
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
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)
Last edited by gerryg400 on Mon Jun 20, 2011 12:10 am, edited 2 times in total.
If a trainstation is where trains stop, what is a workstation ?