Page 1 of 2

LGDT crashing bootloader

Posted: Sun Nov 30, 2008 1:38 pm
by mrnoob
hi, im having a really annoying problem with getting into protected mode and its been bugging (no pun intended) and delaying my OS development for weeks, and i cant find the problem. everything is fine in my bootloader until it executes lgdt, at which point it triple faults. I cant see anything wrong with the code, maybe someone else can?

[edit] it is compiled with as86, my ld86 instruction includes "-T 0x7c00
Thanks a lot, the bootloader code is as follows:

Code: Select all

entry start
start:
	cli
	call enableA20
	mov ax, #0x0600
	mov bh, #0x0F
	mov cx, #0
	mov dh, #25
	mov dl, #80
	int 0x10
	lgdt[gdtr]
	mov eax, cr0
	or al, 1
	mov cr0, eax
	jmp cleareip
cleareip:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

enableA20:
	call    a20wait
	mov     al,#0xAD
	out     #0x64,al
	call    a20wait
	mov     al,#0xD0
	out     #0x64,al
	call    a20wait2
	in      al,#0x60
	push    eax
	call    a20wait
	mov     al,#0xD1
	out     #0x64,al
	call    a20wait
	pop     eax
	or      al,2
	out     #0x60,al
	call    a20wait
	mov     al,#0xAE
	out     #0x64,al
	call    a20wait
	ret
a20wait:
	in      al,#0x64
	test    al,#2
	jnz     a20wait
	ret
a20wait2:
	in      al,#0x64
	test    al,#1
	jz      a20wait2
	ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

gdtr:
	.word gdtend-gdt-1
	.long gdt

gdt:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

nullsel equ *-gdt
.word 0x0000
.word 0x0000
.word 0x0000
.word 0x0000
kcode equ *-gdt
.word 0xFFFF	;limit 0-15
.word 0x0000	;base 0-15
.byte 0x00	;base 16-23
.byte 0x9A	;options
.byte 0xC0	;flags and limit set to 256MB
.byte 0x00	;base set to 0
kdata equ *-gdt
.word 0xFFFF	;limit 0-15
.word 0x0000	;base 0-15
.byte 0x00	;base 16-23
.byte 0x92	;options
.byte 0xC0	;flags and limit set to 256MB
.byte 0x00	;base set to 0
gdtend:

Re: LGDT crashing bootloader

Posted: Sun Nov 30, 2008 1:41 pm
by 01000101
You need to setup your segment registers.

normally when you reference memory in ASM, it turns into "ds:[memory_address]", so if ds is 0x1234, then you will be referencing unintended memory.

I'd set up your DS,ES (at least) registers and setup a stack as well before installing a GDT.

Re: LGDT crashing bootloader

Posted: Sun Nov 30, 2008 1:49 pm
by mrnoob
i cant believe i didn't notice that >.>

OK ive now set those up, ill leave setting up the stack til im in protected mode i think.
Thanks!

Re: LGDT crashing bootloader

Posted: Sun Nov 30, 2008 1:51 pm
by 01000101
mrnoob wrote: OK ive now set those up, ill leave setting up the stack til im in protected mode i think.
Thanks!
Then be sure to not use "call" or "push/pop" or anything else that uses the stack as it could either A: trash good memory, or B: get overwritten while on the 'stack' and pop'd incorrectly.

I'd set up a stack, it takes 2 lines of code.

Re: LGDT crashing bootloader

Posted: Sun Nov 30, 2008 1:53 pm
by mrnoob
lol ok, im so used to writing ASM in a linux environment that i expect it all set up already. Duh.

How do you stop the stack from overflowing the code though? i dont want to get further into the development only to realise that my code is now in stack space.

Re: LGDT crashing bootloader

Posted: Sun Nov 30, 2008 2:07 pm
by 01000101
place it below your kernel or bootloader, that way if your kernel gets too big, it won't leech into stack-space.

remember, the stack grows DOWN, and therefor, if you place it below code, then it will never interfere.

Re: LGDT crashing bootloader

Posted: Sun Nov 30, 2008 2:18 pm
by mrnoob
alright, thanks, ill work on that

Re: LGDT crashing bootloader

Posted: Sun Nov 30, 2008 2:45 pm
by mrnoob
argh, its still not working :@
ive set up ds, es, ss, sp and bp and now i have the same problem as i started with, when i move EAX into CR0 it triple faults.

[edit]Heres what i've got now(still doesnt work):

Code: Select all

entry start
start:
	nop
	cli
	mov ax, cs
	mov ds, ax
	mov es, ax
	mov ax, #0x0000
	mov ss, ax
	mov si, #0x7c00
	mov sp, #0x7c00
	mov bp, sp
	call enableA20
	mov ax, #0x0600
	mov bh, #0x0F
	mov cx, #0
	mov dh, #25
	mov dl, #80
	int 0x10
	lgdt [gdtr]
	mov eax, cr0
	or al, #1
	mov cr0, eax
moi:	jmp moi
	jmp kcode:cleareip
cleareip:
repme:	jmp repme
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

enableA20:
	call    a20wait
	mov     al,#0xAD
	out     #0x64,al
	call    a20wait
	mov     al,#0xD0
	out     #0x64,al
	call    a20wait2
	in      al,#0x60
	push    eax
	call    a20wait
	mov     al,#0xD1
	out     #0x64,al
	call    a20wait
	pop     eax
	or      al,2
	out     #0x60,al
	call    a20wait
	mov     al,#0xAE
	out     #0x64,al
	call    a20wait
	ret
a20wait:
	in      al,#0x64
	test    al,#2
	jnz     a20wait
	ret
a20wait2:
	in      al,#0x64
	test    al,#1
	jz      a20wait2
	ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

gdtr:
	.word gdtend-gdt-1
	.long gdt

gdt:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

nullsel equ *-gdt
.word 0x0000
.word 0x0000
.word 0x0000
.word 0x0000
kcode equ *-gdt
.word 0xFFFF	;limit 0-15
.word 0x0000	;base 0-15
.byte 0x00	;base 16-23
.byte 0x9A	;options
.byte 0xC0	;flags and limit set to 256MB
.byte 0x00	;base set to 0
kdata equ *-gdt
.word 0xFFFF	;limit 0-15
.word 0x0000	;base 0-15
.byte 0x00	;base 16-23
.byte 0x92	;options
.byte 0xC0	;flags and limit set to 256MB
.byte 0x00	;base set to 0
gdtend:

Re: LGDT crashing bootloader

Posted: Sun Nov 30, 2008 5:25 pm
by Troy Martin
Is this in AT&T (gas) syntax or Intel syntax?

Re: LGDT crashing bootloader

Posted: Sun Nov 30, 2008 5:44 pm
by mrnoob
its a bit of a hybrid of both really.
opcode order is [op] [dest], [source]

Re: LGDT crashing bootloader

Posted: Wed Dec 03, 2008 1:40 pm
by Mike
One possibility: Some BIOSes load the boot sector at 07C0:0000, others at 0000:7C00. Make sure your CS register and origin are set properly (0000:7C00) so that when the CPU executes the mov cr0, eax instruction, the next instruction is at the same address in both modes.

I'm not 100% this would be the fix due to the caching and other means of dealing with seemingly inconsistent states during the transition to protected mode.

Have you tried running this in bochs? When bochs triple faults, it usually gives a reason in the log file.

Re: LGDT crashing bootloader

Posted: Wed Dec 03, 2008 2:03 pm
by IanSeyler
Did you try this:

Code: Select all

lgdt [cs:gdtr]
-Ian

Re: LGDT crashing bootloader

Posted: Wed Dec 03, 2008 3:20 pm
by mrnoob
unfortunately bochs doesnt work on my pc, a bunch of PANIC messages come up even with a default installation.
as for lgdt[cs:gdtr], i get a syntax error and i cant seem to get any kind of segment:offset links working :/

could i upload my image or code for someone to debug in bochs or something? ive been trying to fix this for a couple of months now and havent got anywhere, and i just want to get on with developing an OS.

Re: LGDT crashing bootloader

Posted: Wed Dec 03, 2008 4:17 pm
by Combuster
This sounds a lot like PEBCAK.

For starters, I would seriously consider getting a modern assembler which can do all the opcodes properly and isn't from the previous century. And read documentation. Lots of it.

Also, how did you manage to break everything when you said it was working a month ago? :shock:

Re: LGDT crashing bootloader

Posted: Wed Dec 03, 2008 4:32 pm
by mrnoob
it wasnt properly working, as soon as i tried any operations after the PM switch it tripled. I might convert the code to nasm actually.