Protected mode problems

If you are new to OS Development, plan on spending some time here first before going into the other forums.

Moderator:Moderators

hahnski07
Posts:19
Joined:Sat Jul 18, 2009 1:50 am
Protected mode problems

Post by hahnski07 » Tue Aug 11, 2009 2:27 pm

Great work on the tutorials, but I am having some issues w/ entering protected mode.

I've been staring at it for days and I finally decided it was time to ask for help, so here it is.

I debugged my bootsector w/ bochs and right after I make the jump to protected mode it lists this as the next command

Code: Select all

jmp far f000:e05b
I also tried it w/ VirtualPC and it gives me the error

Code: Select all

An unrecoverable processor error has been encountered.
Here's my code:

Code: Select all

[ORG 0x0]

[BITS 16]

start:
	jmp main
	
Failure:
	xor ax, ax
	int 0x16								; wait for keypress
	int 0x19								; warm reboot
		
	db	'MH'								; padding

;----------------------------------------------------------------------------------------------------
; OEM Parameter Block
;----------------------------------------------------------------------------------------------------
bytesPerSector		dw	512
sectorsPerCluster	db	1
reservedSectors		dw	1
numberOfFATs		db	2
rootEntries			dw	224
totalSectors		dw	2880
media				db	0xF0
sectorsPerFAT		dw	9
sectorsPerTrack		dw 	18
headsPerCylinder	dw	2
hiddenSectors		dd	0
totalSectorsBig		dd	0
driveNumber			db	0
unused				db	0
extBootSignature	db	0x29
serialNumber		dd	0xa0a1a2a3
volumeLabel			db	"Phenom   OS"
fileSystem			db	"FAT12   "

main:

;----------------------------------------------------------------------------------------------------
; Adjust segment registers
;----------------------------------------------------------------------------------------------------
	cli
	mov ax, 0x07C0						; (7C00:0000)
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	
;----------------------------------------------------------------------------------------------------
; Create stack
;----------------------------------------------------------------------------------------------------
	mov ax, 0x0000						; bottom of stack
	mov ss, ax
	mov sp, 0xFFFF						; top of stack
	sti

;----------------------------------------------------------------------------------------------------
; Load root directory table and FAT
;----------------------------------------------------------------------------------------------------
	xor ax, ax
	mov al, byte [numberOfFATs]			; number of FATs
	mul word [sectorsPerFAT]			; total sectors used
	mov cx, ax
	mov ax, 0x0020						; 32 byte directories
	mul word [rootEntries]				; number of bytes
	div word [bytesPerSector]			; number of sectors
	add cx, ax			

	mov ax, word [reservedSectors]		; adjust for bootsector
	mov word [datasector], ax
	add word [datasector], cx
	
	mov bx, 0x0200						; (7C00:0200)
	call ReadSectors
	
;----------------------------------------------------------------------------------------------------
; Find stage 2
;----------------------------------------------------------------------------------------------------
	mov cx, word [rootEntries]			; loop counter
	mov di, 0x2600						; first entry
.loop:
	push cx
	mov cx, 0x000B						; 8.3 names
	mov si, fileName					; file to find
	push di
rep cmpsb
	pop di
	je Load_File
	pop cx
	add di, 0x0020						; next directory
	loop .loop
	jmp Failure
	
;----------------------------------------------------------------------------------------------------
; Load Kernel
;----------------------------------------------------------------------------------------------------
Load_File:
	mov dx, word [di + 0x001A]
	mov word [cluster], dx				; file's first cluster
	
	mov ax, 0x0050
	mov es, ax
	mov bx, 0x0000						; (0050:0000)
	push bx

	mov ax, word [cluster]				; cluster to read
	pop bx								; buffer to read into
	
	sub ax, 0x0002						; zero base cluster
	xor cx, cx
	mov cl, byte [sectorsPerCluster]
	mul cx
	add ax, word [datasector]			; offset after root directory table

	xor cx, cx
	mov cl, byte [sectorsPerCluster]	; sectors to read
	call ReadSectors
	push bx
	
	mov ax, word [cluster]				; current cluster
	mov cx, ax
	mov dx, ax
	shr dx, 0x0001						; divide by 2
	add cx, dx							; sum for (3/2)
	mov bx, 0x0200						; location of FAT
	add bx, cx							; index into FAT
	mov dx, word [bx]					; read 2 bytes
	test ax, 0x0001
	jnz .odd
	
.even:
	and dx, 0000111111111111b			; take 12 low bits
	jmp .done
.odd:
	shr dx, 0x0004						; take 12 high bits
	
.done:

;----------------------------------------------------------------------------------------------------
; Load GDT
;----------------------------------------------------------------------------------------------------
	cli
	lgdt [toc]

;----------------------------------------------------------------------------------------------------
; Enable A20 line
;----------------------------------------------------------------------------------------------------
	call Wait_Input
	mov al, 0xAD
	out 0x64, al						; disable keyboard
	
	call Wait_Input	
	mov al, 0xD0
	out 0x64, al						; read output port command

	call Wait_Output	
	in al, 0x60
	push eax							; store output data

	call Wait_Input
	mov al, 0xD1
	out 0x64, al						; write ouput port command
	
	call Wait_Input
	pop eax
	or al, 2							; enable A20
	out 0x60, al

	call Wait_Input	
	mov al, 0xAE						; enable keyboard
	out 0x64, al

;----------------------------------------------------------------------------------------------------
; Enter Protected Mode
;----------------------------------------------------------------------------------------------------
	cli
	mov eax, cr0
	or eax, 0x01
	mov cr0, eax

	!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Problem
	jmp 0x8:Protected
	
[BITS 32]	
	
;----------------------------------------------------------------------------------------------------
; Set Registers
;----------------------------------------------------------------------------------------------------
Protected:
	mov ax, 0x10
	mov ds, ax
	mov ss, ax
	mov es, ax
	mov esp, 0x90000					; stack begins at 0x90000
	
	jmp 0x8:0x500


[BITS 16]
	
	cli
	hlt
	
;----------------------------------------------------------------------------------------------------
; Print a string
; 
; si <= Address of string
;----------------------------------------------------------------------------------------------------
;Print:
;	mov ah, 0x0E
;.loop:
;	lodsb
;	or al, al
;	jz .finish
;	int 0x10
;	jmp .loop
;.finish:
;	ret

;----------------------------------------------------------------------------------------------------		
; GDT (Global Descriptor Table)
;----------------------------------------------------------------------------------------------------
gdt_null:
	dq	0								; null descriptor
	
gdt_code:								; code descriptor
	dw	0xFFFF							; 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	0xFFFF							; limit low
	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_null - 1		; limit
	dd	gdt_null						; base of GDT

;----------------------------------------------------------------------------------------------------
; Wait for keyboard input buffer
;----------------------------------------------------------------------------------------------------
Wait_Input:
	in al, 0x64
	test al, 2
	jnz Wait_Input
	ret
	
;----------------------------------------------------------------------------------------------------
; Wait for keyboard output buffer
;----------------------------------------------------------------------------------------------------
Wait_Output:
	in al, 0x64
	test al, 1
	jz Wait_Output
	ret	

;----------------------------------------------------------------------------------------------------
; Read sectors from floppy drive
;
; cx => # of sectors
; ax => starting sector
; es:bx => buffer to read to
;----------------------------------------------------------------------------------------------------
ReadSectors:
.main:
	mov di, 0x0005						; five tries for error
.loop:
	push ax
	push bx
	push cx

	xor dx, dx							; prepare dx:ax
	div word [sectorsPerTrack]
	inc dl
	mov cl, dl
	xor dx, dx
	div word [headsPerCylinder]			; calculate
	mov dh, dl
	mov ch, al

	mov ah, 0x02						; read sector
	mov al, 0x01						; read one sector
	mov dl, byte [driveNumber]			; drive
	int 0x13							; BIOS low level disk operations
	jnc .success						; test for read error
	xor ax, ax							; BIOS reset disk
	int 0x13							; BIOS low level disk operations
	dec di								; decrement error counter
	pop cx	
	pop bx
	pop ax
	jnz .loop
	int 0x18
.success:
	pop cx
	pop bx
	pop ax
	add bx, word [bytesPerSector]		; next
	inc ax
	loop .main							; read next sector
	ret

fileName		db	"KERNEL  SYS"
datasector		dw	0x0000
cluster			dw	0x0000
	
times 510 - ($-$$) db 0					; fill with zeros

	dw 0xAA55
^^ The !!! are the line where bochs says my problem is
Last edited by hahnski07 on Tue Aug 11, 2009 7:04 pm, edited 1 time in total.

Andyhhp
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: Protected mode problems

Post by Andyhhp » Tue Aug 11, 2009 5:50 pm

Which line specifically is it that is giving you the problem?
Image

hahnski07
Posts:19
Joined:Sat Jul 18, 2009 1:50 am

Re: Protected mode problems

Post by hahnski07 » Tue Aug 11, 2009 7:15 pm

put !!!! in front of problem line

Andyhhp
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: Protected mode problems

Post by Andyhhp » Wed Aug 12, 2009 6:10 pm

Hmm

I cant see a problem offhand.

How long is the binary file for your bootloader?
Image

hahnski07
Posts:19
Joined:Sat Jul 18, 2009 1:50 am

Re: Protected mode problems

Post by hahnski07 » Wed Aug 12, 2009 6:32 pm

I have at least 64 bytes left before I hit the 512 mark.

hahnski07
Posts:19
Joined:Sat Jul 18, 2009 1:50 am

Re: Protected mode problems

Post by hahnski07 » Thu Aug 13, 2009 7:22 pm

any suggestions?

Andyhhp
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: Protected mode problems

Post by Andyhhp » Thu Aug 13, 2009 11:01 pm

hehe - I was just writing a post about how I couldnt see anything wrong and then it struck me.

Code: Select all

...
   cli
   mov eax, cr0
   or eax, 0x01
   mov cr0, eax

   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Problem
   jmp 0x8:Protected
   
[BITS 32]   
...
As soon as you do the mov cr0, eax instruction, you are in 32bit mode.

Therefore, your code needs to read:

Code: Select all

...
   cli
   mov eax, cr0
   or eax, 0x01
   mov cr0, eax

   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Problem
   [BITS 32]
   jmp 0x8:Protected
   
   ...
Try that

~Andrew


[EDIT]
I also wish to point out that unless you have a flat binary kernel file, the jump here

Code: Select all

Protected:
   mov ax, 0x10
   mov ds, ax
   mov ss, ax
   mov es, ax
   mov esp, 0x90000               ; stack begins at 0x90000
   
   jmp 0x8:0x500
will not succesfully execute the kernel.

If you follow the tutorials here, you will need to follow the section on parsing the PE header of the kernel file to get it running.
Image

hahnski07
Posts:19
Joined:Sat Jul 18, 2009 1:50 am

Re: Protected mode problems

Post by hahnski07 » Thu Aug 13, 2009 11:59 pm

That makes sense now that I look at it, but I had copied that part from the downloaded example which means that the example is wrong.

At this point in time my kernel is still flat.

Fortunately because I was able to combine the loading of the FAT and the Root Directory, I will still have enough space to lgdt, enable A20, and load a PE kernel all in my bootloader :)

hahnski07
Posts:19
Joined:Sat Jul 18, 2009 1:50 am

Re: Protected mode problems

Post by hahnski07 » Fri Aug 14, 2009 12:21 am

It seems I spoke too early, it still doesn't work. So weird

hahnski07
Posts:19
Joined:Sat Jul 18, 2009 1:50 am

Re: Protected mode problems

Post by hahnski07 » Fri Aug 14, 2009 12:29 am

I debugged it till it got to the jmp into protected mode and this is what boch's gave me

Code: Select all

jmp far 0000:012d
what? Shouldn't it be jmp far 0008:7C?? or something like that?

hahnski07
Posts:19
Joined:Sat Jul 18, 2009 1:50 am

Re: Protected mode problems

Post by hahnski07 » Fri Aug 14, 2009 12:40 am

It seems like 0x012d should be the offset but for some reason cs is not being added in, any reason why it's doing this?

User avatar
Mike
Site Admin
Posts:465
Joined:Sat Oct 20, 2007 7:58 pm
Contact:

Re: Protected mode problems

Post by Mike » Fri Aug 14, 2009 1:52 am

Hello,
As soon as you do the mov cr0, eax instruction, you are in 32bit mode
Not necessarily. After the above instruction, he is in 16 bit protected mode until he jumps into 32 bit code via the jmp instruction. Because of this, the jmp does not need to be in 32 bit code.

Code: Select all

jmp far f000:e05b
This is a common CPU first instruction on the Bochs bios. It may mean a triple fault. More information can be found in the bochs crash log. The An unrecoverable processor error has been encountered. in VPC indicates a #GPF exception not handled.

Your code has odd 16 bit and 32 bit sections. Be very careful when mixing 16 bit and 32 bit code like that - odd issues can crop up in doing so. (ie, having 16 bit code segments in 32 bit code is a bad idea.)

I will post back if I find anything :)
Lead Programmer for BrokenThorn Entertainment, Co.
Website: http://www.brokenthorn.com
Email: webmaster@brokenthorn.com

hahnski07
Posts:19
Joined:Sat Jul 18, 2009 1:50 am

Re: Protected mode problems

Post by hahnski07 » Fri Aug 14, 2009 1:56 am

What do you mean by odd 16 and 32 bit sections?

It is essentialy the bootsector and stage two crammed in the same place.

User avatar
Mike
Site Admin
Posts:465
Joined:Sat Oct 20, 2007 7:58 pm
Contact:

Re: Protected mode problems

Post by Mike » Fri Aug 14, 2009 2:40 am

Hello again,

Please update the following lines to the following:

Code: Select all

toc:
   dw   end_of_gdt - gdt_null - 1      ; limit
   dd   gdt_null+0x7c00                  ; base of GDT

Code: Select all

 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ~snip~Problem
   jmp 0x8:Protected+0x7c00
Rebuild the code and test again please. After the above updates, your code worked fine for me :) Because I cannot completely test, I do not know if you will need to update other variable references. You might need to.
What do you mean by odd 16 and 32 bit sections?
Mixing 16 bit and 32 bit code the way you are currently doing can cause possible alignment issues. ie, you are having 16 bit code call 32 bit functions that call BIOS interrupts. This alone is fine, but is also prone to possible low level issues (from my experience, anyways...)
Lead Programmer for BrokenThorn Entertainment, Co.
Website: http://www.brokenthorn.com
Email: webmaster@brokenthorn.com

Andyhhp
Moderator
Posts:387
Joined:Tue Oct 23, 2007 10:05 am
Location:127.0.0.1
Contact:

Re: Protected mode problems

Post by Andyhhp » Fri Aug 14, 2009 7:00 am

Hmm - now im quite embarrased - I specifically checked the org and segment bases to see if this was the problem and missed it.

I cant have been looking too hard :S
Image

Post Reply