Getting stack faults when passing controls to kernel.

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
jeremy6996
Posts: 10
Joined: Mon Sep 28, 2009 11:06 am

Getting stack faults when passing controls to kernel.

Post by jeremy6996 »

All compiling and assembling is being done on a linux, ubuntu machine.

I wrote my bootsector two days ago, and I am sure it is working correctly, because I've swapped other bootsectors with mine and the problem continues. So now I think the problem has to be with my kernel, whenever I make a call to any functions I get a stack fault(I wish I could provide more information but that's all vmware is throwing at me). But, I can pop & push onto the stack fine.

I get into protected mode fine, and I am passing control over to the kernel without any problems, but as soon as any function calls are made within the kernel I get a stack fault.

The bootsector is located on the first sector of the disk, and the kernel on the second.

This is my first bootsector and kernel, so sorry if the problem is obvious.

bootsector.asm

Code: Select all

;[WORD WRAP PROTECTION]------------------------------------------------------------------------------------------------------------------------
; Written By: Jeremy. A. Wildsmith
; Copyright jetaos, 2009, Jeremy. A. Wildsmith

; Main executable of the bootloader.
[BITS 16]     ; Describe code is 16-bit, in real-mode, the processor runs in 16-bit mode
[ORG 0x7C00]  ; Tells the assembler where the code will be in memory
	      ; after being loaded
jmp _start

_start:
	xor ax, ax				; Zero ax
	mov ds, ax				; Setup data segment register to 0
	mov es, ax				; Setup extra segment register.

	mov [data_iBootDriveSource], dl		; Get boot source drive from dl register, and store it.

	mov ebp, data_sBootMessage
	call func_PrintSystemMessage		; Print system message

	;Load kernel into memory
	mov ebp, data_sLoadingKernelFromDisk	; Load message into ebp register
	call func_PrintSystemMessage		; Print system message

	mov BX, 0x1000				; Dump to es:0x1000
	mov AL, 5				; Read 5 sectors
	mov CL, 2				; Start reading at sector 2
	mov DL, byte [data_iBootDriveSource]	; Read from a drive defined in variable data_iBootDriveSource
	call func_DumpSectors			; Dump selected sectors in DS:BX

	mov ebp, data_sContinue    		; Ask user to press any key
	call func_PrintSystemMessage		; Print message
	call func_WaitForKey			; Wait for keypress

	mov ebp, data_sBooting			; Load message into ebp register
	call func_PrintSystemMessage		; Print system message

	;Load GDT

	cli					; Clear interrupts
	lgdt [gdt_desc]				; Load gdt

	;Move processor into protected mode.
	mov eax, cr0				; Load CR0 into EAX
	or  eax, 1				; Set the first bit in eax
	mov cr0, eax				; Load EAX into CR0

	JMP 08h:clear_pipe                      ; Clear pipe, setup stack and pass control to kernel
	
	JMP $         				; Jump to current location(endless loop)


func_DumpSectors:
	; Assumes:
	; Data segment is setup
	; BX = offset to extra segment where sector is loaded.
	; AL = Number of sectors to read
	; CL = Disk sector
	; DL = Drive
	func_DumpSectors_ResetDrive:
		mov AH, 0x0				; Call service 0
		INT 0x13				; Reset drive
		jc func_DumpSectors_ResetDrive 		; If carry Flag is set(reset drive failed) attempt to reset again
		

	mov AH, 0x02 					; Service 2
	mov CH, 0    					; Cylinder 0
	mov DH, 0					; Disk head
	INT 0x13					; Make call to service
	jc func_DumpSectors_ResetDrive 			; If carry Flag is set(read drive failed) attempt to reset again

	ret 						; Return to caller

jmp_BootError:
	mov ebp, data_sError			; Load error message into ebp register.
	call func_PrintSystemMessage		; Print message
	jmp $
	


func_WaitForKey: ;Returns 0 for no, 1 for yes through eax register.

	xor ah, ah	;Make call to service 0
	INT 0x16	;Execute interrupt 0x10
	ret

func_moveCursorDown:
	pushad        ;Reserve Registers

	;Get cursor position
	mov AH, 0x03  ;Get cursor position, DH = row, DL = Col
	mov BH, 0x00  ;Page #0 = graphics mode
	INT 0x10      ;Execute video interrupt

	;Set cursor position
	inc DH        ;Increment current row by one
	xor DL, DL    ;Reset del register(col number)

	mov AH, 0x02  ;Set cursor position
	mov BH, 0x00  ;Page #0 = graphics mode
	INT 0x10      ;Execute video interrupt
	

	popad	      ;Restore Registers
	retn 

func_PrintSystemMessage:
	
	;Assumes ebp is base address of system message

	push ebp                     	; Preserve ebp register.

	mov ebp, data_sSystemPrefix  	; Load ebp with system label prefix message
	call func_PrintString		; Call Print Function

	pop ebp				; Restore ebp register. Which is the system message
	call func_PrintString		; Call print function

	ret				; Return to caller

func_PrintString:
	;Assume ebp contains pointer to start of string.
	;$ == linedown char.

	push ebp ; reserve ebp register.

	@func_PrintString_loop1:
		mov AL, byte [EBP]		; set al register to the character placed at ebp	
		cmp AL, 0                       ; if AL == 0
		jz func_PrintString_end1	; return
		
		cmp AL, '$'                     	; if AL != linedown Char
		jne func_PrintString_print      	;  print character
		
		call func_moveCursorDown                ;  else linedown							
		jmp func_PrintString_loop1_continue	;  and continue loop

		func_PrintString_print:	
			call func_PrintChar		; print char placed in al register

		func_PrintString_loop1_continue:	
			inc EBP				; Increase ebp to move to next character
			jmp @func_PrintString_loop1	;  go to start of loop


	func_PrintString_end1:			; The end of the functions, all registers are
						;  restored to their state when callee made the call.
		pop ebp				; Restore ebp register
		retn				; return to caller
	retn

func_PrintChar:
	;Assume AL register contains ascii character to print.	

	;Preserve registers.	
	push EAX
	push EBX

	mov AH, 0x0E ; Service is 0x0E
	mov BH, 0x00 ; Page #0
	mov BL, 0x04 ; Colors
	int 0x10     ; Call interrupt

	;Restore registers
	pop EBX
	pop EAX
	
	retn         ; return to caller


[BITS 32] ;32 bit instructions for when the processor is put into protected mode.
clear_pipe: ;Assumes far jump was made to this code, at segment 0x8, which will cear the instruction pipe

	mov ax, 10h 		; Set AX Register to 0x10(16d), which points to the data segment
	mov ds, ax   		; Setup data segment
	mov ss, ax		; Setup stack segment

	mov esp, 090000h	; Move stack pointer to 0x90000 offset from data segment
	
	jmp 08h:01000h		; Jmp to kernel

	jmp $			; Hang


;data, Strings are null terminated.
	
	data_sError                  db 'Error booting. Reset machine.$',0

	data_sLoadingKernelFromDisk  db 'RD:-SEC(S:R)(2:4)1.2MB$',0
	
	data_sBootMessage            db '16\32b BL(b3.v[1.0])$',0
	data_sSystemPrefix           db '[SYS] ',0

	data_sContinue               db 'Hit enter to continue$', 0
	data_sBooting                db 'BL loading kern$',0
	data_sInProtected            db 'Exec passed to kernel(P32bit)$',0 ;P32bit = Protected 32 bit mode


	data_iBootDriveSource        db 0


;GDT
gdt:
	gdt_null:
		dq 0 ;First entry in the gdt is null, and is reserved for the processor.
		;dq define quadword

	gdt_code:
		;DWORD1
		dw 0x0FFFF	; Base is 0x0, limit is 0xFFFF. GDT Size is 0xFFFF bytes long
		dw 0x0		; No use of the last WORD
			
		;DWORD2
		db 0x0		; First bits in base address is 0
		db 10011010b	; Ring0, Is data or code|Readable, non-conforming, code segment. Segment is present
		db 11001111b	; Limit 0x0F, 32bit size, 4Kb multiplier
		db 0x0		; Last bits in base address is 0

	gdt_data:
		;DWORD1
		dw 0x0FFFF 	; Base is 0(overlaps code segment) Limit is 0xFFFF
		dw 0x0       	; No use of the last WORD

		;DWORD2
		db 0x0 		; First bits in base address
		db 10010010b	; Non-conforming, writable, data segment, data or code, expands down, and is present
		db 11001111b	; 32 bit, 'BIG' , LIMIT 0x0F
		db 0x0          ; Last bits in the base address
gdt_end:

;GDT Descriptor
gdt_desc:
	dw gdt_end - gdt    	; Size of GDT
	dd gdt			; Address of GDT



;NULL Memory Region + Bootloader Signature
	TIMES 510 - ($ - $$) db 0 	; Fill the rest of the program with 0. $ = cur loc, 
				  	; $$ == start			 
				  	; Bootloader must be 512 bytes long.

	DW 0xAA55 			;Apply signature telling the bios this is a valid boot loader.

;[WORD WRAP PROTECTION]------------------------------------------------------------------------------------------------------------------------
I'm assembling it with nasm using -f to set the format to binary.

And the kernel:
main.c

Code: Select all

int testFunc(int var)
{
	return 0;
}

void main() 	//Kernel Entry-point
{
	int i = 0;
	i = testFunc(i);
	while(1);	//hang
}
I'm using this shell script I wrote:

Code: Select all


kernbase=0x1000

echo Building Kernel

gcc  -ffreestanding -c main.c  -o ./build/main.o

#Build twice, w\ i, unresolved externals not reported
ld   -e main -Ttext $kernbase -o ./build/kernel.o ./build/main.o 
ld   -i -e main -Ttext $kernbase -o ./build/kernel.o ./build/main.o

objcopy -R .note -R .comment -S -O binary ./build/kernel.o ./build/kernel.bin
echo kernel build completed.
Thanks.
Last edited by jeremy6996 on Mon Sep 28, 2009 11:41 am, edited 1 time in total.
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: Getting stack faults when passing controls to kernel.

Post by Combuster »

The kernel entry point is not at 0x1000, instead it enters (most likely) at testFunc()
#Build twice, w\ i, unresolved externals not reported
Why are you linking incrementally? objcopy can lift all the needed sections from an executable file just as well as an object file
"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 ]
jeremy6996
Posts: 10
Joined: Mon Sep 28, 2009 11:06 am

Re: Getting stack faults when passing controls to kernel.

Post by jeremy6996 »

Combuster wrote:The kernel entry point is not at 0x1000, instead it enters (most likely) at testFunc()
#Build twice, w\ i, unresolved externals not reported
Why are you linking incrementally? objcopy can lift all the needed sections from an executable file just as well as an object file
I've been following a tutorial which had told me to build incrementally, obviously though it wasn't too accurate as I can see now. I also get the same problem when moving the testFunc function below main.
earlz
Member
Member
Posts: 1546
Joined: Thu Jul 07, 2005 11:00 pm
Contact:

Re: Getting stack faults when passing controls to kernel.

Post by earlz »

is this a C kernel?

are you sure you can push and pop about 32-256 bytes onto the stack from within the kernel?

Are you sure its a stack fault and not something else(as in, tried it in another emulator such as bochs)
jeremy6996
Posts: 10
Joined: Mon Sep 28, 2009 11:06 am

Re: Getting stack faults when passing controls to kernel.

Post by jeremy6996 »

earlz wrote:is this a C kernel?
Yes
are you sure you can push and pop about 32-256 bytes onto the stack from within the kernel?
No, but I'll run a test now.
Are you sure its a stack fault and not something else(as in, tried it in another emulator such as bochs)
Vmware does report a stack fault, I'm only as sure as that. I'll try another emulator.
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: Getting stack faults when passing controls to kernel.

Post by Combuster »

Just ran some of my current code through the object dumper the way you do:

Code: Select all

e8 fc ff ff ff          call   665 <AUTOLOADPCICLASS+0xd5>
The instruction is not pointing to the function, instead its pointing to itself as the linker still has to add the offsets.

In other words, whatever code you try you get stuck in an infinite "call myself" loop which, obviously, leads to problems...

In more other words: incremental linking eats you while asleep :wink:
"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 ]
jeremy6996
Posts: 10
Joined: Mon Sep 28, 2009 11:06 am

Re: Getting stack faults when passing controls to kernel.

Post by jeremy6996 »

Wow, thanks.

Thank god I posted here, that would have taken me years to figure out. The tutorial told me to link incrementally so I just took it for granted. Thanks again.
User avatar
Firestryke31
Member
Member
Posts: 550
Joined: Sat Nov 29, 2008 1:07 pm
Location: Throw a dart at central Texas
Contact:

Re: Getting stack faults when passing controls to kernel.

Post by Firestryke31 »

Tip: If a tutorial doesn't explain why it's doing something, it's not a very good tutorial.
Owner of Fawkes Software.
Wierd Al wrote: You think your Commodore 64 is really neato,
What kind of chip you got in there, a Dorito?
Post Reply