Page 1 of 1
Am I in protected mode yet?
Posted: Thu Jul 07, 2011 1:49 pm
by rspencer
Hi,
I am fairly new to the level of programming required for osdev and was wondering if I am missing something stupid in the following problem:
I am following many different tutorials and am always getting stuck at one point: protected mode.
My code currently reads as follows (an extract):
Code: Select all
cli
mov al, 2 ; set bit 2 (enable a20)
out 0x92, al
call InstallGDT
jmp 0x1000 : Stage3
Stage3:
mov eax, cr0 ; set bit 0 in CR0-go to pmode
or eax, 1
mov cr0, eax
hlt
This runs fine on Bochs. However I am wondering about the following:
1) That jump statement. I am told by numerous sources that it should be jmp 0x08 for my GDT and ds. However implementing this results in a triple fault. (I am loaded at 0x10000)
2) The order of my commands. Should I be jumping before setting cr0 or after? Jumping after gave a fault. Also, when should I enable A20?
3) Am I actually in pmode by the hlt statement???
I understand if you get impatient with my questions which may have obvious solutions but I have trawled the web and consulted tutorials 'till I was blue in the face. Everything they suggested ran into triple faults when I ran it. This suggests another alternative. Is there anything I need to know about setting up bochs that may help?
Any help would be much appreciated.
Thanks.
Re: Am I in protected mode yet?
Posted: Thu Jul 07, 2011 1:56 pm
by AJ
Hi and Welcome,
rspencer wrote:1) That jump statement. I am told by numerous sources that it should be jmp 0x08 for my GDT and ds. However implementing this results in a triple fault. (I am loaded at 0x10000)
This is because of:
rspencer wrote:2) The order of my commands. Should I be jumping before setting cr0 or after? Jumping after gave a fault. Also, when should I enable A20?
You need to set the protected mode bit
before the jump. You have not entered PMode until you have jumped, as it's the far jump that makes CS point to a GDT offset rather than a real mode segment.
3) Am I actually in pmode by the hlt statement???
No
You should then be able to load the various segment registers and hlt with no triple fault (provided you don't re-enable interrupts until you have loaded a valid PMode IDT.
Cheers,
Adam
[edit: BTW, enable A20 before going to PMode - on computers that still pay any attention to A20, you will otherwise find that you can only access alternate megabyte ranges of memory otherwise]
Re: Am I in protected mode yet?
Posted: Thu Jul 07, 2011 1:59 pm
by rspencer
Ok, my code now reads:
Code: Select all
cli
mov al, 2 ; set bit 2 (enable a20)
out 0x92, al
call InstallGDT
mov eax, cr0 ; set bit 0 in CR0-go to pmode
or eax, 1
mov cr0, eax
jmp 0x8: Stage3
Stage3:
hlt
But this too triple faults
. (The same story if I say jmp 0x1000: Stage3)
Re: Am I in protected mode yet?
Posted: Thu Jul 07, 2011 2:06 pm
by xenos
Could you post the code in InstallGDT and the contents of your GDT?
Re: Am I in protected mode yet?
Posted: Thu Jul 07, 2011 2:08 pm
by rspencer
My whole code is:
Code: Select all
[org 0x0000]
[bits 16]
mov si,letter
call ptstr
mov ax,0x0E61
int 10h
;
mov ax,0x0E62
int 10h
cli
mov al, 2 ; set bit 2 (enable a20)
out 0x92, al
call InstallGDT
mov eax, cr0 ; set bit 0 in CR0-go to pmode
or eax, 1
mov cr0, eax
jmp 0x8: Stage3
Stage3:
hlt
mov ax, 0x10 ; set data segments to data selector (0x10)
mov ds, ax
mov ss, ax
mov es, ax
mov esp, 90000h
;---------------------------------------------------------------------------------
ptstr: ; Prints a null terminated string, starting at [es:si]
pusha
.go:
lodsb ; Load Byte
or al, al ; Compare to 0
jz .rt ; If null, return
mov ah,0x0E
int 0x10
jmp .go
.rt:
popa
ret ; Return
InstallGDT:
cli ; clear interrupts
mov ax,0x00
mov ds,ax
lgdt [toc] ; load GDT into GDTR
; enable interrupts
ret ; All done!
;*******************************************
; Global Descriptor Table (GDT)
;*******************************************
gdt_data:
dd 0 ; null descriptor
dd 0
; gdt code: ; code descriptor
dw 0FFFFh ; limit low
dw 0 ; base low
db 0 ; base middle
db 10011010b ; access
db 11001111b ; granularity
db 0 ; base high
; gdt data: ; data descriptor
dw 0FFFFh ; limit low (Same as code)
dw 0 ; base low
db 0 ; base middle
db 10010010b ; access
db 11001111b ; granularity
db 0 ; base high
end_of_gdt:
toc:
dw end_of_gdt - gdt_data - 1 ; limit (Size of GDT)
dd gdt_data ; base of GDT
letter db 13,10,'Welcome',13,10,0
[edit: some of the code after the hlt is redundant]
Re: Am I in protected mode yet?
Posted: Thu Jul 07, 2011 2:39 pm
by DavidCooper
rspencer wrote:Code: Select all
[org 0x0000]
[bits 16]
mov si,letter
call ptstr
mov ax,0x0E61
int 10h
;
mov ax,0x0E62
int 10h
Please comment your code properly. It looks as if it prints "Welcome" to the screen, followed by "ab" on the line below, but you should say so. Should I take it that the "a" and "b" are appearing for a moment before the crash, or does it happen to quickly for you to tell?
Code: Select all
cli
mov al, 2 ; set bit 2 (enable a20)
out 0x92, al
That's the fast way to enable the A20, but it doesn't work on all machines. I don't know if it can cause a crash if you do that on a machine that doesn't support it, but you can find out by printing to the screen again afterwards, just so long as you follow that with a delay loop big enough to show it up before a following crash.
Your GDT looks fine, but I'm not an assembler programmer and can't tell if you're loading it correctly - I'd need to see the raw machine code, but I'm sure someone else will tell you if there's something wrong with it.
Re: Am I in protected mode yet?
Posted: Thu Jul 07, 2011 3:48 pm
by Velko
I highly doubt, your code is actually loaded at address 0, but you are assuming so
Code: Select all
[org 0x0000]
.
.
InstallGDT:
cli ; clear interrupts
mov ax,0x00
mov ds,ax
lgdt [toc] ; load GDT into GDTR
If your
ptstr works, you need not to modify DS at all. If not - load your DS register with value of CS.
Also, your GDT pointer is wrong:
Code: Select all
toc:
dw end_of_gdt - gdt_data - 1 ; limit (Size of GDT)
dd gdt_data ; base of GDT
Value of base should contain linear (not segment-relative) address to gdt_data. You may want to calculate linear address at runtime and then put it there.
Re: Am I in protected mode yet?
Posted: Thu Jul 07, 2011 5:08 pm
by Combuster
The same problem goes again for the jump in protected mode: The start of the file has been given address 0. Stage3 becomes relative to the start of the file, and not relative to the start of actual memory.
3) Am I actually in pmode by the hlt statement???
No
Actually, you are in 16-bit protected mode. Protected mode makes that all segments are treated as indexes into the GDT (hence, you need 0x8 for the jump instead of 0). You are not however in the mode most people mean when they say "protected mode", which implies 32-bit mode and requires some more setup after setting "protected mode enable" in CR0.
Re: Am I in protected mode yet?
Posted: Fri Jul 08, 2011 4:24 am
by rspencer
Thank you one and all for your comments and suggestions.
However, I am still having trouble, having fixed all the problems you mentioned.
My code reads as follows (I changed a lot):
Code: Select all
[org 0x500] ;I KNOW I am loaded at 0x500 (bootloader
;put me there)
[bits 16]
st: ;Program start
push cs ;Set up ds to cs
pop ds
mov si,letter-st ;Print out the welcome message
call ptstr
cli ;Clear interrupts to be alone
mov al, 2 ; set bit 2 (enable a20)
out 0x92, al
mov ax,0x0E62 ;Print letter 'b' to test no crash at a20
int 10h
LGDT [toc] ;Load our GDT
mov eax, cr0 ; set bit 0 in CR0-go to pmode
or eax, 1
mov cr0, eax
jmp 0x8: Stage3 ;Jump to set up
Stage3:
[bits 32]
hlt
[bits 16] ;Get back into 16 bits for the rest of
;the funtions
;---------------------------------------------------------------------------------
ptstr: ; Prints a null terminated string, starting at [es:si]
pusha
.go:
lodsb ; Load Byte
or al, al ; Compare to 0
jz .rt ; If null, return
mov ah,0x0E ; Print
int 0x10
jmp .go
.rt:
popa
ret ; Return
;*******************************************
; Global Descriptor Table (GDT)
;*******************************************
gdt_data:
dd 0 ; null descriptor
dd 0
; gdt code: ; code descriptor
dw 0FFFFh ; limit low
dw 0 ; base low
db 0 ; base middle
db 10011010b ; access
db 11001111b ; granularity
db 0 ; base high
; gdt data: ; data descriptor
dw 0FFFFh ; limit low (Same as code)
dw 0 ; base low
db 0 ; base middle
db 10010010b ; access
db 11001111b ; granularity
db 0 ; base high
end_of_gdt:
toc:
dw end_of_gdt-gdt_data-1 ; limit (Size of GDT)
Pointer:
dd gdt_data ; base of GDT The Org command sets it correctly
letter db 13,10,'Welcome',13,10,0
I know that I am loaded at 0x500, so the gdt pointer should be right shouldn't it? I checked the machine code and it looks correct: 5d 05 (should it be least sig. first?). Thus I don't think it is the gdt that is giving the error. I do see the letter 'b' before it crashes, so it is not the A20 and I have narrowed it down (again) to that jmp.
As far as I can see, the jmp should work as the ord at the top should add 0x500 to Stage3 so once again I am at a bit of a loss.
Re: Am I in protected mode yet?
Posted: Fri Jul 08, 2011 4:50 am
by Combuster
The only undocumented thing is that your code still assumes CS=DS=0, which means your bootloader must end with a jmp far 0x0000:0x0500. I tested the code based on that assumption and the switch to protected mode worked for me, which means your code probably does something different.
I did find some other issues though:
ES undefined
Code: Select all
mov si,letter-st ;Print out the welcome message
Why changing the offset relative to CS into the offset relative to the start of the file? The org directive also takes care of this address.
With regards to the original issue, please post your bootloader if above comments do not fix the problem.
Re: Am I in protected mode yet?
Posted: Fri Jul 08, 2011 5:56 am
by rspencer
Ah, thank you.
It turned out that a combination of defining ES and changing my last line of the bootloader from:
to
got rid of the problem (slap on wrist for messing up that jump).
Thanks again all for your comments and suggestions.
Re: Am I in protected mode yet?
Posted: Sat Jul 09, 2011 6:13 am
by DLBuunk
Erm, i suppose you mean:
As you are executing the IVT right now...
Re: Am I in protected mode yet?
Posted: Sat Jul 09, 2011 10:16 am
by rspencer
Yes, my mistake. Sorry.