Page 1 of 1

Fighting with a GDT

Posted: Sat Mar 01, 2014 3:13 pm
by onlyonemac
Hi!

I've recently just started developing my own OS and currently I've just reached the dreaded protected mode stage. I've spent about a month reading up about this and planning a GDT, but today when it comes to it I just can't seem to jump to my code segment selector! Somehow every segment I try for the jump just doesn't work, and Boch's log output for various segments doesn't seem to match what's in my GDT (e.g. I say jump to segment ABC and it says "invalid TSS" when segment ABC isn't a TSS etc. etc.). I've checked that the GDT is being read from disk and set up correctly.

Code: Select all

;This is the bootloader for xxxOS.
;It loads the kernel file (consisting of a GDT, IDT and a set of interrupt handlers) and then tells it to initialise.
;Note that we don't actually need to set up a GDT/IDT: this is stored in the kernel file and loaded when we load the kernel.

entry start
start:
	;The first thing we want here is a temporary usable stack.
	;We'll use the memory where the kernel will later set up its data blocks.
	mov	ax, #0x0050
	mov	ss, ax
	mov	ax, #0x00FF
	mov	sp, ax

	;This specifies the place where the kernel will be loaded.
	mov	ax, #0x1000
	mov	es, ax

	;Set another segment to the video memory, as this will be needed later for status messages.
	mov	ax, #0xB800
	mov	fs, ax

	;Display the start of the progress bar.
	seg	fs
	mov	[0], #0x41
	seg	fs
	mov	[1], #0x71

	;896 sectors
	;458752 bytes
	mov	ch, #1		;First track number
	mov	dh, #0		;First head number

readloop:
	call	readtrack
	not	dh
	and	dh, #1
	cmp	dh, #0
	jnz	readloop

	;Increment the progress bar.
	mov	al, ch		;Prepare the character to display
	add	al, #0x41
	mov	bl, ch		;Calculate the video memory offset
	mov	bh, #0
	rol	bx, #1
	seg	fs
	mov	[bx], al	;Output the character...
	add	bx, #1
	seg	fs
	mov	[bx], #0x71	;...and the attributes (blue on grey).

	inc	ch
	cmp	ch, #26		;We're reading a total of 25 tracks starting from track 1
	jnz	readloop

	;Enable A20.

	;Load GDT and IDT registers.
	mov	ax, #0x1000
	mov	ds, ax
	lgdt	[0x0000]
	mov	ax, #0x2000
	mov	ds, ax
	lidt	[0x0000]

	;Enter protected mode.
	cli
	mov	eax, cr0
	or	al, #1
	mov	cr0, eax

	;Initialise the kernel.
;	hlt
;	int	0xF0
	jmp	0x0E:0

	;We should never get down here, but just in case...
	hlt

readtrack:
	mov	cl, #1
	trackloop:
	call	readsector
	inc	cl
	cmp	cl, #19
	jnz	trackloop
	ret

readsector:
	mov	bx, #0		;Offset within extra segment for destination
	mov	dl, #0		;Drive number
	mov	al, #1		;Number of sectors to read
	mov	ah, #2		;Function code (2 = read sectors from disk)
	int	0x13

	cmp	ah, #0		;Check for errors
	jnz	readerror

	mov	bx, es		;Adjust the destination pointer ready for next sector
	add	bx, #0x0020
	mov	es, bx
	ret

readerror:
	mov	al, ah		;Prepare the character to display (represents error code)
	add	al, #0x30
	mov	bl, ch		;Calculate the video memory offset
	mov	bh, #0
	rol	bx, #1
	seg	fs
	mov	[bx], al	;Output the character...
	add	bx, #1
	seg	fs
	mov	[bx], #0x74	;...and the attributes (red on grey).
	hlt

Re: Fighting with a GDT

Posted: Sat Mar 01, 2014 3:41 pm
by Antti
Hello and welcome. I would recommend that you make protected mode experiments without loading anything from the disk. It would be easier to concentrate on the problem itself.

Re: Fighting with a GDT

Posted: Sat Mar 01, 2014 3:51 pm
by Pancakes
Check your bits in the GDT entries are in the proper ordering, and bytes. You might be doing 0101011 when it should be 1101010, or the other way around. Also, dump the GDT under boches. Also IIRC correctly if you dump the GDT under boches you can make sure it is actually loading your GDT and not something from somewhere else in memory which could also be your problem.

Re: Fighting with a GDT

Posted: Sat Mar 01, 2014 4:03 pm
by Antti

Code: Select all

;Initialise the kernel.
;   hlt
;   int   0xF0
   jmp   0x0E:0
There is a bug here (at least here, I did not check everything). Look at the documentation of segment selectors. I think you do not want to set those bits that are set now (0Eh == 1110b).

Code: Select all

 _____________________ ____ _____
|15                  3| 2  | 1 0 |
|         SI          | TI | RPL |
|_____________________|____|_____|

Bits
15-3    SI      Selector Index
2       TI      Table Indicator
1-0     RPL     Request Privilige Level

Re: Fighting with a GDT

Posted: Sat Mar 01, 2014 7:25 pm
by Bender
Hi,
Welcome 8)

Code: Select all

 lgdt   [0x0000] 
:roll:
Where is the GDT?
;Note that we don't actually need to set up a GDT/IDT: this is stored in the kernel file and loaded when we load the kernel.
So you load the first GDT after entering protected mode?
IMO you should have a GDT in your boot loader code itself, I see no point in having a GDT inside some other file or sector, and after your kernel is loaded you should load your kernel's GDT.
~Bender