16-битная операционная система на коленках

—

от автора

Предисловие

Здравствуйте. Это моя первая статья, и она будет о разработке собственной операционной системы. Если в процессе чтения заметите какие либо ошибки или у вас более глубокие познания в этой области, пишите комментарии и я внесу правки. Автор ещё учится этому непростому ремеслу. Полный исходный код ОС будет приведён в конце статьи. ОС написана полностью на статью.

После нажатия на кнопку «Power«, системный контроллер расположенный на материнской плате, подаёт сигнал на включение процессору. Затем процессор загружает и исполняет код Постановка приоритетов загрузки ОС

Постановка приоритетов загрузки ОС

И слово было 0xaa55

Как я выразился выше, процессор «ищет» загрузочный сектор. В конце сектора должно быть магическое число 0xaa55. Благодаря этому магическому числу, процессор «понимает», что это загрузочный сектор, затем сгружает его в ОЗУ по адресу 0x7c00 и исполняет его в реальном режиме. В случае если жёсткий диск не содержит загрузочный сектор, вызывается прерывание 0x19 и процессор переходит к следующему диску. Если устройств больше нет, то выведет ошибку по типу «No bootable devices found.«.

Процессор не нашёл загрузочных устройств

Процессор не нашёл загрузочных устройств

Регистры

В реальном режиме работы процессора «Real Mode«, пользователю доступны 16-битные регистры: ax, bx, cx, dx, sp, si, di, bp. Также пользователь имеет доступ и к 8-битным регистрам. 8-битные регистры формируют 16-битный регистр.

Старший 8-битный регистр

Младший 8-битный регистр

16-битный регистр

AH

AL

AX

BH

BL

BX

CH

CL

CX

DH

DL

DX

Прерывания

BIOS предоставляет разработчикам целый инструментарий для работы с периферией, графикой, жёсткими дисками и так далее (256 прерываний). Я приведу таблицу прерываний, используемых в процессе написания ОС.

Номер прерывания

Назначение прерывания

0x13

Работа с жёстким диском

0x10

Видео сервис. Понадобится для вывода текста на экран

0x16

Работа с клавиатурой

0x15

Работа с памятью. Понадобится для задержки выполнения кода

0x19

Перезагрузка системы с помощью org 0x7c00 jmp pre_boot pre_boot: cli ; Запрещаем прерывания xor ax, ax ; Зануляем регистры mov ds, ax ; Зануляем регистры mov es, ax ; Зануляем регистры mov ss, ax ; Зануляем регистры mov sp, 0x7c00 ; Чтение и размещение операционной системы в ОЗУ mov ah, 0x02; Функция 0x02 - Работа с жёстким диском mov al, 7 ; Количество секторов на чтение. В нашем случае 7 = 7*512 = 3584 байт mov ch, 0x00 ; Номер цилиндра mov cl, 0x02 ; Номер начального сектора 2. 1 сектор - загрузчик, 2 сектор - ОС. mov dh, 0x00 ; Сторона диска mov dl, 0x80 ; Номер устройства. Начинается с 0x80 - 0, 0x81 - 1, ... mov bx, 0x7e00 ; Адрес загрузки данных int 0x13 ; Прерывание чтения сектора jc read_error ; Если возникает ошибка, переходим к выполнению куска кода read_error. jmp 0x7e00 ; Если ошибок не возникло, то переходим к загруженному коду. 0x7c00 + 512 = 0x7e00 read_error: mov ah, 0x0e ; Номер функции в прерывании 0x10, вывод символа на экран. mov al, 'R' ; Загружаем символ int 0x10 ; Выводим символ mov al, 'E' int 0x10 mov al, 'A' int 0x10 mov al, 'D' int 0x10 mov al, ' ' int 0x10 mov al, 'E' int 0x10 mov al, 'R' int 0x10 mov al, 'R' int 0x10 mov al, 'O' int 0x10 mov al, 'R' int 0x10 mov al, '!' int 0x10 jmp $ ; Бесконечный переход к этой метке. Зависаем на месте с выводом ошибки. times 510 - ($- $$) db 0 ; Заполняем оставшуюся часть кода нулями. dw 0xaa55 ; Магическое число в конце сектора.

Важное замечание!

Операционная система будет размещена в одном файле и её реальный размер на данный момент составляет 7 секторов. В случае, если реальный размер файла будет меньше чем указано секторов на чтение, будет выводиться ошибка «READ ERROR!«. При написании ОС, имейте это ввиду!

Ошибка чтения диска. Указанное количество секторов на чтение превышает реальный размер исполняемого файла.

Ошибка чтения диска. Указанное количество секторов на чтение превышает реальный размер исполняемого файла.

Теперь, когда загрузчик готов, приступаем к написанию библиотеки ввода-вывода. Эти функции я расположу в другом файле, в директории «drivers».

Для удобства добавил комментарии в стиле языка C, что бы быстро определить в какие регистры, какие значения необходимо поместить для вызова определённой функции. А теперь пройдёмся по функционалу:

  • cls — Очистка экрана.

  • out_char — Вывод символа на экран.

  • out_string — Вывод строки на экран.

  • in_char — Пользовательский ввод символа.

  • in_string — Пользовательский ввод строки.

  • compare_str — Сравнение двух строк.

  • clear_buffer — Очистить буфер (Занулить).

  • new_line — Перевод каретки ввода на новую строку.

; ============================================================================ ; Библиотека для ввода/вывода текстовой информации, с помощью прерываний BIOS ; ============================================================================ global cls          ; void cls(); global out_char     ; void out_char(char bl); global out_string   ; void out_string(char* si);  global in_char      ; char in_char() return char al; global in_string    ; void in_string(char[]* si);  global comapre_strs ; int (const char* first_word[] si, const char* last_word[] bx) return cx (1 - равны, 0 - не равны);  global clear_buffer ; void (const char* buf_address[] si, int buf_size bx);  global new_line ; void new_line();  section .text  new_line:        ; Перевод каретки на новую строку     push ax      ; Сохраняем значение регистра ax в стеке     mov ah, 0x0e ; Номер функции прерывания 0x10. Вывод     mov al, 0x0a ; Символ перевода каретки в начало     int 0x10     ; Вызов прерывания для работы с видеосервисом     mov al, 0x0d ; Символ перевода строки     int 0x10     pop ax       ; Восстанавливаем значение в регистре ax     ret          ; Выходим из функции  cls:     push ax      ; Сохраняем значение ax     mov ah, 0x00 ; Номер функции прерывания 0x10. Изменение видеорежима     mov al, 0x03 ; Номер видеорежима. 0x03 - текстовый видеорежим.     int 0x10          pop ax       ; Восстанавливаем значение регистра ax     ret          ; Выходим из функции  out_char:        ; Вывод символа на экран     push ax     mov ah, 0x0e     mov al, bl   ; В регистр bl мы заранее положили символ на вывод     int 0x10     pop ax     ret  out_string:      ; Вывод строки на экран     push ax     mov ah, 0x0e     call __out_string_next_char     pop ax     ret __out_string_next_char:     mov al, [si]        ; В регистре si храниться адрес начала строки. Помещаем значение из адреса si в al     cmp al, 0           ; Затем сравниваем al с 0     jz __out_string_if_zero  ; если al = 0 значит строка закончилась     int 0x10                 ; если al != 0 значит, по этому адресу что-то есть, выводим символ на экран     inc si                   ; Увеличиваем si на 1     jmp __out_string_next_char ; Выполняем функцию снова __out_string_if_zero:     ret                    ; Покидаем функцию  in_char:        ; Пользовательский ввод символа     push bx     mov ah, 0     int 0x16    ; Символ сохранён в регистр al     mov ah, 0x0e     mov bh, 0     mov bl, 0x07     int 0x10    ; Вывод введённого символа на экран     pop bx     ret   comapre_strs:       ; Сравнивание строк     push si     push bx     push ax __comapre_strs_comp:     mov ah, [bx]     cmp [si], ah     jne __comapre_strs_first_zero     inc si     inc bx     jmp __comapre_strs_comp __comapre_strs_first_zero:     cmp byte [bx], 0     jne __comapre_strs_not_equal     mov cx, 1     pop si     pop bx     pop ax     ret __comapre_strs_not_equal:     mov cx, 0     pop si     pop bx     pop ax     ret   clear_buffer:     ; si - Адрес буфера     ; bx - Количество байт на очистку     push cx     mov cx, 0 __clear_buffer_loop:     cmp cx, bx     je __clear_buffer_end_loop     mov byte [si], 0     inc si     inc cx     jmp __clear_buffer_loop __clear_buffer_end_loop:     pop cx     ret    in_string:             ; Пользовательский ввод строки. Адрес буфера хранится в si     push ax     push cx     xor cx, cx __input_string_loop:     mov ah, 0     int 0x16     cmp al, 0x0d            ; Если пользователь нажал Enter, то обрабатываем это событие     je __input_string_enter     cmp al, 0x08            ; Если пользователь нажал Backspace, то обрабатываем это событие     je __input_string_backspace      mov [si], al     inc si     inc cx      mov ah, 0x0e     mov bh, 0     mov bl, 0x07     int 0x10     cmp cx, 255               ; Если Пользователь ввёл 255 символов     je __input_string_enter   ; То прыгаем в событие нажатия на Enter     jmp __input_string_loop __input_string_enter:     mov ah, 0x0e ; Номер функции int 0x10 - вывод символа      mov al, 0x0d ; Перевод каретки на новую строку     mov bh, 0     mov bl, 0x07 ; Цвет выводимого символа 0 - чёрный фон 7 - белый символ     int 0x10     mov al, 0xa  ; Перевод каретки в начало строки     int 0x10      mov byte [si], 0 ; Помещаем в конец строки 0     pop cx     pop ax     ret __input_string_backspace:     cmp cx, 0         ; Проверка номера символа по счёту. Если это 0 символ - значит нужно запретить стирание символа, потому что, пользователь может случайно стереть выводимую ОС информацию.     je __input_string_loop ; Если это 0 символ, то возвращаемся в цикл ввода     mov ah, 0x0e            ; Иначе, эмулируем нажатия на Backspace, Пробел, Backspace     mov al, 0x08            ; Backspace     int 0x10     mov al, 0x20            ; Пробел     int 0x10     mov al, 0x08            ; Backspace     int 0x10      mov byte [si], 0     dec si                 ; Уменьшаем si на 1. si - адрес cx - номер введённого символа. Уменьшаем два этих регистра на один     dec cx     jmp __input_string_loop ; Возвращаемся в цикл ввода

Обратите внимание на строки 157-163. В строке 157 в комментарии я указал, «эмулируем нажатия на Backspace, Пробел, Backspace«. Когда пользователь нажимает на Backspace во время ввода, каретка смещается влево на 1 символ и остаётся под предыдущим символом. Пользователь не может её стереть, может только лишь заменить на другой символ (Напоминает включённый режим Insert на клавиатуре). Это можно обойти через набор действий, Backspace, Пробел, Backspace. Что бы изменить такое поведение, в коде заранее прописаны эти действия.

Операционная система

Операционная система должна поддерживать как минимум командную строку и набор команд. Работу с командами реализуем по подобию Callback функций.

Пользователь вводит команду -> Обработчик команд сравнивает пользовательский ввод с существующими командами. Если название команды и пользовательский ввод равны, то начинается исполнение команды, иначе проверяем следующую команду. Если команда не найдена, выводим ошибку «Comand not found!».

Графическое представление принципа обработки команд

Графическое представление принципа обработки команд
jmp boot  boot:     call cls                 ; Очищаем экран     call IBM_WELCOME_WINDOW  ; Вызываем функцию вывода логотипа IBM     call cls                 ; Очищаем экран     mov si, welcome     call out_string          ; Выводим приветственное сообщение     jmp input_loop           ; Переходим к выполнению цикла пользовательского ввода  IBM_WELCOME_WINDOW:     mov si, IBM_WELCOME     call out_string      mov ax, 0x8600  ; Время ожидания, в мс     mov cx, 30      ; Номер функции 30 - ожидание     int 0x15        ; Вызываем 0x15 прерывание для ожидания     ret  input_loop:      mov si, buffer     mov bx, 255     call clear_buffer ; Очищаем буфер от пользовательского ввода      mov si, prompt       call out_string   ; Выводим live@cd>      mov si, buffer         call in_string    ; Даём пользователю возможность ввода команды      jmp OS_callback   ; Проверяем что ввёл пользователь       jmp input_loop    ; Повторяем цикл    OS_callback:     mov si, help_in     mov bx, buffer     call comapre_strs   ; Проверяем пользовательский ввод с help     cmp cx, 1     je Callback_HELP    ; Если пользователь ввёл help, то прыгаем в Callback_HELP      mov si, cls_in      ; Проверяем пользовательский ввод с cls     mov bx, buffer     call comapre_strs     cmp cx, 1     je Callback_CLS     ; Если пользователь ввёл cls, то прыгаем в Callback_CLS      mov si, info_in     mov bx, buffer     call comapre_strs     cmp cx, 1     je Callback_INFO      mov si, reboot_in     mov bx, buffer     call comapre_strs     cmp cx, 1     je Callback_REBOOT      mov si, echo_in     mov bx, buffer     call comapre_strs     cmp cx, 1     je Callback_ECHO       jne Callback_WRONG  ; Если ни одна команда не подошла, то сообщаем, что команда введена неправильно     jmp input_loop  Callback_HELP:     mov si, help_out     call out_string     ; Выводим справку по командам     jmp input_loop Callback_CLS:     call cls            ; Вызываем функцию очистки экрана     jmp input_loop  Callback_WRONG:         ; Неверная команда     mov si, wrong_command_1     call out_string           ; Выводим первую часть сообщения: Command '     mov si, buffer            ;      call out_string           ; Выводим то, что ввёл пользователь     mov si, wrong_command_2   ;      call out_string           ; Выводим выводим вторую часть сообщения: ' not found. Type 'help' to get all commands     jmp input_loop            ; Переходим в цикл пользовательского ввода  Callback_INFO:     mov si, info_out     call out_string           ; Тот же алгоритм, что и help     jmp input_loop  Callback_REBOOT:     mov ah, 0                 ; Номер функции 0 - "тёплая" перезагрузка     int 0x19                  ; Выполняем 0x19 прерывание     jmp $                     ; Зависаем. Можно не добавлять, на всякий случай добавил  Callback_ECHO:     mov si, echo_out               call out_string           ; Выводим просьбу ввести слово, которое затем выведем      mov si, buffer                 call in_string            ; Ожидаем пользовательский ввод      mov si, buffer     call out_string           ; Выводим введённое слово      call new_line             ; Переходим на новую строку          jmp input_loop            ; Возвращаемся в цикл ввода   %include "drivers/IO.asm"     ; Подключаем библиотеку IO.asm ; Далее секция данных. тут думаю проблем с пониманием не возникнет. welcome db "Welcome to TermOS!", 0x0a, 0x0d, "Type 'help' to get command list!", 0x0a, 0x0d, 0 prompt db "live@cd:>", 0  wrong_command_1 db "Command: '", 0 wrong_command_2 db "' not found. Type 'help' to get all commands", 0x0a, 0x0d, 0 echo_out db "Echo: ", 0    help_in db "help", 0 cls_in db "cls", 0 info_in db "info", 0 reboot_in db "reboot", 0 echo_in db "echo", 0    info_out db "TermOS x16 (Terminal Operation System 16-bit) v.0.0:", 0x0a, 0x0d, "        This is operation system in development.", 0x0a, 0x0d, "         Author: Daniil Kulikovskiy.", 0x0a, 0x0d, "          Made in Russia!", 0x0a, 0x0d, 0 help_out db "          cls - Clear screen", 0x0a, 0x0d, "         info - Get system info", 0x0a, 0x0d, "        reboot - Reboot computer", 0x0a, 0x0d, "       echo - Write text in screen", 0x0a, 0x0d, 0     IBM_WELCOME db "                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"              ======== ========    ======          =======                     ", 0x0a, 0x0d,"              ======== =========   ========       ========                     ", 0x0a, 0x0d,"                ===       ==  ===    =======     =======                       ", 0x0a, 0x0d,"                ===       ======     ========   ========                       ", 0x0a, 0x0d,"                ===       ======     ==  ===== =====  ==                       ", 0x0a, 0x0d,"                ===       ==  ===    ==   =========   ==                       ", 0x0a, 0x0d,"              ======== =========  =====    =======    =====                    ", 0x0a, 0x0d,"              ======== ========   =====       =       =====                    ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d," (C) COPYRIGHT 1981, 1996 IBM CORPARATION - ALL RIGHTS RESERVED                ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d, 0   buffer times 255 db 0
Забавы ради, добавил логотип "IBM" на стартовый экран.

Забавы ради, добавил логотип «IBM» на стартовый экран.

Попрошу заметить!

jmp — безусловный переход к метке или адресу.

call — безусловный переход к метке или адресу, с сохранением адреса возврата в стек. После выполнения работы функции, которая вызывается через call, всегда нужно прописывать ret.

ret — перейти к адресу указанному в стеке.

Почему в конце метки с данными указывается 0x0a, 0x0d, 0?

0x0a — Перевод на следующую строку.

0x0d — Перевод каретки в начало строки.

0 — К строке добавляется ноль, для того, что бы определить конец строки.

На примере команды «help«, рассмотрим принцип работы всех команд. В коде есть 2 метки help_in и help_out. help_in — название команды, с ним будет сравниваться пользовательский ввод. help_out — Выводимая информация на экран.

Первое что происходит в коде, это переход к метке input_loop, где очищается буфер и от пользователя ожидается ввод команды. Введённая пользователем команда сохраняется в буфере, затем происходит переход к метке OS_callback — В этой функции, происходит проверка введённой команды, и если команда сходиться в одной из проверок, начинается исполнение этой команды, иначе вывод ошибки и возвращение в цикл ввода.

Для добавления собственной команды, необходимо прописать её логику в отдельной callback функции, затем прописать название команды и добавить код обработки вашей команды в OS_callback. Важно, после выполнения вашей команды, всегда возвращаться в метку input_loop для корректной работы ОС.

OS_callback:     mov si, you_command_in     mov bx, buffer     call comapre_strs     cmp cx, 1     je Callback_YOU_COMMAND  ...  Callback_YOU_COMMAND:   ...    jmp input_loop you_command_in db "you command",0

Напоминаю! При добавлении функционала, не забывайте проверять размер скомпилированного файла. Может оказаться так, что вы допишите функционал, а при запуске он не будет реализован или реализован не полностью. Проверяйте количество секторов на чтение и размер файла!

Сборка и первый запуск

Операционную систему необходимо собирать с помощью NASM в «nasm -f bin TermOS.asm -o TermOS.bin qemu-system-x86_64 TermOS.bin

Получившаяся Операционная Система TermOS

Получившаяся Операционная Система TermOS

Исходный код

drivers/IO.asm

; ============================================================================ ; Библиотека для ввода/вывода текстовой информации, с помощью прерываний BIOS ; ============================================================================ global cls          ; void cls(); global out_char     ; void out_char(char bl); global out_string   ; void out_string(char* si);  global in_char      ; char in_char() return char ax (al); global in_string    ; void in_string(char[]* si);  global comapre_strs ; int (const char* first_word[] si, const char* last_word[] bx) return cx (1 - равны, 0 - не равны);  global clear_buffer ; void (const char* buf_address[] si, int buf_size bx);  global new_line ; void new_line();  section .text  new_line:     push ax     mov ah, 0x0e     mov al, 0x0a     int 0x10     mov al, 0x0d     int 0x10     pop ax     ret  cls:     push ax     mov ah, 0x00     mov al, 0x03     int 0x10     pop ax     ret  out_char:     push ax     mov ah, 0x0e     mov al, bl     int 0x10     pop ax     ret  out_string:     push ax     mov ah, 0x0e     call __out_string_next_char     pop ax     ret __out_string_next_char:     mov al, [si]     cmp al, 0     jz __out_string_if_zero     int 0x10     inc si     jmp __out_string_next_char __out_string_if_zero:     ret  in_char:     push bx     mov ah, 0     int 0x16    ; Сохранение символа в регистр al     mov ah, 0x0e     mov bh, 0     mov bl, 0x07     int 0x10    ; Вывод введённого символа на экран     pop bx     ret   comapre_strs:     push si     push bx     push ax __comapre_strs_comp:     mov ah, [bx]     cmp [si], ah     jne __comapre_strs_first_zero     inc si     inc bx     jmp __comapre_strs_comp __comapre_strs_first_zero:     cmp byte [bx], 0     jne __comapre_strs_not_equal     mov cx, 1     pop si     pop bx     pop ax     ret __comapre_strs_not_equal:     mov cx, 0     pop si     pop bx     pop ax     ret   clear_buffer:     ; si - Адрес буфера     ; bx - Колчисевто байт на очистку     push cx     mov cx, 0 __clear_buffer_loop:     cmp cx, bx     je __clear_buffer_end_loop     mov byte [si], 0     inc si     inc cx     jmp __clear_buffer_loop __clear_buffer_end_loop:     pop cx     ret    in_string:     push ax     push cx     xor cx, cx __input_string_loop:     mov ah, 0     int 0x16     cmp al, 0x0d            ; Enter     je __input_string_enter     cmp al, 0x08            ; Backspace     je __input_string_backspace      mov [si], al     inc si     inc cx      mov ah, 0x0e     mov bh, 0     mov bl, 0x07     int 0x10     cmp cx, 255     je __input_string_enter     jmp __input_string_loop __input_string_enter:     mov ah, 0x0e     mov al, 0x0d     mov bh, 0     mov bl, 0x07     int 0x10     mov al, 0xa     int 0x10      mov byte [si], 0     pop cx     pop ax     ret __input_string_backspace:     cmp cx, 0     je __input_string_loop     ; 0x20                  ; Пробел     mov ah, 0x0e     mov al, 0x08            ; Backspace     int 0x10     mov al, 0x20            ; Пробел     int 0x10     mov al, 0x08     int 0x10      mov byte [si], 0     dec si     dec cx     jmp __input_string_loop 

TermOS.asm

org 0x7c00  jmp pre_boot  pre_boot:     cli     xor ax, ax     mov ds, ax     mov es, ax     mov ss, ax     mov sp, 0x7c00          mov ah, 0x02     mov al, 7   ; Количество секторов на чтение     mov ch, 0x00     mov cl, 0x02     mov dh, 0x00     mov dl, 0x80     mov bx, 0x7e00     int 0x13       ; Прерывание чтения сектора     jc read_error       jmp 0x7e00    ; Переход к загруженному коду  read_error:     mov ah, 0x0e     mov al, 'R'     int 0x10     mov al, 'E'     int 0x10     mov al, 'A'     int 0x10     mov al, 'D'     int 0x10     mov al, ' '     int 0x10     mov al, 'E'     int 0x10     mov al, 'R'     int 0x10     mov al, 'R'     int 0x10     mov al, 'O'     int 0x10     mov al, 'R'     int 0x10     mov al, '!'     int 0x10       jmp $  times 510 - ($- $$) db 0 dw 0xaa55  jmp boot  boot:     call cls     call IBM_WELCOME_WINDOW     call cls     mov si, welcome     call out_string     jmp input_loop  IBM_WELCOME_WINDOW:     mov si, IBM_WELCOME     call out_string      mov ax, 0x8600     mov cx, 30     int 0x15     ret  input_loop:      mov si, buffer     mov bx, 255     call clear_buffer      mov si, prompt     call out_string      mov si, buffer     call in_string      jmp OS_callback       jmp input_loop    OS_callback:     mov si, help_in     mov bx, buffer     call comapre_strs     cmp cx, 1     je Callback_HELP      mov si, cls_in     mov bx, buffer     call comapre_strs     cmp cx, 1     je Callback_CLS      mov si, info_in     mov bx, buffer     call comapre_strs     cmp cx, 1     je Callback_INFO      mov si, reboot_in     mov bx, buffer     call comapre_strs     cmp cx, 1     je Callback_REBOOT      mov si, echo_in     mov bx, buffer     call comapre_strs     cmp cx, 1     je Callback_ECHO       jne Callback_WRONG     jmp input_loop  Callback_HELP:     mov si, help_out     call out_string     jmp input_loop Callback_CLS:     call cls     jmp input_loop  Callback_WRONG:     mov si, wrong_command_1     call out_string     mov si, buffer     call out_string     mov si, wrong_command_2     call out_string     jmp input_loop  Callback_INFO:     mov si, info_out     call out_string     jmp input_loop  Callback_REBOOT:     mov ah, 0     int 0x19     jmp $  Callback_ECHO:     mov si, echo_out     call out_string     mov si, buffer     call in_string      mov si, buffer     call out_string      call new_line          jmp input_loop   %include "drivers/IO.asm" welcome db "Welcome to TermOS!", 0x0a, 0x0d, "Type 'help' to get command list!", 0x0a, 0x0d, 0 prompt db "live@cd:>", 0  wrong_command_1 db "Command: '", 0 wrong_command_2 db "' not found. Type 'help' to get all commands", 0x0a, 0x0d, 0 echo_out db "Echo: ", 0    help_in db "help", 0 cls_in db "cls", 0 info_in db "info", 0 reboot_in db "reboot", 0 echo_in db "echo", 0    info_out db "TermOS x16 (Terminal Operation System 16-bit) v.0.0:", 0x0a, 0x0d, "        This is operation system in development.", 0x0a, 0x0d, "         Author: Daniil Kulikovskiy.", 0x0a, 0x0d, "          Made in Russia!", 0x0a, 0x0d, 0 help_out db "          cls - Clear screen", 0x0a, 0x0d, "         info - Get system info", 0x0a, 0x0d, "        reboot - Reboot computer", 0x0a, 0x0d, "       echo - Write text in screen", 0x0a, 0x0d, 0     IBM_WELCOME db "                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"              ======== ========    ======          =======                     ", 0x0a, 0x0d,"              ======== =========   ========       ========                     ", 0x0a, 0x0d,"                ===       ==  ===    =======     =======                       ", 0x0a, 0x0d,"                ===       ======     ========   ========                       ", 0x0a, 0x0d,"                ===       ======     ==  ===== =====  ==                       ", 0x0a, 0x0d,"                ===       ==  ===    ==   =========   ==                       ", 0x0a, 0x0d,"              ======== =========  =====    =======    =====                    ", 0x0a, 0x0d,"              ======== ========   =====       =       =====                    ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d," (C) COPYRIGHT 1981, 1996 IBM CORPARATION - ALL RIGHTS RESERVED                ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d,"                                                                               ", 0x0a, 0x0d, 0   buffer times 255 db 0

Список литературы

Как запустить программу без операционной системы

О работе ПК ч.3: От включения до полной загрузки Windows 10


ссылка на оригинал статьи https://habr.com/ru/articles/807459/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *