Пишем операционную системы своими руками

Статьи по предмету «Программирование»
Информация о работе
  • Тема: Пишем операционную системы своими руками
  • Количество скачиваний: 137
  • Тип: Статьи
  • Предмет: Программирование
  • Количество страниц: 5
  • Язык работы: Русский язык
  • Дата загрузки: 2018-07-13 19:31:14
  • Размер файла: 396.65 кб
Помогла работа? Поделись ссылкой
Информация о документе

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

Если Вы являетесь автором текста представленного на данной странице и не хотите чтобы он был размешён на нашем сайте напишите об этом перейдя по ссылке: «Правообладателям»

Можно ли скачать документ с работой

Да, скачать документ можно бесплатно, без регистрации перейдя по ссылке:

Пишем ОС


Введение

Не давно мне стало интересно на сколько тяжело написать операционную систему, как она вообще устроенна внутри, что должна делать, ну или хотя бы какой минимальный набор функциональности иметь. Так же было интересно низкоуровневое программирование, там где нет помощников и готовых функций, только ты, железо и BIOS, без него было бы совсем туго :). И я решил написать простенькую ОС а попутно подучить уже совсем забытый мной ассемблер, и архитектуру x86.

Первое что я решил заделать это поискать статьи, типа «Пишем простую ОС». Таковых оказалось довольно много но лично я смог уловить по ним только основной принцип написания ОС, довольно поверхностно. Возможно просто мой уровень IQ маловат, хотя признаться я его не когда не измерял, боюсь результата :). Ну так вот открыв кучу вкладок в своём браузере, а также различных исходников ОС в notepad++ я принялся за дело. Ниже я опишу всё что я выяснил о создании собственной ОС.


Загрузка ОС с дискеты

Нашу ОС мы разместим на дискете, по этому давайте рассмотрим процесс загрузки операционной системы с дискеты. Он состоит из нескольких этапов, сначала загружается BIOS (англ. basic input/output system — «базовая система ввода-вывода»), затем BIOS определяет различные устройства в том числе и блочные устройства ввода-вывода, К блочным относятся такие устройства, которые хранят информацию в блоках фиксированной длины, у каждого из которых есть свой собственный адрес. Обычно размеры блоков варьируются от 512 до 32 768 байт. Вся передача данных ведется пакетами из одного или нескольких целых (последовательных) блоков. Важным свойством блочного устройства является то, что оно способно читать или записывать каждый блок независимо от всех других блоков. Среди наиболее распространенных блочных устройств жесткие диски, приводы гибких дисков а так же, приводы компакт-дисков и флэш-накопители USB. Нас же интересуют приводы гибких дисков а именно привод для дискет диаметром 3.5 дюйма и объёмом 1.4МБ(1 474 560 байт)

Немного об устройстве привода. Привод состоит из электронной части и механической, в механической части присутствуют два двигателя, один из них шаговый, шаговым его называют по тому что он вращается не непрерывно, как обычные двигатели, а маленькими точными шагами, шаг двигателя 3.5 дюймового дисковода равен 1,8°,что позволяет с его помощью довольно точно позиционировать головку записи-чтения над определённой областью магнитного диска дискеты. Также к механической части относятся головки чтения-записи они то и считывают-записывают данные на магнитный диск. Их в дисководе две, одна над магнитным диском другая под ним. Ниже показано размещение головок над диском.



Д
иск имеет магнитное покрытие и разбит на дорожки и сектора, на одной стороне диска содержится 80 дорожек, всего сторон две, нумерация дорожек начинается с 0 по 79, в одной дорожке содержится 18 секторов, емкость одного сектора составляет 512байт. Нумерация секторов начинается с первого. Первый сектор является загрузочным




После определения всех устройств BIOS начинает загрузку с накопителя который выбран как загрузочный. На этом накопителе должен присутствовать загрузочный сектор в котором находится программа загрузки ядра ОС. После чего BIOS прочтёт первый сектор диска, который как правило является загрузочным и если найдёт на нём сигнатуру загрузочного сектора, это два последних байта сектора, имеющие вид в шестнадцатеричной системе AAh,55h, то загрузит этот сектор в оперативную память по адресу 07C00h, и передаст управление загруженному коду. Далее этот код должен загрузить ядро ОС в память и передать ему управление.


Инструментарий

У меня нет ни дискеты ни дисковода, да и писать любую программу куда приятнее если есть возможность запускать её по сто раз за час, дабы убедится в работе каждой написанной строчки кода :). По этому воспользуемся виртуальной машиной, я выбрал Virtual Box. Скачать Virtual Box можно тут https://www.virtualbox.org/ . Моя версия 5.0.0 на Windows 7 64 бит, сразу работать не захотела, порыскав на форумах, оказалось проблема заключается в том, что у многих для установки расширенных тем оформления пропатчен фал Windows\system32\uxtheme.dll. Обычно оригинальный файл находится в том же каталоге и имеет имя uxtheme.dll.backup. Просто поменяйте между собой их названия.

Далее нам понадобится компилятор FASM( flat assembler ) - это свободно распространяемый многопроходной ассемблер, написанный Томашем Грыштаром (польск. Tomasz Grysztar). Скачать его можно с официального сайта http://flatassembler.net/. Писать код мы будем в Notepad++ его скачать можно тут https://notepad-plus-plus.org/. Установите FASM в корневой каталог диска C, затем установите Notepad++.

Также нам понадобится программа способная создать виртуальный образ дискеты, для этих целей я написал на C# простенькую программку, которую назвал imgMaster. Принцып её действия довольно прост, после запуска программы, нажимаем кнопку Add File, и выбираем первый файл, его размер должен составлять 512байт не больше, не меньше, не больше так как он может не поместится в загрузочный сектор размер которого, как мы уже знаем 512байт. А не меньше по тому что 511 и 512 байты, это сигнатура загрузочного сектора, без них BIOS решит что программа загрузчик отсутствует, и не станет не чего загружать из сектора. Далее при необходимости добавляем остальные файлы, и нажимаем Create IMG, сохраняем образ. Программа запишет файлы один за другим, в той же очерёдности в которой они расположены в списке, затем оставшееся место заполнит нулями, чтобы размер образа был равен ёмкости дискеты 1.4МБ(1 474 560 байт).


Пишем Hello World

Можно приступать к написанию первой тестовой программы, которая без операционной системы, будет способна вывести на экран традиционную надпись «Hello World!».

И так первое что нам необходимо сделать это узнать где мы будем находится в ОЗУ. Ниже представлена модель адресного пространства ОЗУ, как я её понял.


Адресное пространство:

Размер

Назначение

Физ.Адрес

1KB

Векторы прерываний

00000h

256B

Область данных BIOS

00400h

638KB

Первая свободная область


(Суда BIOS помещает данные из загрузочного сектора)

00500h


07С00h

64KB

Графический видео буфер

A0000h

32KB

Вторая свободная область

B0000h

32KB

Текстовый видео буфер

B8000h

64KB

ПЗУ — Расширения BIOS

C0000h

128KB

Третья свободная область

D0000h

64KB

ПЗУ - BIOS

F0000h

64KB

HMA

100000h

До 4GB

XMS

Четвёртая свободная область

10FFF0h


Первые 640 Кбайт (до графического видео буфера) называются стандартной (conventional) памятью. Начинается стандартная память с килобайта, который содержит векторы прерываний, их 256 на каждый отводится по 4 байта.

Затем идет область данных BIOS. Где находятся данные необходимые для корректной работы функций BIOS. Но также можно модифицировать эту область, тем самым мы влияем на ход выполнения системных функций, по сути дела меняя что либо в этой области мы передаем параметры BIOS и его функциям, которые становятся более гибкими. С адреса 500h начинается свободная область до 640КБ. За 640 килобайтами начинается старшая память или верхняя (upper) память, она располагается до 1 мегабайта (до HMA), т.е. она составляет 384 Кбайт. Тут располагаются ПЗУ (постоянно запоминающее устройство ) : текстовый видео буфер (его микросхема рассчитана на диапазон B8000h…BFFFFh) и графический видео буфер (A0000h…AFFFFh). Если требуется вывести текст то его ASCII коды требуется прописать в текстовый видео буфер и вы немедленно увидите нужные символы. F0000h…FFFFFh, а вот и сам BIOS. Так же есть еще одна ПЗУ – ПЗУ расширений BIOS (C0000h…CFFFFh), её задача обслуживание графических адаптеров и дисков. За первым мегабайтом, с адреса 100000h, располагается память именуемая как расширенная память, конец которой до 4 гигабайт. Расширенная память состоит из 2х подуровней: HMA и XMS. Высокая память (High MemoryArea, HMA) доступна в реальном режиме, а это еще плюс 64 Кбайт (точнее 64 Кбайт – 16 байт), но для этого надо разрешить линию A20 (открыв вентиль GateA20). Функционирование расширенной памяти подчиняется спецификации расширенной памяти (Expanded Memory Specification, XMS), поэтому саму память назвали XMS- памятью, но она доступна только в защищенном режиме.


Красным отмечен адрес начала нашей программы, теперь мы можем смело указать компилятору с какого адреса начинать размещать данные в оперативной памяти. Для этого служит директива org. Давайте приступим к написанию программы. Запустите Notepad++, затем создайте новый файл и сохраните его где вам удобно, назвав boot.asm. После чего Notepad++ начнёт подсвечивать ассемблерный синтаксис. Теперь набираем данный код, сообщая компилятору адрес начала нашей программы.

org 07C00h ;BIOS помещает нашу программу по адресу 07C00h, поэтому указываем что все ;данные программы мы будем размещать начиная с этого адреса

Далее необходимо провести инициализацию регистров данных и стека.

;Инициализация

;-------------

cli ;Запретить прерывания, чтобы не чего не отвлекало :)

xor ax,ax ;Обнуляем регистр ax

mov ds,ax ;Сегмент данных. Наши данные размещены от начала программы

mov ss,ax ;Сегмент стека.

mov sp,07C00h ;Стек начинается в начале программы и растёт в ;противоположную сторону, в начало памяти

sti ;Разрешить прерывания


Давайте узнаем какой размер стека у нас получится при такой инициализации. Для этого выполним следующие действия: 7C00h – 0500h = 7700h. Где 7C00h – адрес начала нашей программы, 0500h – адрес начала свободного пространства. Полученное шестнадцатеричное значение 7700h, это размер стека в байта, переведём его в десятичное получим 30464байт, разделим на 1024 и получим 29КБ. Для наших целей этого более чем достаточно.

Теперь для удобства работы давайте создадим несколько макросов, в дальнейшем мы можем вынести их в отдельный файл.


macro displayClean ;Очистка дисплея

{

mov ax, 02h ;очищаем экран - функция 02h прерывания 10h

int 10h

}


Макрос displayClean служит для очистки экрана от всего лишнего.


Далее идёт макрос setCursor служащий для установки курсора в нужную нам позицию, имеющий два аргумента, координату по оси X, и координату по оси Y. От местоположения курсора зависит, место куда будет выведен следующий символ выводимой нами строки.


macro setCursor x, y ;Установить курсор

{

mov dx,x

mov dh,y

;установка курсора : функция 02h прерывания 10h

mov ah,02h

xor bh,bh

int 10h

}


И последний необходимый нам макрос Print будет выводить нашу строку, у него есть три аргумента, string – адрес первого символа строки, length — количество символов строки, и color — цвет строки.


macro print string, lenght, color ;Вывод строки

{

mov bp,string ;Адрес строки

mov cx,lenght ;Длина строки

mov bl,color ;в регистре bl- атрибут цвета

mov ah,13h ;функция 13h прерывания 10h

mov al,01h ;строка только с символами + смещение курсора

;xor dx,dx ;dh-номер строки на экране, dl - номер столбца на экране

int 10h

}


После определения макросов можно разместить нашу строку в памяти

msg0 db "Hello World!" ;Текст сообщения

msg0_len = $ - msg0 ;Длина строки, $ текущий адрес минус адрес начала строки msg0

Далее следует этот код:


displayClean ;Очистим экран с помощью подготовленного нами макроса

setCursor 0, 0 ;Утановим курсор в верхний левый угол

println msg0, msg0_len, 03h ;Выведим приветствие


На этом наша программа закончена осталось забить оставшееся место ( минус два байта сигнатуры ) нулями, чтобы файл занимал равно 512байт.


times (512-2)-($-$$) db 0 ;Цикл выполняется (512-2)-($-$$) раз. Где

;512 - размер загрузочного сектора

;2 - два последних байта

;$ - текущий адрес в памяти

;$$ - Начальный адрес в памяти


И записать два байта сигнатуры, указывающие BIOS-у что это кот загрузчика


;Конец загрузочного сектора

;---------------

db 0AAh,55h ;сигнатура, символизирующая о завершении загрузочного сектора

;последние два байта - признак конца таблицы MBR - код 0xAA55.

;──────────────────────────────END──────────────────────────

Давайте теперь скомпилируем наш код. Для этого нажмите F5, в появившемся окне введите, C:\fasm\FASM.EXE(FULL_CURRENT_PATH), нажмите сохранить, и выберите комбинацию клавиш для быстрого вызова. Теперь после нажатия выбранной комбинации, компилятор FASM скомпилирует нашу программу, и рядом с исходным кодом появится бинарный файл, этот файл и будет нашим загрузчиком, который мы должны будем записать на первый сектор дискеты.

Теперь давайте проверим работу нашей программы. Запустите imgMaster и добавте в список скомпилированный файл, он должен называется boot.bin, затем нажмите Create IMG и сохраните образ дискеты. Далее запустите Virtual Box и нажмите Создать, затем заполните поля как на рисунке ниже:

Д
алее жмём создать и выставляем:

И
снова жмём создать


После чего в списке появится наша новенькая виртуальная машина. Выбираем её и жмём Настроить, выбираем вкладку Носители, мы видим что к контроллеру IDE у нас подключен один жёсткий диск My_OS.vdi и один CD-ROM, поскольку CD-ROM мы использовать не будем мы можем его удалить, что бы не мешал. После того как мы удалили CD-ROM, жмём зелёную кнопку Добавить новый контроллер и выбираем Добавить Floppy контроллер. Затем на появившемся в списке контроллере жмём добавить привод гибких дисков, откроется окно с предложением выбрать образ, вбираем сохранённый ранее образ и жмём ОК. Теперь запускаем нашу виртуальную машину. После запуска на экране у нас должно отобразится приветствие Hello World!.

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