Доброго дня, уважаемые читатели. В статье начнем писать ядро операционной системы. В предыдущей статье был подготовлен загрузчик для нашей Simple OS. Однако чистый черный экран не вызывал чувства исполненного долга. В качестве первого шага я напишу на ассемблере строку с названием операционной системы и версию ядра. Предположим что текущая версия — 0.0.1. Значит нужно вывести на экран следующую строку:
Simple OS, version 0.0.1
Увы, знания о выводе строк на экран средствами BIOS больше не помогут. Они остались в прошлом, в режиме реальных адресов. В суровой действительности защищённого режима вывести текст на экран поможет лишь прямая запись в видеопамять.
Видеопамять
Видеопамять — это внутренняя память, предназначенная для хранения данных изображения, которое выводится на экран. Адрес начала видеопамяти в текстовом режиме для цветных мониторов: 0xB8000, а для монохромных: 0xB0000. Каждый символ кодируется двумя байтами. Первый байт это ASCII-код символа. Второй вмещает в себя в младших 4-х битах цвет текста, в старших 3-х битах цвет фона и в последнем бите — конфигурацию оборудования.
Если в байт атрибута будет установлено, например, значение 0x1F, то на экран выведутся белые символы на синем фоне. Пользователям Windows знакомо такое сочетание цветов :).
Но мы будем пользоваться другим цветом. В DOS используется сочетание светло-серый шрифт на черном фоне. Примем значение 0x07 временно за эталон.
Очистка экрана
С очисткой экрана, думаю, все просто. Нам надо заполнить весь экран пробелами — ‘ ‘. Длина массива данных для формирования изображения высчитывается по простой формуле:
80 символов * 25 строк * 2 байта = 4000 байт
mov ebx,0xB8000 mov dx, 0 clean: cmp dx, 4000 je done_clean mov al, ' ' mov ah, 0x07 mov [ebx], ax add ebx, 2 add dx, 2 jmp clean done_clean:
Как видно в коде, в регистр ebx (помним что сейчас мы работаем в 32-битной среде) нужно поместить значение адреса начала видеопамяти — 0xB8000. В цикле помещаем нужные значения в регистры: al — символ пробела, а в ah — цвет. Далее помещаем значение ax по адресу, хранимому в ebx. Увеличиваем значение адреса и регистр цикла dx на 2, возвращаемся и повторяем процедуру пока dx не станет равен 4000. Профит!
Вывод текста
Теперь делаем практически то же самое для текста:
mov ebx,0xB8000 mov edx,OS_DETAILS print: mov al,[edx] cmp al, 0 je done mov ah,0x07 mov [ebx],ax add ebx, 2 add edx, 1 jmp print done: hlt OS_DETAILS: db 'Simple OS, version 0.0.1', 0
Код полностью
Хочу пояснить, что код выше исполняется, как ядро операционной системы. И оно уже отвечает нам, пусть и немудрено. Чтобы не оставалось вопросов приведу полный код вместе с загрузчиком.
section .multiboot_header header_start: dd 0xE85250d6 dd 0 dd header_end - header_start dd 0x100000000 - (0xE85250D6 + 0 + (header_end - header_start)) dw 0 dw 0 dd 8 header_end: section .text bits 32 global start start: cli mov esp, stack_space mov ebx,0xB8000 mov dx, 0 clean: cmp dx, 4000 je done_clean mov al, ' ' mov ah, 0x07 mov [ebx], ax add ebx, 2 add dx, 2 jmp clean done_clean: mov ebx,0xB8000 mov edx,OS_DETAILS print: mov al,[edx] cmp al, 0 je done mov ah,0x07 mov [ebx],ax add ebx, 2 add edx, 1 jmp print done: hlt OS_DETAILS: db 'Simple OS, version 0.0.1', 0 section .bss resb 8192 stack_space:
Надеюсь , что вам так же интересно как и мне. Вскоре мы постараемся вырваться из оков ассемблера и подняться на уровень выше! До свидания!
Картинки видеокарты и синего экрана найдены на просторах интернета.