# kernel — болваночное ядро + загрузчик (Plan9 a.out) Ядро-болванка, которое пишет строку в VGA-текстбуфер **0xB8000**, и **загрузчик**, который грузит его. Всё в формате **Plan9 a.out** (не ELF) — потому что наш kencc-выхлоп именно a.out; загрузчик разбирает a.out-заголовок, а не ELF. ## Файлы * `kern.s` — энтрипоинт на 386-асме: ставит стек, зовёт `kmain`. * `kernel.c` — ядро: пишет `PLAN9 KERNEL STUB -> writes to 0xB8000` в 0xB8000. * `loader.c` — загрузчик Plan9 a.out: разбор заголовка (big-endian), загрузка сегментов `[text][data]` по адресу линковки, обнуление bss, прыжок в entry. * `loader_test.c` — хостовый тест: прогоняет `aout_parse` из настоящего загрузчика на собранном ядре и печатает поля (magic/entry/размеры). * `mkboot.sh` — сборка: `8a`+`8c`+`8l` -> `kernel` (a.out), `8c` -> `loader.8`. ## Сборка ```sh BINDIR=../bin ./mkboot.sh ``` ## Формат Plan9 a.out (386) 32-байтный заголовок, **big-endian**, 8 полей по 4 байта: ``` magic text data bss syms entry spsz pcsz ``` `magic == I_MAGIC == 0x1EB` (intel 386). Сегменты идут сразу за заголовком: `file[32 .. 32+text]` = text, дальше data. Загрузчик копирует их по `entry` (равен `-T` линкера, тут `0x100000`), зануляет bss и прыгает в `entry`. ## Что проверено ``` kernel: Plan9 a.out, magic=0x1EB (I_MAGIC 386), entry=0x100000, константа 0xB8000 присутствует в коде. loader: aout_parse на реальном kernel -> OK, entry=0x100000, text/data сходятся. ``` Реальный запуск в QEMU/Bochs не гонялся (в контейнере нет эмулятора), но kernel — валидный a.out, а загрузчик корректно его разбирает и знает, куда грузить и куда прыгать. > Хочешь под GRUB/multiboot — можно докинуть a.out→ELF-обёртку; здесь же честный > a.out-путь под твоё «выхлоп у нас в а.аут».