Готовим систему
Чтобы разрабатывать свое ядро нам потребуется эмулятор виртуальной машины, который в принципе близок по возможностям к virtual box.
Для этого надо его установить
так же нам потребуется ассемблер
можно проверить что виртуалка работает если запустить команду
увидим, как запустится виртуалка и начнет пытаться загрузиться с чего-нибудь
Создаем сообщение
Мы будем тут работать с legacy режимом загрузки, то есть через чистый BIOS (без uefi), то есть когда система грузится с первого сектора загрузочного диска.
Размер сектора 512 байт, и последние два байта должны содержать 0xAA55
Простейший бут сектор должен содержать следующий код
eb fe 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[еще 29 строчек по 16 нулевых байт]
00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa
давайте напишем такой загрузчик
создаем новый файлик kernel.s и пишем в него
; бесконечный цикл, те самый (eb fe) сверху
loop:
jmp loop
; заполняем 510 нулевыми байтами минус размер в байтах кода выше
times 510-($-$$) db 0
; те самые магические байты в конце сектора
dw 0xaa55
а теперь соберем его в машинный код используя ассемблер nasm
появится файлик kernel
, можно глянуть его содержимое и
теперь можно запустить этот файлик
qemu-system-x86_64 kernel
система выглядит как будто грузится. Так как у нас бесконечный цикл, то мы навечно зависнем в этом состоянии
поздравляю, биос опознал ваш код как загрузочный и по сути у вас болванка операционной системы готова =)
Выводим сообщение
теперь воспользуемся механизмом прерываний, чтобы выводить текст. В BIOS встроен набор прерываний для работы с консолью. Список прерываний доступен тут https://en.wikipedia.org/wiki/BIOS_interrupt_call. Например, чтобы вывести текст, его надо выводить побуквенно. Для этого вызывается прерываний 0x10.
Так как процессор оперирует данными исключительно находящимися в регистрах процессора.
mov ah, 0x0e ; будет запрашивать вывод к консоль биоса
mov al, 'H' ; в регистр al положили символ для печати
int 0x10 ; вывзываем запрос на печать
mov al, 'e' ; ну и так на каждую букву
int 0x10
mov al, 'l'
int 0x10 ; буква l два раза поэтому просто два раза вызываем прерывание
int 0x10
mov al, 'o'
int 0x10
; остальное не трогаем
loop:
jmp loop
times 510 - ($-$$) db 0
dw 0xaa55
собираем
глядим содержимое собранного файлика
можно кстати вызывать обратное преобразование и увидеть, как байты сопоставляются командам
objdump -D -b binary -mi386 kernel
в общем запускаем
qemu-system-x86_64 kernel
и ура увидим наше приветственное сообщение