Diese Seite zeigt, wie man Lyx OS baut, in QEMU startet und ein erstes Ring-3-Programm schreibt. Voraussetzung sind Grundkenntnisse in der Lyx-Sprache und einer Linux-Kommandozeile.
→ Übersicht · Architektur · Anwendungen entwickeln
Alle benötigten Tools müssen im PATH verfügbar sein:
# Debian / Ubuntu
sudo apt install nasm qemu-system-x86 ovmf gdisk dosfstools mtools
# Compiler (muss bereits installiert sein)
lyxc --version # erwartet: lyxc version 0.9.3B
| Tool | Zweck |
|---|---|
nasm | UEFI-Bootloader aus boot.asm assemblieren |
qemu-system-x86_64 | LyxOS in einer virtuellen Maschine starten |
ovmf | UEFI-Firmware für QEMU (OVMF_CODE.fd + OVMF_VARS.fd) |
sgdisk (gdisk) | GPT-Partitionstabelle auf dem Disk-Image anlegen |
mformat, mmd, mcopy (mtools) | FAT32-Partition befüllen |
lyxc | Lyx-Kernel und Ring-3-Programme kompilieren |
git clone https://github.com/lyxos/lyx-os.git # oder eigenes Verzeichnis
cd lyx-os
Das Repository hat folgende Struktur:
lyx-os/
├── bootloader/ ← NASM-Bootloader (boot.asm), build.sh, run.sh
├── kernel/ ← Kernel-Module in Lyx (.lyx / .lyu)
├── shell/ ← Ring-3-Shell (shell.lyx)
├── examples/ ← Beispielprogramme für LyxOS
└── doku/ ← Interne Spezifikationen (syscalls.md, fahrplan.md)
bash bootloader/build.sh
Das Skript führt vier Schritte aus:
BOOTX64.EFI aus bootloader/boot.asm (NASM, PE32+-Format).lyu-Units und linkt kernel.elflyx_boot.img) mit GPT-Partitionstabelle und FAT32-EFI-PartitionBOOTX64.EFI nach /EFI/BOOT/ und kernel.elf in die PartitionErwartete Ausgabe (gekürzt):
[1/4] Assembling bootloader...
BOOTX64.EFI 10240 bytes
[2/4] Compiling kernel...
kernel.elf 98304 bytes
[3/4] Building bootable disk image...
[4/4] Staging ESP directory...
Build complete.
Disk image : bootloader/lyx_boot.img
Boot with: bash bootloader/run.sh
bash bootloader/run.sh
QEMU startet mit 256 MB RAM, KVM-Beschleunigung und OVMF-Firmware. Kernel-Ausgaben erscheinen direkt im Terminal (COM1 → stdio).
bash bootloader/run.sh --headless # kein Grafikfenster (nur serielle Ausgabe)
bash bootloader/run.sh --no-kvm # Software-Emulation ohne KVM (langsamerer, aber überall nutzbar)
Lyx OS v0.1 - Kernel running
PMM: init... free pages: 65432
VMM: identity map + CR3 load... CR3=0x200000 OK
Exceptions: IDT loaded (256 gates)
SMP: 4 CPUs detected, APs started
ATA: disk ready
FAT32: init OK
VFS: mounted
Keyboard: ready
Lyx Shell v0.1 - Ring-3 active
Exit.
Debug-Ausgaben werden zusätzlich nach /tmp/lyx_debugcon.txt geschrieben.
Ring-3-Programme werden mit lyxc –target=lyxos kompiliert. Das Target löst alle Standard-Builtins (PrintLn, mmap usw.) auf LyxOS-Syscalls auf — keine libc-Abhängigkeit.
Erstelle hello.lyx:
fn main(): int64 {
PrintLn("Hallo von Ring-3!");
return 0;
}
Kompilieren:
lyxc --target=lyxos hello.lyx -o hello.elf
Das Binary hello.elf ist ein ELF64-Executable das direkt auf LyxOS läuft. Es verwendet ausschließlich den sys_write- und sys_exit-Syscall — kein Userspace-Linking gegen Bibliotheken.
Hinweis: Die Shell in M4 startethello.elfnoch nicht automatisch. Das vollständige Programm-Laden aus dem Dateisystem ist Teil von M5. Für jetzt: das Binary inkernel.elfintegrieren und beim Systemstart aufrufen.
Wer Syscalls direkt nutzen möchte, ohne Builtins:
// Syscall-Nummern als Konstanten
con SYS_WRITE: int64 := 0x0203;
con FD_STDOUT: int64 := 1;
fn WriteLn(msg: pchar) {
// sys_write(fd, buf, len) → rax=Fehler, rdx=bytes
var msg_len: int64 := StrLen(msg);
// Lyx --target=lyxos mappt sys_write auf das native syscall-Gate
var err: int64 := 0;
var written: int64 := 0;
// Inline-Syscall via Compiler-Builtin (verfügbar ab M5):
// (err, written) := syscall(SYS_WRITE, FD_STDOUT, msg, msg_len);
}
→ Vollständige Syscall-Referenz: Syscall-ABI v1.0
PrintLn und PrintStr aus Kernel- und Ring-3-Code erscheinen beide auf COM1 → Terminal. Kein separates Debug-Interface nötig.
PrintStr an einen speziellen Debug-Port schreibt nach /tmp/lyx_debugcon.txt:
tail -f /tmp/lyx_debugcon.txt
Im laufenden QEMU: Ctrl-Alt-2 wechselt in den QEMU-Monitor. Nützliche Befehle:
info mem # aktueller Page-Table-Dump
info registers # CPU-Registerstand
x/10i $pc # Disassembly ab aktuellem Instruction Pointer
Letzte Aktualisierung: 2026-06-09