OS keeps crashing

Programming, for all ages and all languages.
Post Reply
Aphex
Posts: 15
Joined: Mon Nov 23, 2009 5:57 pm

OS keeps crashing

Post 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
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: OS keeps crashing

Post 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.
Aphex
Posts: 15
Joined: Mon Nov 23, 2009 5:57 pm

Re: OS keeps crashing

Post 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
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: OS keeps crashing

Post 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.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: OS keeps crashing

Post 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.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
Aphex
Posts: 15
Joined: Mon Nov 23, 2009 5:57 pm

Re: OS keeps crashing

Post 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.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: OS keeps crashing

Post by Owen »

Another important point: you dont load es, which is used implicitly by some instructions (those using edi iirc?)
Post Reply