A simple hello world "OS" - created purely for the purpose of learning more about OS concepts. Functionality includes a simple bootloader which switches to 32 bit protected mode, and a kernel which provides basic VGA graphics and PS/2 keyboard support.
Ensure that qemu and nasm are installed:
apt-get install nasm
apt-get install qemu qemu-kvm
Build and start qemu:
make run
The cross compiler can either run within docker, or can be installed on your host machine:
./install_crosscompiler.sh all
This will enable access to both i686-elf-gcc
, i686-elf-ld
, and i686-elf-gdb
, which can be used to compile and debug the OS.
This script has been tested on Ubuntu, Docker, and OS X.
It might be useful to run the cross compiler within docker. To run an interactive terminal within the current directory:
docker build -t osbuilder .
docker run --rm -it -v $(pwd):$(pwd) -w $(pwd) osbuilder
The OS image can then be created within docker via:
make
This will generate an os.img
file which can be loaded into qemu, either directly on your host or with docker:
make curses
To exit qemu in curses mode, press Esc+2
, and within the qemu menu type quit.
Example:
You can use pwndbg:
make debug
Bochs, an alternative to qemu, provides additinoal graphical debugging functionality. This is useful for showing the contents of registers, the IDT, the GDT, and paging information:
make clean bochs
To trigger a bochs breakpoint within assembly:
xchg bx, bx
Or within C:
asm("xchg %bx, %bx");
For now the kernel attempts to its internal logs to:
- bochs -
serial.out
- qemu - stdout
Currently the memory layout is:
---------------------------
VGA text mode buffer
--------------------------- [0xB8000]
Unused
--------------------------- [0x90000] <-- Stack pointer. Grows downwards. Set by the bootloader.
vvvvv Stack vvvvv
^^^^^ heap ^^^^^
--------------------------- [0x50000] <-- Heap pointer. Grows upwards. Set by mem.c for now.
Unused
--------------------------- [0x7e00]
Boot Loader
512 Bytes
(Loads Kernel at 0x1000)
--------------------------- [0x7C00]
Kernel Loaded
--------------------------- [0x1000]
BIOS / etc.
--------------------------- [0x0000]
To view the sections of the kernel:
make kernel.elf
readelf --sections kernel.elf
- If the kernel becomes too large, reading from disk will trample 0x7c00 - our bootloader
- The stack grows downwards in terms of memory
- The easiest way to see specific calling conventions between the
caller
andcallee
is with godbolt, in conjunction with reading Calling convention - Useful commands: dumping stack
x/100w $esp+4
,info registers
,info frame
- You can use
si
to step from C extern calls directly into the assembly instructions
- Writing a simple bootloader
- Writing a simple operating system - from scratch
- os-tutorial
- Brans's kernel development tutorial
- JamesM's kernel development tools
- Intel® 64 and IA-32 Architectures Software Developer’s Manual
- print memory address and value of c arguments
- Ascii escape sequences
- OS Interrupts