Exploring MikeOS Source Code: Key Components ExplainedMikeOS is a small, open-source, hobbyist operating system written in assembly language for the 16-bit x86 architecture. It was created by Mike Saunders to teach operating system concepts and assembly programming by providing a compact, readable codebase that boots on real and emulated hardware. This article dissects the MikeOS source code, explaining its main components, structure, and how they interact. Wherever helpful, I include concrete examples and pointers to where particular functions or behaviors appear in the codebase.
Overview and goals
MikeOS aims to be small, well-documented, and easy to understand. Its design priorities are:
- Simplicity: minimal features to make the codebase approachable.
- Education: clear comments and structure to teach OS concepts.
- Portability to emulators and real hardware: it runs in QEMU, Bochs, VirtualBox, and on real x86 PCs.
The system is a 16-bit real-mode OS, meaning it runs directly on BIOS without protected mode or advanced memory management. This limits its functionality but keeps the code straightforward.
Project layout and build system
A typical MikeOS repository contains:
- boot/ — bootstrap and bootloader code
- kernel/ — kernel routines and system call handlers
- apps/ — example applications (text editor, calculator, etc.)
- tools/ — build scripts and utilities
- docs/ — documentation and tutorials
- Makefile / build scripts — assemble and create floppy or disk images
The project uses NASM for assembly. The build system assembles .asm files, links or concatenates binaries, and creates a bootable image (often a floppy image) that emulators can run.
Boot process and bootloader
The bootloader is the first code executed by the BIOS after the BIOS loads the boot sector into memory at address 0x7C00 and transfers control to it. Key points:
- The boot sector is exactly 512 bytes with the 0xAA55 signature in the last two bytes.
- The bootloader sets up the initial stack and data segments, then loads the rest of the OS (kernel and apps) from the disk into memory.
- Because MikeOS uses a simple single-stage or two-stage bootloader (depending on version), it often loads additional sectors into memory using BIOS interrupt 0x13 (disk services).
Example responsibilities in the boot code:
- Switch to appropriate segment values (CS:IP already set by BIOS).
- Initialize stack at a safe RAM area.
- Use BIOS calls to read sectors from disk to memory.
- Jump to the kernel entry point.
Kernel: entry point and setup
Once the bootloader transfers control, the kernel initializes hardware and software state. Typical kernel tasks:
- Set up segment registers (DS, ES, SS).
- Initialize the display (text mode at VGA memory 0xB8000).
- Initialize keyboard handling and interrupt vectors.
- Provide system call dispatching for applications.
MikeOS sticks to BIOS and interrupt-based I/O rather than direct hardware drivers. The kernel maps human-friendly services (print string, read key, load/execute program) onto BIOS interrupts and internal handlers.
Interrupts and BIOS integration
MikeOS relies heavily on BIOS interrupts and the real-mode interrupt vector table (IVT) at 0x0000:0x0000. Important interrupts:
- INT 0x10 — video services (set mode, write character).
- INT 0x16 — keyboard services.
- INT 0x13 — disk services for reading sectors.
- INT 0x21 — DOS services are sometimes used or emulated for convenience.
The kernel sets up its own interrupt handlers for keyboard input and may hook BIOS interrupts to extend or change behavior. The code shows how to read keystrokes using INT 0x16 and how to write characters to the screen with INT 0x10 or by writing directly to VGA memory.
Console and text output
Text I/O in MikeOS is implemented in a small console subsystem. Two common approaches appear in the codebase:
- Using BIOS INT 0x10 to print characters (portable and simple).
- Directly writing to VGA text buffer at memory 0xB8000 for faster control and cursor management.
The kernel maintains cursor coordinates and provides functions for printing strings, handling backspace, newlines, and scrolling the screen by moving memory blocks.
Keyboard input and line editing
Keyboard handling typically uses INT 0x16 or hooks the BIOS keyboard interrupt. The OS implements a small line-editor routine that:
- Reads keys (including special keys like arrow keys, backspace).
- Updates an input buffer.
- Echoes characters to the console.
- On Enter, passes the buffer to the command interpreter.
Code demonstrates translating scan codes to ASCII and handling control keys. Special handling may be present for extended keys (function keys, arrows) by reading the two-byte scan sequences.
File loading and program execution
MikeOS can load and run simple, raw binary programs from the disk image. The mechanism usually is:
- File listing and simple file allocation method (MikeOS often uses a flat file list or a tiny filesystem).
- Read sectors containing the target program into a known memory location.
- Set up registers and stack, then far-jump or call into the loaded program.
Because the OS runs in real mode, programs are typically simple 16-bit binaries that follow calling conventions expected by MikeOS (for example, a small header or expected load address).
System calls and API for applications
MikeOS exposes services to applications through a software interrupt or a fixed entry point. Common design patterns:
- A designated interrupt (e.g., INT 0x40) where applications push function number and parameters, then invoke the interrupt to request services.
- Alternatively, applications call a known kernel address with registers set for parameters.
Services include printing text, reading keyboard input, opening/reading files, and exiting to the shell.
Example of a syscall flow:
- App sets AH = service number, other registers for parameters.
- App executes INT 0x21 (or chosen vector).
- Kernel dispatches to the appropriate handler and returns results in registers.
Sample applications and utilities
MikeOS includes example apps written in assembly to showcase system calls and OS capabilities: a text editor, calculator, alarm clock, and simple games. Each app demonstrates:
- Using kernel services (print/read).
- Handling input and basic UI.
- Loading and chaining programs.
Reading these apps is educational: they are compact and show practical use of the kernel API.
Memory layout and conventions
Because MikeOS runs in 16-bit real mode, it uses segment:offset addressing. Common conventions in the code:
- Kernel loaded at a specific segment (often 0x1000 or similar).
- Stack placed in a high memory area to avoid overlapping with data.
- Data and code segments defined with understandable labels and comments.
Understanding the memory map is crucial when modifying or adding features to avoid overwriting code or stacks.
Extending MikeOS: drivers and features
Adding features typically involves:
- Writing assembly routines for new hardware interactions.
- Hooking or creating new interrupts for services (e.g., timer, disk).
- Extending the filesystem or program loader.
Because of the simple structure, developers can incrementally add functionality: a sound driver that writes to the PC speaker port, or a rudimentary disk filesystem replacing the flat-file listing.
Debugging and emulation
Emulators like QEMU and Bochs are commonly used to test MikeOS. Debugging techniques include:
- Using emulator debug console or logs.
- Writing debug prints to the screen.
- Using Bochs’ built-in debugger or QEMU’s GDB stub to set breakpoints and inspect memory/registers.
The small codebase and linear flow make it easy to reason about behavior during boot and runtime.
Learning path: reading the code
Suggested steps to learn from the source:
- Start with the boot sector: understand stack setup and disk reading.
- Follow the kernel entry and initialization code.
- Inspect console and keyboard routines to see I/O handling.
- Read the program loader and one or two apps to understand syscall conventions.
- Modify a small piece (change boot message, add command) and rebuild/run.
Conclusion
MikeOS is intentionally minimal and well-documented, making it an excellent learning OS. Its source code demonstrates core OS concepts—bootstrapping, interrupts, text I/O, program loading—within a manageable assembly codebase. Exploring those components provides a hands-on way to learn low-level programming and system design.
If you want, I can: list specific files/functions to open first, produce annotated excerpts of key routines, or write a small patch (e.g., add a new syscall or simple driver).
Leave a Reply