So I've been interested in doing this for a while, and I have quite a bit of C/C++ experience, and a little assembly. I didn't really want to use GRUB to boot my OS, as I want it to be entirely "my OS" rather than grub booting a kernel. Anywho, so at the moment my kernel is very simple:
Code: Select all
// kernel.c
void kmain( void )
{
unsigned char * vram = (unsigned char *)0xb8000;
int i;
for( i = 0; i < 20; ++i )
{
if( i % 2 == 0 ) vram[i] = 65;
else vram[i] = 0x07;
}
}
Code: Select all
; and asmkernel.asm
%define STACKSIZE 0x4000
global load_kernel
extern _kmain
section .text
align 4
load_kernel:
mov esp, stack+STACKSIZE ; Set stack pointer so we can safely
; push back into the stack
call _kmain ; Call kmain() from kernel.c
hlt ; halt should it return
section .bss
align 32
stack:
resb STACKSIZE
Code: Select all
//Linker script here
ENTRY (load_kernel)
SECTIONS{
. = 0x00100000;
.text :{
*(.text)
}
.rodata ALIGN (0x1000) : {
*(.rodata)
}
.data ALIGN (0x1000) : {
*(.data)
}
.bss : {
sbss = .;
*(COMMON)
*(.bss)
ebss = .;
}
}
// And then compiled with the following commands
nasm.exe -f elf -o asmkernel.o asmkernel.asm
gcc.exe -o kernel.o -c kernel.c -Wall -Wextra -Werror -nostdlib -nostartfiles -nodefaultlibs
ld.exe -T linker.ld -o kernel.bin asmkernel.o kernel.o
Code: Select all
[BITS 16]
[ORG 0x7C00]
; Start the code
section .text
jmp 0x0000:load_kernel
load_kernel: ; use the int 13h bios call to read more data from floppy
mov bx, 0x2000 ; segment to read into
mov es, bx ; can't read directly into segment registers damn them
mov bx, 0x0000 ; offset to read into
mov ah, 0x02 ; BIOS read sector function code
mov al, 0x05 ; read 5 sectors (this is because the kernel is 2.35kb, rounds up to 5*512)
mov ch, 0x01 ; read track 1, won't need to worry about track 2 unless the kernel gets pretty big
mov cl, 0x02 ; start reading at sector 2
mov dh, 0x00 ; head 0
mov dl, 0x00 ; Drive 0 (floppy 1)
attempt_load:
int 0x13
jc load_fail ; if there was an error carry flag will be set, say so and try again
load_success:
mov ax, bSuccess
call print_string
mov ax, 0x2000
mov ds, ax
mov ax, 0x0000
mov es, ax
jmp 0x2000:0x0000 ; jump to kernel
load_fail:
mov ax, bFailure
call print_string
mov ah, 0x02 ; restore ax register
mov al, 0x05 ;
jmp attempt_load
print_string:
.init:
mov si, ax ; move parameter into si
mov ax, 0000h ; set up ds with 0, so we'll have 0000:string
mov ds, ax
mov ah, 0eh ; char printing bios function code
mov bh, 00h ; page number.. Dunno, just leave 0 I think =/
mov bl, 07h ; text attribute, white text black bg
.put_char:
lodsb ; ok so in case I forget, this loads the byte at DS:SI
; into AL and incs SI, which is what the bios
; char printing function uses to store the character
cmp al, 0 ; if char is 0, end of string
je .return
int 10h ; else print char and jump back
jmp .put_char
.return:
ret
section .data ; stick any initialised data here
bFailure db "Kernel failed to load, trying again...", 0
bSuccess db "Successfully read kernel, booting...", 0
; Pad the end
times 430-($-$$) db 0
; Bootloader signature, probably not needed on modern machines
dw 0xAA55
Code: Select all
nasm.exe boot.asm
But it just seems to successfully read the floppy and then stop...
Any ideas?
Thanks in advance
Spec
EDIT: Updated code