Bizarre Kernel Issue

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
brodeur235
Member
Member
Posts: 86
Joined: Sat Jun 06, 2009 11:55 am

Bizarre Kernel Issue

Post by brodeur235 »

Here is my short kernel code:

Code: Select all

;||=====================================================||
;||                        KERNEL                       ||
;||=====================================================||
[BITS 32]

;||======================================||
;||               K_MAIN                 ||
;||======================================||
k_main:
	
	; setup segments and stack
	mov ax,0x10
	mov ds,ax
	mov es,ax
	mov fs,ax
	mov gs,ax
	mov ss,ax
	mov esp,0x0000D000
	
	;THE FOLLOWING FUNCTION CALL IS THE ISSUE
	mov al,0x1B
	call k_set_screen_colors
	
	jmp (($-k_main)+KERNEL_OFFSET)

end_k_main:
;||======================================||
;||            END K_MAIN                ||
;||======================================||

;||======================================||
;||              K_SCREEN                ||
;||======================================||
k_screen:

k_set_screen_colors:
	mov ebx,0x00B8001
	mov ecx,(80*25)
	.kssc_set_next:
		mov BYTE [ds:ebx],al
		add ebx,0x2
		loop .kssc_set_next
	ret
	
k_print:
	mov ebx,0x000B8000
	imul eax,160
	add ebx,eax
	.kp_next_char:
		lodsb
		cmp al,0x00
		jz .kp_done
		mov BYTE [ds:ebx],al
		add ebx,0x2
		jmp .kp_next_char
	.kp_done:
		ret

end_k_screen:
;||======================================||
;||           END K_SCREEN               ||
;||======================================||

kl_data:
	
	dbg_msg db "Debug MSG.",0x00
	

kl_padding:
	
	; pad to kernel size
	times (KERNEL_SIZE - ($-k_main)) db 0x00

;||=====================================================||
;||                      END KERNEL                     ||
;||=====================================================||
The part right under ";THE FOLLOWING FUNCTION CALL IS THE ISSUE":

Code: Select all

	mov al,0x1B
	call k_set_screen_colors
Is VERY wierd. If I do ANYTHING but call the function and that one function alone, I get a "stuck" error from vbox. If I even comment those two lines out, then I get the stuck error. However if this function is the ONLY thing I call in EXACTLY that manner, everything works as expected. Here is what the error page looks like:

Image
EDIT: Here is the VBox log: http://pastebin.ca/1490214 I don't understand it at all.

What is the problem here?

All help appreciated,

Brodeur235
User avatar
yemista
Member
Member
Posts: 299
Joined: Fri Dec 26, 2008 12:31 pm
Location: Boston
Contact:

Re: Bizarre Kernel Issue

Post by yemista »

maybe KERNEL_OFFSET is the problem? What is is being set to? If you want an infinite loop, use

Code: Select all

loop:
   jmp loop
Also, I dont know virtual box, but maybe you should try to use bochs? That error message is hard to debug. It would be more helpful if you could provide us with a register dump before and after the crash. I am suggesting bochs because it puts out a lot of information when it crashes in bochsout.txt. If virtual box does the same, show us some of the output
brodeur235
Member
Member
Posts: 86
Joined: Sat Jun 06, 2009 11:55 am

Re: Bizarre Kernel Issue

Post by brodeur235 »

KERNEL_OFFSET is the offset in memory that the kernel was loaded to. The reason I don't use the loop you suggested is because my bootloader is in the same source file, at the beginning of it. And just before the bootloader I ORGed the file to 0x7C00 for the bootloder. So, whenever I want to JMP somewhere in the kernel, I have to say (($-k_main)+KERNEL_OFFSET) where k_main is the beginning of the kernel and KERNEL_OFFSET is the kernel's offset in memory. For clarity's sake, here is the whole source:

Code: Select all

; general sizes (in bytes)
%define SECTOR_SIZE   0x0200
%define KILOBYTE_SIZE 0x0002 * SECTOR_SIZE
%define MEGABYTE_SIZE 0x0200 * KILOBYTE_SIZE
%define GIGABYTE_SIZE 0x0200 * MEGABYTE_SIZE
%define PAGE_SIZE     0x0004 * KILOBYTE_SIZE

; kernel disk info
%define KERNEL_DRIVE  0x0000
%define KERNEL_HEAD   0x0000
%define KERNEL_TRACK  0x0000
%define KERNEL_SECTOR 0x0002
%define KERNEL_SIZE   PAGE_SIZE * 2

; kernel memory info
%define KERNEL_OFFSET 0x00000040

; kernel screen module
%define SCREEN_WIDTH  80
%define SCREEN_HEIGHT 25
%define BLACK         0x00
%define BLUE          0x01
%define GREEN         0x02
%define CYAN          0x03
%define RED           0x04
%define MAGENTA       0x05
%define BROWN         0x06
%define LIGHT_GREY    0x07
%define DARK_GREY     0x08
%define LIGHT_BLUE    0x09
%define LIGHT_GREEN   0x0A
%define LIGHT_CYAN    0x0B
%define LIGHT_RED     0x0C
%define LIGHT_MAGENTA 0x0D
%define LIGHT_BROWN   0x0E
%define WHITE         0x0F

;||=====================================================||
;||                      BOOT LOADER                    ||
;||=====================================================||
[BITS 16]
[ORG 0x7C00]

bl_main:
	
	; setup stack
	xor ax,ax
	mov ss,ax
	mov sp,0x8000
	
	; setup data
	xor ax,ax
	mov ds,ax
	
	; load kernel
	call kernel_loader
	
	; load gdt
	lgdt [gdt_descriptor]
	
	; enter pmode
	mov eax,cr0
	or eax,1
	mov cr0,eax
	
	; jmp to kernel
	jmp 0x8:KERNEL_OFFSET

kernel_loader:
	
	; determine # of sectors to load
	; dx:ax / bx = ax remainder dx
	mov dx,0x0000
	mov ax,KERNEL_SIZE
	mov bx,SECTOR_SIZE
	div bx
	
	; ensure size is even number of sectors
	cmp dx,0x0000
	jnz .kl_error
	
	; setup to loop thru sectors
	mov cx,ax
	mov BYTE [sector_current], KERNEL_SECTOR
	mov WORD [offset_current], KERNEL_OFFSET
	.lk_copy_sector:
		push cx
		
		; copy current sector
		; disk loc -> es:bx in mem
		mov dh,KERNEL_DRIVE
		mov dl,KERNEL_HEAD
		mov ch,KERNEL_TRACK
		mov cl,[sector_current]
		xor bx,bx
		mov es,bx
		mov bx,[offset_current]
		mov ah,0x02
		mov al,0x01
		int 0x13
		
		; prepare for next sector
		add WORD [offset_current],SECTOR_SIZE
		inc BYTE [sector_current]
		
		pop cx
		loop .lk_copy_sector
	
	; completed
	jmp .kl_success
	
	; error section
	.kl_error:
		jmp $
	
	; success section
	.kl_success:
		ret
	
gdt_entries:
	
	; null entry
	db 00000000b
	db 00000000b
	db 00000000b
	db 00000000b
	db 00000000b
	db 00000000b
	db 00000000b
	db 00000000b
	
	; code segment descriptor: OFFSET = 0x0008
	db 11111111b
	db 11111111b
	db 00000000b
	db 00000000b
	db 00000000b
	db 10011010b
	db 11001111b
	db 00000000b
	
	; data segment descriptor: OFFSET = 0x0010
	db 11111111b
	db 11111111b
	db 00000000b
	db 00000000b
	db 00000000b
	db 10010010b
	db 11001111b
	db 00000000b
	
gdt_descriptor:
	
	; table size (2 bytes)
	dw (gdt_descriptor - gdt_entries)
	
	; table offset (4 bytes)
	dd gdt_entries
	
bl_data:
	
	; kernel_load data
	sector_current db 0x00 ; KERNEL_SECTOR
	offset_current dw 0x0000 ; KERNEL_OFFSET
	
bl_padding:
	
	;pad to 510 bytes
	times (512-2-($-bl_main)) db 0x00
	
	;make disk bootable w/ 2 byte flag
	db 0x55
	db 0xAA

;||=====================================================||
;||                    END BOOT LOADER                  ||
;||=====================================================||

;||=====================================================||
;||                        KERNEL                       ||
;||=====================================================||
[BITS 32]

;||======================================||
;||               K_MAIN                 ||
;||======================================||
k_main:
	
	; setup segments and stack
	mov ax,0x10
	mov ds,ax
	mov es,ax
	mov fs,ax
	mov gs,ax
	mov ss,ax
	mov esp,0x0000D000
	
	mov al,0x78
	call k_set_screen_colors
	
	jmp (($-k_main)+KERNEL_OFFSET)

end_k_main:
;||======================================||
;||            END K_MAIN                ||
;||======================================||

;||======================================||
;||              K_SCREEN                ||
;||======================================||
k_screen:

k_set_screen_colors:
	mov ebx,0x00B8001
	mov ecx,(80*25)
	.kssc_set_next:
		mov BYTE [ds:ebx],al
		add ebx,0x2
		loop .kssc_set_next
	ret
	
k_print:
	mov ebx,0x000B8000
	imul eax,160
	add ebx,eax
	.kp_next_char:
		lodsb
		cmp al,0x00
		jz .kp_done
		mov BYTE [ds:ebx],al
		add ebx,0x2
		jmp .kp_next_char
	.kp_done:
		ret

end_k_screen:
;||======================================||
;||           END K_SCREEN               ||
;||======================================||

kl_data:
	
	dbg_msg db "Debug MSG.",0x00
	

kl_padding:
	
	; pad to kernel size
	times (KERNEL_SIZE - ($-k_main)) db 0x00

;||=====================================================||
;||                      END KERNEL                     ||
;||=====================================================||
Also yemista, I'm staying at a hotel in Boston tonight ;). Small world, eh?

Brodeur235
User avatar
yemista
Member
Member
Posts: 299
Joined: Fri Dec 26, 2008 12:31 pm
Location: Boston
Contact:

Re: Bizarre Kernel Issue

Post by yemista »

In general, its not wise to define offsets like that. If you ever change something youll have to recalculate it. Let the linker set them for you.

You should be able to do jmp 0x8:kmain rather than jumping to the kernel offset, and loop: jmp loop should work as well. You can also change your org, which might be a good idea. The way you are doing it, since it is all one source file, all your code thinks it starts at 0x7c00, even though you are loading it somewhere else. That could be screwing things up. I suggest you break it down into different source files, and learn about linker scripts. When you make a function call, a physical address is supplied. Since it is all one source file, with [org 0x7c00] at the top, every function takes that as its base, even though you seem to be loading the kernel to 0x40, and that could be screwing things up. try to debug it step by step, and show us the instruction that fails.
User avatar
mathematician
Member
Member
Posts: 437
Joined: Fri Dec 15, 2006 5:26 pm
Location: Church Stretton Uk

Re: Bizarre Kernel Issue

Post by mathematician »

Near jumps are relative, so where you loaded the file is irrelevant. jmp $ will get you into an infinite loop.

On the other hand, far jumps are absolute, so if your kernel was located at 0x8000 say, and your gdt is initialised for the flat memory model, the far jump to the kernel would need to tanslate into jmp 0x08:0x8000.
Last edited by mathematician on Thu Jul 09, 2009 8:14 pm, edited 1 time in total.
The continuous image of a connected set is connected.
brodeur235
Member
Member
Posts: 86
Joined: Sat Jun 06, 2009 11:55 am

Re: Bizarre Kernel Issue

Post by brodeur235 »

Near jumps are relative, so where you loaded the file is irrelevant. jmp $ will get you into an infinite loop.
As far as I can tell, that did it. I no longer get the vbox error. I have a couple flights to make tommorow and I've got to go to bed, but I'll get back to this thread if it turns out that didn't do it.. Thanks for the advice,

Brodeur235
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Bizarre Kernel Issue

Post by Combuster »

Code: Select all

jmp 0x8:KERNEL_OFFSET ; execute IVT
Other than that, virtual box logs do provide a crashdump (note the EIP):

Code: Select all

# 00:00:04.916 Guest CPUM (VCPU 0) state: se
# 00:00:04.916 eax=60000010 ebx=00000040 ecx=00000000 edx=00000000 esi=0000c440 edi=0000ffde
# 00:00:04.916 eip=c48305bd esp=0000cff4 ebp=00000000 iopl=0      rf nv up ei pl zr na pe nc
# 00:00:04.916 cs={0008 base=0000000000000000 limit=ffffffff flags=0000c09b} dr0=00000000 dr1=00000000
# 00:00:04.916 ds={0010 base=0000000000000000 limit=ffffffff flags=0000c093} dr2=00000000 dr3=00000000
# 00:00:04.916 es={0010 base=0000000000000000 limit=ffffffff flags=0000c093} dr4=00000000 dr5=00000000
# 00:00:04.916 fs={0010 base=0000000000000000 limit=ffffffff flags=0000c093} dr6=ffff0ff0 dr7=00000400
# 00:00:04.916 gs={0010 base=0000000000000000 limit=ffffffff flags=0000c093} cr0=60000011 cr2=00000000
# 00:00:04.916 ss={0010 base=0000000000000000 limit=ffffffff flags=0000c093} cr3=00000000 cr4=00000000
# 00:00:04.916 gdtr=0000000000007c6e:0018  idtr=0000000000000000:ffff  eflags=00010202
# 00:00:04.916 ldtr={0000 base=00000000 limit=00000000 flags=00000082}
# 00:00:04.916 tr  ={0000 base=00000000 limit=0000ffff flags=0000008b}
# 00:00:04.916 SysEnter={cs=0000 eip=00000000 esp=00000000}
By the looks of it, it made a jump instruction out of the int 0x10 vector...
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply