Page 1 of 1
pmode switch doesn't work correctly
Posted: Fri Oct 26, 2007 3:19 am
by sevobal
Hi,
I've written a real-mode OS with a console so the user can give commands to it. The bootsector of the flopp disk just loads sector 1 - 19 to the position 0X1000:0x0000 and jumps to it to execute the OS. This works perfectly. Now if the user enters 'PM' at the console the system shut switch to protected mode. But this doesn't work and I don't why. Maybe I've missed something
Here is my code:
Code: Select all
; Code is now at 0x1000x0x0000
; Here is some code of my real-mode is.
; User enters 'PM'
jmp kernel_pmode:
; Here are also some functions of my real-mode OS
; Let's try to switch
kernel_pmode:
jmp p_start
gdt:
gdt_null:
dd 0x00
dd 0x00
gdt_code:
dw 0xFFFF ; Size of 65535
dw 0x00
db 0x1000 ;Because code is at 0x1000:0x0000
db 10011010b ;segment is in memory, priority 0, executable and readable
db 11001111b ;4096 KB, 80386 segment
db 0x00
gdt_data:
dw 0xFFFF ; Size of 65535
dw 0x00
db 0x1000 ;Because code is at 0x1000:0x0000
db 10010010b ;segment is in memory, priority 0, writeable and readable
db 11001111b ;4096 KB, 80386 segment
db 0x00
gdt_end:
GDT32:
Limit dw gdt_end - gdt - 1 ;limit (size)
BaseAdr dd gdt
p_start:
lgdt [GDT32]
cli
mov eax, 000000011h
mov cr0, eax
; "FAR-JMP"
db 0eah
dw now_in_prot
dw 0x08
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 32-Bit protected mode
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
now_in_prot:
jmp $
Posted: Fri Oct 26, 2007 5:54 am
by ManOfSteel
You load it with int 13h at 0X1000:0x0000, but are you sure your above code is actually running there? What's your
org xxxx value?
For example, if you have
org 0 you would have to adjust all your memory references so they point to 0X1000:0x0000 or else you'd be running code (or even data) contained elsewhere instead of your PM code.
Also, when switching to PM without paging, you usually only have to set the PE bit on (i.e. bit 0):
And bit 4 tells you if there's a coprocessor or not.
Posted: Fri Oct 26, 2007 6:14 am
by sevobal
My bootloader has org 0x7c20, but my kernel didn't has any org xxxx. So I tried org 0x1000, but now the kernel doesn't work correctly. Any other possibilities for org xxxx or something else?
Posted: Fri Oct 26, 2007 6:33 am
by Solar
You do know what "org" does? Or are you just guessing / doing trial & error?
Posted: Fri Oct 26, 2007 6:39 am
by sevobal
org sets the start adresse of the actual segment in which org is placed. If org isn't set the program starts at 0.
I think this should be correct.
Posted: Fri Oct 26, 2007 5:48 pm
by iammisc
doesn't the limit come *after* the base address in the gdt pointer?
Posted: Fri Oct 26, 2007 6:40 pm
by Dex
And where,s the use32 or [BITS 32], just before the now_in_prot label ?.
Posted: Sat Oct 27, 2007 2:05 am
by sevobal
Okay guys here we go again:
I modified this code a little bit and now I've this one. The PC stands for about 5 seconds in pmode or trying to switch into, but then restarts again.
Code: Select all
jmp p_start
gdt:
gdt_null:
dd 0x00
dd 0x00
gdt_code:
dw 0xFFFF ; Size of 65535
dw 0x00
db 0x10 ;Because code is at 0x1000:0x0000
db 10011010b ;segment is in memory, priority 0, executable and readable
db 11001111b ;4096 KB, 80386 segment
db 0x10
gdt_data:
dw 0xFFFF ; Size of 65535
dw 0x00
db 0x10 ;Because code is at 0x1000:0x0000
db 10010010b ;segment is in memory, priority 0, writeable and readable
db 11001111b ;4096 KB, 80386 segment
db 0x00
gdt_end:
GDT32:
Limit dw 3 * 8
BaseAdr dd gdt + 0x10000
p_start:
mov ax,cs
and eax,0FFFFh
shl eax,4
add ax,p_start
mov word [gdt_code+2],ax
shr eax,16
mov byte [gdt_code+4],al
mov ax,cs
and eax,0FFFFh
shl eax,4
add ax,p_start
mov word [gdt_data+2],ax
shr eax,16
mov byte [gdt_data+4],al
lgdt [GDT32]
cli
mov eax, cr0
or al,1
mov cr0,eax
; "FAR-JMP"
db 0eah
dw now_in_prot
dw 0x08
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 32-Bit protected mode
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[BITS 32]
now_in_prot:
jmp $
Posted: Sat Oct 27, 2007 2:08 am
by ManOfSteel
@iammisc:
doesn't the limit come *after* the base address in the gdt pointer?
No, the limit is 0-15 and the base is 16-47 (or 16-79).
@sevobal:
My bootloader has org 0x7c20
0x7c20?
org sets the start adresse of the actual segment in which org is placed.
org xxxx sets the address where the rest of your code is
expected to be running, i.e. it adds xxxx to every memory reference in your code. Keep in mind it doesn't actually move anything.
Posted: Sat Oct 27, 2007 2:25 am
by sevobal
Sorry my bootloader is of course at 7c00.
I tried to debug with bochs and get this:
Code: Select all
00200832996i[CPU0 ] BxError: instruction with opcode=0xff
00200832996i[CPU0 ] mod was c0, nnn was 7, rm was 7
00200832996i[CPU0 ] WARNING: Encountered an unknown instruction (signalling illegal instruction)
00200832996i[CPU0 ] protected mode
00200832996i[CPU0 ] CS.d_b = 32 bit
00200832996i[CPU0 ] SS.d_b = 16 bit
00200832996i[CPU0 ] EFER = 0x00000000
00200832996i[CPU0 ] | RAX=0000000000000011 RBX=0000000000000001
00200832996i[CPU0 ] | RCX=0000000000000607 RDX=0000000000000e00
00200832996i[CPU0 ] | RSP=000000000000fffc RBP=0000000000000000
00200832996i[CPU0 ] | RSI=00000000ffff0849 RDI=0000000000080000
00200832996i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00200832996i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00200832996i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00200832996i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00200832996i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00200832996i[CPU0 ] | SEG selector base limit G D
00200832996i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00200832996i[CPU0 ] | CS:0008( 0001| 0| 0) 10010aac 000fffff 1 1
00200832996i[CPU0 ] | DS:1000( 0005| 0| 0) 00010000 0000ffff 0 0
00200832996i[CPU0 ] | SS:9000( 0005| 0| 0) 00090000 0000ffff 0 0
00200832996i[CPU0 ] | ES:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00200832996i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00200832996i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00200832996i[CPU0 ] | MSR_FS_BASE:0000000000000000
00200832996i[CPU0 ] | MSR_GS_BASE:0000000000000000
00200832996i[CPU0 ] | RIP=0000000000000af1 (0000000000000af1)
00200832996i[CPU0 ] | CR0=0x00000011 CR1=0x0 CR2=0x0000000000000000
00200832996i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00200832996i[CPU0 ] >> (invalid) : FFFF
00200832996e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
Could this be usefull for someone here?
Posted: Sat Oct 27, 2007 3:29 am
by os64dev
looks like the base of your CS is really wrong. why do you have a base anyway. It is way safer to just use zero. Further more you are in protected mode now so set DS en SS also to the correct value 0x10 in your case.
Posted: Sat Oct 27, 2007 4:24 am
by sevobal
I correct ds and ss:
Code: Select all
...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 32-Bit protected mode
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[BITS 32]
now_in_prot:
mov ax,0x10 ; Segmentregister laden
mov ds,ax
mov ss,ax
jmp $
But where should I correct the wrong cs? (And then why I'm not needing a base for it?)
Posted: Sat Oct 27, 2007 5:59 am
by ManOfSteel
You must add the address (10000h) to all your memory references (including "dw now_in_prot"), but this may be a problem in 16bit code so I suggest you divide all your addresses by 16 (eg: 1000h->100h, 10000h->1000h).
You indeed have to set ds and ss, but that not what's causingthe tripple fault anyway.
Posted: Sat Oct 27, 2007 6:46 am
by sevobal
At this point I would like to thank you for your patience.
Now I'm getting this:
Code: Select all
00797242979e[CPU0 ] jump_protected: call gate.p == 0
00797242979e[CPU0 ] fetch_raw_descriptor: GDT: index (f007)1e00 > limit (18)
00797242979i[CPU0 ] protected mode
00797242979i[CPU0 ] CS.d_b = 16 bit
00797242979i[CPU0 ] SS.d_b = 16 bit
00797242979i[CPU0 ] EFER = 0x00000000
00797242979i[CPU0 ] | RAX=0000000000000011 RBX=0000000000000001
00797242979i[CPU0 ] | RCX=0000000000000607 RDX=0000000000000e00
00797242979i[CPU0 ] | RSP=000000000000fffc RBP=0000000000000000
00797242979i[CPU0 ] | RSI=00000000ffff0849 RDI=0000000000080000
00797242979i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00797242979i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00797242979i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00797242979i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00797242979i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00797242979i[CPU0 ] | SEG selector base limit G D
00797242979i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00797242979i[CPU0 ] | CS:1000( 0004| 0| 0) 00010000 0000ffff 0 0
00797242979i[CPU0 ] | DS:1000( 0005| 0| 0) 00010000 0000ffff 0 0
00797242979i[CPU0 ] | SS:9000( 0005| 0| 0) 00090000 0000ffff 0 0
00797242979i[CPU0 ] | ES:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00797242979i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00797242979i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00797242979i[CPU0 ] | MSR_FS_BASE:0000000000000000
00797242979i[CPU0 ] | MSR_GS_BASE:0000000000000000
00797242979i[CPU0 ] | RIP=0000000000000aba (0000000000000aba)
00797242979i[CPU0 ] | CR0=0x00000011 CR1=0x0 CR2=0x0000000000000000
00797242979i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00797242979i[CPU0 ] >> jmp far 0008:0abf : EABF0A0800
00797242979e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
I think it's a problem with the far-jmp or is there something more?
Posted: Mon Oct 29, 2007 5:47 am
by Combuster
You have yet another org xxx related issue
Code: Select all
p_start:
mov ax,cs
and eax,0FFFFh
shl eax,4
add ax,p_start
your code is assembled to the start of the file while you try to modify the GDT to make the offset relative to some point halfway into the file.
Other than that, you get an error that you are calling a call gate, which is something not present in your GDT. That means it either got corrupted or that you are looking at something that isn't the GDT