User:Imate900/32-bit assembler bare bones

From OSDev.wiki
Jump to navigation Jump to search
Difficulty level

Medium
Kernel Designs
Models
Other Concepts

This tutorial will teach you how to make a 32-bit assembler kernel.

GRUB

All we need is something like this (GNU as):

.global loader # making entry point visible to linker

# setting up the Multiboot header - see GRUB docs for details
.set ALIGN, 1<<0 # align loaded modules on page boundaries
.set MEMINFO, 1<<1 # provide memory map
.set FLAGS, ALIGN | MEMINFO # this is the Multiboot 'flag' field
.set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header
.set CHECKSUM, -(MAGIC + FLAGS) # checksum required

.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM

_start:
# Write the kernel here
jmp _start

Link with:

as -o kernel.o kernel.s
ld --oformat binary -o kernel.bin kernel.o

For NASM:

global loader ; making entry point visible to linker

; setting up the Multiboot header - see GRUB docs for details
ALIGN equ 1<<0 ; align loaded modules on page boundaries
MEMINFO equ 1<<1 ; provide memory map
FLAGS equ ALIGN | MEMINFO ; this is the Multiboot 'flag' field
MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
CHECKSUM equ -(MAGIC + FLAGS) ; checksum required

mboot:
dd MAGIC
dd FLAGS
dd CHECKSUM

_start:
; Write the kernel here
jmp _start

Link with:

nasm -f bin kernel.asm

Make sure you have a GRUB entry...

title Assembler Barebones
kernel (hd0,0)/boot/kernel.bin

Now, reboot, and enjoy!

Without GRUB

Starting In Protected Mode

If your bootloader loads flat binary images and gives you protected mode for you, use this code as a basis:

_start:
 ; Write kernel here. It might be good to load a new GDT. I include the GDT business here nevertheless.
 lgdt [kern_gdtr]
 jmp 0x08:normalize_regs
normalize_regs:
 mov ax, 0x10 ; 0x10 points at the new data selector
 mov ds, ax
 mov es, ax
 mov fs, ax
 mov gs, ax
 mov ss, ax
 jmp kernel

kernel:
 ; After all that tricky business! Write your kernel here, anyway.
 jmp kernel

kern_gdt:
 db 0, 0, 0 ; null entry
 db 0, 0xffffffff, 0x9A
 db 0, 0xffffffff, 0x92

kern_gdtr DW 0 ; For limit storage
          DD 0 ; For base storage

Starting In Real Mode

Usually (in most FAT bootloaders), you must first switch to Protected Mode in order to write a 32-bit kernel if your kernel starts in Real Mode. For reference, this code is enough (GDT is composed of null entry, a code entry and a data entry:)

BITS 16
cli
lgdt [kern_gdtr]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x08:normalize_regs
BITS 32
normalize_regs:
 mov ax, 0x10 ; 0x10 points at the new data selector
 mov ds, ax
 mov es, ax
 mov fs, ax
 mov gs, ax
 mov ss, ax
 jmp kernel

kernel:
 ; After all that tricky business! Write your kernel here, anyway.
 jmp kernel

kern_gdt:
 db 0, 0, 0 ; null entry
 db 0, 0xffffffff, 0x9A
 db 0, 0xffffffff, 0x92

kern_gdtr DW 0 ; For limit storage
          DD 0 ; For base storage