.code16 # tell the assembler that we're using 16 bit mode .include "gdt.s" .section .text .global init # makes our label "init" available to the outside .globl mainentry init: # this is the beginning of our binary later. #jmp init # jump to "init" #ljmpw $0xFFFF, $0 # jumps to the "reset vector", doing a reboot call printhelloworld jmp switchto32bit switchto32bit: # Load Global Descriptor Table lgdt gdt32ptr # Load Control Register CR0 # Enable Protected Mode (Bit0 in CR0) # Store Control Register CR0 movl %cr0, %eax orl $(1<<0), %eax movl %eax, %cr0 # Setup all Segment Registers # and reload Code Segment, Instruction Pointer movw $0x0010, %ax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs movw %ax, %ss ljmp $0x0008, $JumpToPM .code32 JumpToPM: call mainentry ljmpw $0xFFFF, $0 # jumps to the "reset vector", doing a reboot printhelloworld: mov $0x0e, %ah # function mode -> display char mov $'S', %al int $0x10 # video bios interrupt mov $'T', %al int $0x10 # video bios interrupt mov $'A', %al int $0x10 # video bios interrupt mov $'R', %al int $0x10 # video bios interrupt mov $'T', %al int $0x10 # video bios interrupt .fill 510-(.-init), 1, 0 # add zeroes to make it 510 bytes long # . is current position - start position .word 0xaa55 # magic bytes that tell BIOS that this is bootable # x86 is little endian - so bytes are swapped in memory!