Exploring MikeOS: Source Code Walkthrough and Key Components

Exploring MikeOS: Source Code Walkthrough and Key ComponentsMikeOS is a compact educational operating system written primarily in 16-bit x86 assembly. Its small size, readable code, and clear structure make it an excellent learning platform for anyone interested in low-level programming, OS fundamentals, and how hardware and software interact at the bare-metal level. This article walks through MikeOS’s source code, explains its key components, and highlights practical exercises to deepen understanding.


Quick overview and goals

MikeOS is designed to be:

  • Simple and small: The entire system fits in a few kilobytes, uses BIOS services for I/O, and avoids protected-mode complexities.
  • Educational: Source code is deliberately clear, with comments and modular structure to teach concepts such as bootloading, segment-based memory, interrupts, and simple file systems.
  • Executable: It runs in emulators (Bochs, QEMU, VirtualBox) and on real x86 hardware that supports 16-bit real mode.

Project layout and main files

A typical MikeOS repository contains:

  • boot/ — boot sector and initial assembly
    • boot.asm — the 512-byte bootsector that the BIOS loads
  • src/ — core OS code
    • main.asm — main entry and kernel initialization
    • console.asm — text I/O routines
    • keyboard.asm — keyboard handling and buffering
    • disk.asm — floppy/disk read routines (if present)
    • irq.asm / timer.asm — interrupt handlers (timer, keyboard)
    • shell.asm — simple command shell and command table
    • apps/ — simple bundled applications (hello, calc, editor)
  • include/ — shared constants, macros
    • macros.inc, const.inc, bios.inc
  • tools/ — build scripts and utilities
  • mikeos.img / floppy image — built disk image

Boot sector (boot.asm)

The boot sector is the first code the BIOS executes. Important points:

  • Must be exactly 512 bytes and end with the signature 0x55 0xAA.
  • Runs in real mode with DS=ES=CS segments set by BIOS; typically starts at 0x7C00 physical.

Key responsibilities:

  • Set up segment registers and stack.
  • Load the kernel code from disk into memory (commonly at 0x1000:0x0000 or similar).
  • Switch to a known state and jump to the kernel entry point.

Typical boot flow (simplified):

  1. Disable interrupts (cli).
  2. Set DS, ES to point at boot data and temporary stack.
  3. Use BIOS INT 13h to read sectors from disk into memory.
  4. Verify success and jump to kernel start.

Examining the boot sector teaches disk access via BIOS interrupts, error handling, and the tight size constraints of 512 bytes.


Kernel entry and initialization (main.asm)

Once the bootloader transfers control to the kernel, the kernel performs setup steps:

  • Initialize segment registers and relocate data segments.
  • Set up the stack: kernels commonly set stack pointer to a safe memory region.
  • Initialize hardware IRQs and the Interrupt Vector Table (IVT) entries that the OS will use.
  • Clear or set up BSS/data areas used by the kernel.

In MikeOS, main.asm typically:

  • Calls an initialization routine for the console.
  • Sets up keyboard interrupt handling (installing an ISR at int 9 or remapped PIC IRQ).
  • Enters the command shell loop.

Key learning points:

  • Real mode memory model: segmentation, offsets, and effective addresses.
  • Stack discipline and why kernels need controlled stacks.
  • How the IVT works in real mode: each interrupt vector is a 4-byte far pointer at 0000:0000 + 4 * int_number.

Console and text I/O (console.asm)

Console routines in MikeOS are simple but essential for interaction. There are two main approaches:

  • Use BIOS teletype (INT 10h, AH=0Eh) to print characters.
  • Write directly to text-mode video memory at 0xB800:0000 for speed and control.

MikeOS demonstrates both approaches; the kernel often uses direct video memory for cursor control and faster output. Typical routines include:

  • cls — clear screen by writing spaces with attribute bytes.
  • putchar — write a character at cursor position, handle newlines, carriage returns.
  • putstr / printf-like — loop over characters and output.

Examining console.asm shows text-mode video memory layout: each character cell is two bytes (character and attribute), and the screen is 80×25 by default.


Keyboard input and buffering (keyboard.asm)

Keyboard handling can be polled or interrupt-driven. MikeOS uses interrupt-driven handling to capture keypresses asynchronously.

Core elements:

  • Interrupt Service Routine (ISR) for IRQ1 (keyboard).
  • Read scancode from I/O port 0x60.
  • Translate scancodes to ASCII using a table (handling shift/caps lock via status flags).
  • Place characters into a circular buffer for the shell to read.

Challenges and teaching points:

  • IRQs and PIC (Programmable Interrupt Controller): remapping PIC to avoid conflicts with CPU exceptions is common in more advanced OSes; MikeOS uses default real-mode mapping (IRQ0..IRQ7 -> int 8..15).
  • Debouncing and dealing with key releases (make/break codes).
  • Synchronization between ISR context and main kernel when accessing the buffer.

Interrupt handling and PIT (irq.asm, timer.asm)

MikeOS usually installs simple handlers for:

  • Timer tick (IRQ0) — can be used for timekeeping or simple multitasking.
  • Keyboard (IRQ1) — input capture.

Handlers must:

  • Save registers and processor state.
  • Acknowledge the PIC by sending End of Interrupt (EOI) to port 0x20 (and 0xA0 if using slave PIC).
  • Restore registers and issue IRET.

Examining these handlers shows the need to preserve CPU state, the IRET instruction semantics, and how hardware-generated interrupts transfer control into the OS.


Simple shell and command table (shell.asm)

MikeOS provides a small command-line shell that:

  • Prints a prompt.
  • Reads input from the keyboard buffer.
  • Tokenizes input and matches commands in a command table.
  • Dispatches to built-in commands or loads/runs simple apps.

Common built-in commands:

  • help — list commands.
  • cls — clear screen.
  • echo — print arguments.
  • run — execute an included app.

The shell demonstrates parsing strategies in tight assembly code, string handling, and how to structure a command table — typically a list of command names with pointers to handler routines.


Applications (apps/)

MikeOS bundles tiny apps implemented in assembly:

  • hello — prints a greeting.
  • calc — simple arithmetic demonstration.
  • editor — minimal text editor.
  • pong or tiny games in some forks.

Apps are linked or loaded at runtime by the kernel’s simple loader. Studying app code shows how to use kernel services (print, read), manage stack/locals, and return control to the shell.


Disk access and filesystem basics (disk.asm)

Some MikeOS variants include simple disk I/O code and a tiny filesystem abstraction:

  • Use BIOS INT 13h for sector read/write.
  • A minimal file table: fixed-size directory or simple linear list of files stored in specific sectors.
  • A loader that reads app sectors into memory and jumps to them.

This shows how higher-level concepts like files can be implemented on top of block devices using small, fixed data structures.


Build process and emulation

Typical build steps:

  1. Assemble code with NASM: nasm -f bin boot/boot.asm -o boot.bin
  2. Assemble kernel/object files and link or concat into an image.
  3. Create a floppy image (often by concatenation or using a tool like dd).
  4. Run in emulator: qemu-system-i386 -fda mikeos.img

Examining build scripts helps you understand flat binary formats, offsets for boot sectors, and how to package a runnable image.


Key concepts illustrated by MikeOS

  • Real mode vs. protected mode: MikeOS stays in real mode, avoiding descriptor tables and paging; this simplifies code while teaching segmentation.
  • BIOS interrupts: keyboard, video, disk services demonstrate interaction with firmware.
  • Interrupt vectors and ISRs: installing and writing safe interrupt handlers.
  • Memory layout: conventional memory limits and where OS code/data live in low memory.
  • Minimal process model: “programs” are just code loaded and jumped into — useful to illustrate control transfer and simple program lifecycle.
  • I/O buffering and concurrency basics: shared data between ISRs and main code.

Code walkthrough: selected snippets and explanations

Below are concise conceptual examples (not full files) highlighting common patterns.

Bootloader: setting segment registers and loading kernel

; (conceptual) org 0x7C00 cli xor ax, ax mov ds, ax mov es, ax mov ss, 0x0000 mov sp, 0x7C00 ; load kernel sectors via INT 13h into 0x1000:0x0000 ; jump to 0x1000:0x0000 

ISR prologue/epilogue pattern

; save registers push ax push bx push cx push dx ; ... ISR work ... ; send EOI mov al, 0x20 out 0x20, al ; restore registers pop dx pop cx pop bx pop ax iret 

Console write to video memory

; video base at 0xB800:0000 mov si, [cursor_offset] mov di, 0xB8000 + si*2 mov [di], 'A'        ; ascii mov [di+1], attr     ; attribute 

Keyboard handler: read scancode and push to buffer

in al, 0x60          ; read scancode ; translate scancode -> ascii (using table) ; store in circular buffer (head++) ; send EOI, iret 

These snippets are intentionally simplified; MikeOS’s real source contains full tables, error checks, and size-optimized implementations.


Exercises to learn by doing

  1. Add support for arrow keys in the shell — extend the scancode translation and implement simple line editing (move cursor, delete).
  2. Implement a very small file index: reserve sectors for a file table and add commands to list / load files.
  3. Replace BIOS text output with direct VGA cursor handling and implement colored output attributes.
  4. Add a timer-based blinking cursor using IRQ0 and a simple count to toggle a screen cell attribute.
  5. Port a tiny C runtime: write a minimal C entry and compile with a cross-compiler to call into MikeOS services (advanced).

Where to look in the source for key learning points

  • Boot quirks and sector loading: boot/boot.asm.
  • Interrupt setup and handlers: irq.asm, keyboard.asm, timer.asm.
  • I/O: console.asm (video memory), disk.asm (INT 13h calls).
  • Shell logic and command dispatch: shell.asm.
  • Small app examples: apps/hello.asm, apps/editor.asm.

Limitations and next steps beyond MikeOS

MikeOS purposefully avoids complexities like protected mode, multitasking, memory protection, and advanced device drivers. After mastering MikeOS, natural next steps include:

  • Writing a simple protected-mode kernel with GDT/IDT setup.
  • Implementing paging and a simple memory allocator.
  • Building a preemptive scheduler and context switching.
  • Learning device drivers (ATA, PCI) and more realistic filesystems (FAT).

Conclusion

MikeOS is a compact, well-documented educational OS that maps the theoretical concepts of operating systems to concrete, readable assembly code. Walking through its bootloader, kernel, interrupt handlers, and apps gives a deep, practical understanding of how x86 machines boot and run software at the lowest level. Use the exercises above to turn passive reading into hands-on skill building.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *