Page 1 of 1

OS keeps crashing

Posted: Mon Nov 23, 2009 6:31 pm
by Aphex
I'm beginning OS development and have created a bootsector that loads the second sector (of the floppy disk) into memory and jumps to it. I want to write the second sector in C and so far with some success. Problem is, when I try to call a C function from my entry point, my "OS" just crashes. I am using protected mode and I am attempting to write directly to video memory, for example. this works;

Code: Select all

void start()
{
	unsigned char *vidmem = (unsigned char*) 0xb8000;

	vidmem[0] = 'H';
	vidmem[1] = 0x2a;
	
	for (;;);	
}
But this doesnt; :(

Code: Select all

void print()
{
	unsigned char *vidmem = (unsigned char*) 0xb8000;

	vidmem[0] = 'H';
	vidmem[1] = 0x2a;
}

void start()
{
        print();
	for (;;);	
}

This page describes a similar problem (scroll down for the main page)

http://www.osdever.net/tutorials/ckernel.php

Although none of the solutions seem to work. Can anyone offer a solution?

Thank you

Re: OS keeps crashing

Posted: Mon Nov 23, 2009 6:49 pm
by NickJohnson
First, did you allocate space for a stack? The one the bootloader gives you is often not large, and sometimes completely invalid. Second, what is your linker script? You need the addresses to match where the C code is actually loaded, otherwise function calls will be completely undefined.

Re: OS keeps crashing

Posted: Mon Nov 23, 2009 7:00 pm
by Aphex
Yes, space has been allocated for the stack, starting at 090000h.

Here is the first bootsector incase its of use here.

Code: Select all

[BITS 16]       ; We need 16-bit intructions for Real mode

[ORG 0x7C00]    ; The BIOS loads the boot sector into memory location 0x7C00

reset_drive:
        mov ah, 0               ; RESET-command
        int 13h                 ; Call interrupt 13h
        or ah, ah               ; Check for error code
        jnz reset_drive         ; Try again if ah != 0

        mov ax, 0
        mov es, ax
        mov bx, 0x1000          ; Destination address = 0000:1000

        mov ah, 02h             ; READ SECTOR-command
        mov al, 02h             ; Number of sectors to read = 1
        mov ch, 0               ; Cylinder = 0
        mov cl, 02h             ; Sector = 2
        mov dh, 0               ; Head = 0
        int 13h                 ; Call interrupt 13h
        or ah, ah               ; Check for error code
        jnz reset_drive         ; Try again if ah != 0

        cli                     ; Disable interrupts, we want to be alone

        xor ax, ax
        mov ds, ax              ; Set DS-register to 0 - used by lgdt

        lgdt [gdt_desc]         ; Load the GDT descriptor

        mov eax, cr0            ; Copy the contents of CR0 into EAX
        or eax, 1               ; Set bit 0
        mov cr0, eax            ; Copy the contents of EAX into CR0

        jmp 08h:clear_pipe      ; Jump to code segment, offset clear_pipe


[BITS 32]                       ; We now need 32-bit instructions
clear_pipe:
        mov ax, 10h             ; Save data segment identifyer
        mov ds, ax              ; Move a valid data segment into the data segment register
        mov ss, ax              ; Move a valid data segment into the stack segment register
        mov esp, 090000h        ; Move the stack pointer to 090000h

        jmp 08h:01000h          ; Jump to section 08h (code), offset 01000h


gdt:                    ; Address for the GDT

gdt_null:               ; Null Segment
        dd 0
        dd 0

gdt_code:               ; Code segment, read/execute, nonconforming
        dw 0FFFFh
        dw 0
        db 0
        db 10011010b
        db 11001111b
        db 0

gdt_data:               ; Data segment, read/write, expand down
        dw 0FFFFh
        dw 0
        db 0
        db 10010010b
        db 11001111b
        db 0

gdt_end:                ; Used to calculate the size of the GDT



gdt_desc:                       ; The GDT descriptor
        dw gdt_end - gdt - 1    ; Limit (size)
        dd gdt                  ; Address of the GDT




times 510-($-$$) db 0           ; Fill up the file with zeros

        dw 0AA55h                ; Boot sector identifyer

I am not using a linker script to compile this code, this is the steps I take.

1: Use NASM to compile the first sector into a binary file
nasm bootsect.asm -f bin -o bootsect.bin

2: Compile my C source file(s), main.c into an object file
gcc -c main.c -o main.o

3: Link the object file(s) to create another object file, kernel.o
ld -i -e _start -Ttext 0x1000 -o kernel.o main.o

4: Create a binary file from kernel.o
objcopy -R .note -R .comment -S -O binary kernel.o kernel.bin

5: Now I use a utility that adds the kernel.bin to the end of boot.bin that nasm created to create one image that I load into the operating system

Im sure this may not be the best way to do this, maybe you could lead me in the right direction?
Thank you

Re: OS keeps crashing

Posted: Mon Nov 23, 2009 8:41 pm
by NickJohnson
I think I know what the problem is - your print() function is being put first in the kernel.bin file, so it is executed first and runs off the end (possibly into an infinite recursion once hitting the main() function). Because you simply jump to 0x1000 from the bootsector, you aren't guaranteed that you get to main().

One way to fix this is to compile the main() function in a separate object file, then make sure that the object file is listed first in the arguments to ld. I think a better way is with a linker script, but I don't want to go hunting through the docs right now. One way to test this is to add a for(;;); statement at the end of your print() function: if it fixes it, print() was just being executed first.

Re: OS keeps crashing

Posted: Mon Nov 23, 2009 8:47 pm
by neon
In addition to NickJohnson's post, the "best" way is not loading a sector like that but an entire kernel image and executing its entry point. Its harder this way but in the long run is less error prone.

Re: OS keeps crashing

Posted: Mon Nov 23, 2009 9:27 pm
by Aphex
NickJohnson wrote:I think I know what the problem is - your print() function is being put first in the kernel.bin file, so it is executed first and runs off the end (possibly into an infinite recursion once hitting the main() function). Because you simply jump to 0x1000 from the bootsector, you aren't guaranteed that you get to main().

One way to fix this is to compile the main() function in a separate object file, then make sure that the object file is listed first in the arguments to ld. I think a better way is with a linker script, but I don't want to go hunting through the docs right now. One way to test this is to add a for(;;); statement at the end of your print() function: if it fixes it, print() was just being executed first.
You are right, thanks alot NickJohnson, I kinda should have seen that :oops:

I know of some tutorial's on linker scripts, Thank's loads for the help.

Also, thank you neon, Ill bear that in mind.

Re: OS keeps crashing

Posted: Tue Nov 24, 2009 4:54 am
by Owen
Another important point: you dont load es, which is used implicitly by some instructions (those using edi iirc?)