Урок ОСдева №8: основной загрузчик, вводная. / программирование :: длиннопост :: ассемблер :: разработка :: Операционная система :: OSDev :: geek (Прикольные гаджеты. Научный, инженерный и айтишный юмор)

программирование geek OSDev Операционная система разработка ассемблер длиннопост песочница 

Урок ОСдева №8: основной загрузчик, вводная.

Дисклеймер: эта серия постов не про UEFI. Это не значит, что я не знаю о существовании UEFI.

Про UEFI будет отдельная серия постов. Почему я не пишу про UEFI прямо сейчас? Потому что

UEFI - это уровень абстракции над железом, а мне интересно именно железо и работа с ним.


Итак, мы закончили писать первичный загрузчик. Что дальше? Дальше - немного пугающая

свобода. Если в случае ПЗ ограничения на объём памяти ставят разработчика в жёсткие рамки

и ограничивают полёт фантазии, то теперь вы можете строить архитектуру программы

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

я, могут быть не самыми разумными и правильными. Не буду вам их навязывать. Считаете,

что сможете сделать лучше - пробуйте. В любом случае стоит держать в голове минимальный

набор задач, который должен будет выполнять ваш загрузчик:


- Переключать процессор из 16-битного в 32-битный или 64-битный режим.

- Включать доступ к расширенной памяти.

- Составлять карту RAM и передавать её ОС.

- Минимально взаимодействовать с устройствами ввода-вывода, чтобы показать сообщение об ошибке

или принять ввод пользователя.

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

- Находить на диске и загружать в указанную область памяти ядро ОС.

- Находить на диске и загружать в указанные области памяти дополнительные файлы (опционально).

- Предоставлять ОС базовую GDT (об этом позже).


Важный момент: рано или поздно перед вами встанет вопрос совмещения в одной программе

16-битного и 32-битного (или 64-битного) кода. Лично я предпочёл с этим не заморачиваться и

разбил загрузчик на отдельные файлы. Тем более, что это соответствует любимой мной аккуратной

модульной структуре. Если вы всё-таки хотите запихать весь код в один файл, стоит заранее

выбрать ассемблер, который это поддерживает.


Ещё один важный момент: достоверное определение аппаратных ресурсов может быть (было до

появления UEFI - вставят тут апологеты) сложной задачей. Там, где это можно сделать

простым способом - я буду использовать его. Там, где для этого нужно будет полагаться

на технологии, рассказ о которых выйдет слишком объёмным для одного-двух постов (ACPI, UEFI) -

пока я буду заявлять наличие устройства как обязательное. Например, для работы ОС на этом

этапе будет обязательно наличие VGA-совместимых видеокарты и дисплея.


На этом вступление закончено и можно начинать писать. 16-битный модуль загрузчика будет

в некоторых местах повторять первичный. Такие участки кода я буду давать без объяснений.

Ну и - этот пост можно назвать вводным в новый этап программы, так что кода будет

немного. Поехали.Если вы вместе со мной писали ПЗ, то сейчас, запустив машину, получите вот такое

сообщение:


Plex86/Bochs UGABios (PCI) 0.7b 03 Jan 2020 This UGA/UBE Bios is released under the GNU LGPL
Please visit :
. http://bochs.sourceforge.net . http //www.nongnu.org/vgab ios
Bochs UBE Display Adapter enabled
Bochs 2.6.10.svn BIOS - build: 01/05/20
^Revision: 13752 $ $Date: 2019-12-30 14:16:18


Создайте в папке boot папку stage2, а в ней - текстовый файл loader.asm. Заголовок и конец

модуля выглядят почти идентично ПЗ:


.386p

CSEG segment use16

ASSUME cs:CSEG, ds:CSEG, es:CSEG, fs:CSEG, gs:CSEG, ss:CSEG

LOCALS @@


begin:


CSEG ends

end begin


Добавилась только директива LOCALS @@. В TASM эта команда разрешает использование локальных

меток. Начинающаяся с символов @@ метка или переменная будет работать только в границах

процедуры или модуля, в котором прописана. Это позволит нам создавать в разных местах

переменные и указатели с одинаковыми именами. Вы оцените полезность фичи, когда начнёте писать

большие программы. Идём дальше. Первое, что нам нужно сделать - это установить значения

сегментных регистров. Совсем как в ПЗ, изменилось только значение. Если помните, loader.bin

у нас был загружен в 0050h:0000h. Выглядит так:


begin:

     ;DS, ES, FS, GS.

          mov ax,0050h     ;Сегмент загрузчика.

          mov ds,ax     ;Поместить это значение во все сегментные регистры.

          mov es,ax

          mov fs,ax

          mov gs,ax


     ;СЕГМЕНТ СТЕКА.

          cli     ;Запретить прерывания перед переносом стека.

          mov ss,ax     ;Поместить в SS адрес сегмента загрузчика.

          mov sp,0FFFFh     ;Указатель стека - на конец сегмента.

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


          cli

          hlt


Регистр CS мы не трогаем, так как его значение было корректно установлено ПЗ. Для комфортной

работы нам понадобится информация из блока параметров BIOS. Мы знаем, что он был загружен в

память вместе с ПЗ, поэтому обращаться к диску нужды нет. Собственно, я мог бы просто

скопировать всю структуру вместе со значениями из него, но это не кажется мне правильным.

Будет лучше считать структуру из RAM. Для этого нам понадобится неинициализированный

дубликат BPB и процедура, которая его заполнит. Добавьте эти переменные в конец модуля:


;=======================================;

;Блок параметров BIOS, 33 байта.;

;Здесь хранятся характеристики;

;носителя.;

;=======================================;

BPB:BPB_OEMnamedb ?,?,?,?,?,?,?,?     ;0-7. Имя производителя. Может быть любым.

BPB_bytespersecdw ?     ;8-9. Размер сектора в байтаx.

BPB_secperclustdb ?     ;10. Количество секторов в кластере.

BPB_reserveddw ?     ;11-12. Число зарезервированныx секторов (1, загрузочный).

BPB_numFATsdb ?     ;13. Число FAT.

BPB_RDentriesdw ?     ;14-15. Число записей Корневой Директории.

BPB_sectotaldw ?     ;16-17. Всего секторов на носителе.

BPB_mediatypedb ?     ;18. Тип носителя. 0F0 - 3,5-дюймовая дискета с 18 секторами в дорожке.

BPB_FATsizedw ?     ;19-20. Размер FAT в сектораx.

BPB_secpertrackdw ?     ;21-22. Число секторов в дорожке.

BPB_numheadsdw ?     ;23-24. Число головок (поверxностей).

BPB_hiddensecdd ?     ;25-28. Число скрытыx секторов перед загрузочным.

BPB_sectotal32dd ?     ;29-32. Число секторов, если иx больше 65535.


;===============================================;

;Расширенный блок параметров BIOS, 26 байт.;

;Этот раздел используется в DOS 4.0.;

;===============================================;

EBPB_drivenumdb ?     ;0. Номер привода.

EBPB_NTflagsdb ?     ;1. Флаги в Windows NT. Бит 0 - флаг необxодимости проверки диска. Бит 1 - флаг необходимости диагностики ;поверхности.

EBPB_extsigndb ?     ;2. Признак расшренного BPB по версии DOS 4.0.

EBPB_volIDdd ?     ;3-6. "Серийный номер". Любое случайное число или ноль, без разницы.

EBPB_vollabeldb ?,?,?,?,?,?,?,?,?,?,?     ;7-17. Название диска. Устарело.

EBPB_filesysdb ?,?,?,?,?,?,?,?     ;18-25. Имя файловой системы.

db ?     ;Еще один байт для того, чтобы структура занимала 15 32-битных слов.


Как видите, в этом варианте переменным не присвоены значения. Кроме того, в конце

зарезервирован ещё один байт. Он нужен для того, чтобы размер таблицы делился на 4

и её можно было загрузить как последовательность 32-битных слов, не перетерев

ничего лишнего. Теперь нужна процедура.


read_BPB proc

     push cx     ;Сохранить регистры.

     push di

     push si

     push ds


     push 07C0h

     pop ds     ;DS=07C0h, сегмент первичного загрузчика.

     mov si,3     ;SI=смещение BPB в ПЗ.

     mov di,offset BPB     ;DI=смещение BPB в loader.bin

     mov cx,15     ;CX=счётчик для копирования.

     rep movsd     ;Скопировать 15 32-битных слов, размер BPB+1 байт.


     pop ds     ;Восстановить регистры.

     pop si

     pop di

     pop cx

     ret     ;Завершить процедуру.

read_BPB endp


Тут в общем всё просто. Устанавливаем пару регистров DS:SI на начало BPB в первичном загрузчике,

а ES:DI - на нашу неинициализированную структуру. Потом командой rep movsd копируем всю

конструкцию + 1 байт. Вызовите процедуру инструкцией call после установки сегмента стека -

и готово. Кстати, вопрос знатокам: что быстрее выполнит 32-битный процессор в 16-битном

режиме - копирование 15 32-битных слов или 30 16-битных?


На этом пока всё. Сделайте новый батч файл с примерно таким текстом, чтобы не возиться

с инструкциями вручную:


tasm project\boot\stage2\loader.asm

tlink loader.obj

exe2bin loader.exe


Слинкуйте файл, закиньте на дискету - и готово. Сообщение о том, что loader.bin

не найден, должно пропасть. В следующий раз - установка видеорежима и методы вывода

текста.


Ссылка на полный полный текст модуля: https://drive.google.com/file/d/1rFc3OcEDmf7Rs_hEJ6iX98-1SimN_dx_/view?usp=sharing



Подробнее
Plex86/Bochs UGABios (PCI) 0.7b 03 Jan 2020 This UGA/UBE Bios is released under the GNU LGPL Please visit : . http://bochs.sourceforge.net . http //www.nongnu.org/vgab ios Bochs UBE Display Adapter enabled Bochs 2.6.10.svn BIOS - build: 01/05/20 ^Revision: 13752 $ $Date: 2019-12-30 14:16:18 +0100 (Mon, 30 Dec 2019) $ Options: apmbios pcibios pnpbios eltorito rombios32 Press F12 for boot menu. Booting from Floppy... LOADER BIN not found!
программирование,geek,Прикольные гаджеты. Научный, инженерный и айтишный юмор,OSDev,Операционная система,разработка,ассемблер,длиннопост,песочница
Еще на тему
Развернуть
это что-то слишком уж заумное, ты молодец, что пытаешься донести людям знания, но место выбрал явно неудачное, я вот сам занимаюсь околопрограммированием, но что-то серьезное я точно не стану искать и изучать на рекаторе, я сюда захожу котиков и сиськи посмотреть, как я думаю и большинство, лучше запостить это где-нибудь на хабре
Кому как. Я тут встречаю много постов по истории, всяким хобби, околонаучные и т.п. С удовольствием читаю.
Мне норм, пиши ещё. И на хабр тоже, если там нет. Ну или ссылку добавляй на хабр, другой бложик.
loyreni loyreni 26.09.202012:28 ответить ссылка 0.0
Как ни странно, на хабре меня нет. Я вообще это постить решил для самодисциплины, чтобы на разработку не забивать. А джой просто под рукой, так сказать, был.
Тогда продолжай, мне нравится.
А быть может, лучше стоит описание в Markdown и на какой-нибудь Github выкладывать, а сюда ссылку? Просто джой хреново подходит для чтения текстов, особенно, технических. Трудно разбирать.
А может быть, кстати. Подумаю.
Пробежался мельком по тексту и картинкам - статья интересная, хоть я почти ничего и не понял, но для общего развития самое то.
Это восьмая серия уже. Ты по всем с начала пройдись - станет понятнее.
Только зарегистрированные и активированные пользователи могут добавлять комментарии.
Похожие темы

Похожие посты
Programmers in Enterprise Company
Programmers in Startup Company
Programmers in Government 		i-^ * TI Кто-нибудь хочет что-то сказать?
Я юзаю линукс ;Нулевой дескриптор, сЫ 00001л бы 00001л db 001л
с1Ь 00000000Ь с1Ь 00000000Ь с!Ь 001л
¿Дескриптор сегмента бы 0РРРР1л с!ы 00001л с!Ь 001л
дЬ 10011010Ь с!Ь 11001111Ь с!Ь 001л
¿Дескриптор сегмента бы 0РРРР1л бы 00001л с!Ь 001л
6Ь 10010010Ь 6Ь 11001111Ь с1Ь 001л
¿Биты 0-15 предела.
¿Биты 0-15 о
подробнее»

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

;Нулевой дескриптор, сЫ 00001л бы 00001л db 001л с1Ь 00000000Ь с1Ь 00000000Ь с!Ь 001л ¿Дескриптор сегмента бы 0РРРР1л с!ы 00001л с!Ь 001л дЬ 10011010Ь с!Ь 11001111Ь с!Ь 001л ¿Дескриптор сегмента бы 0РРРР1л бы 00001л с!Ь 001л 6Ь 10010010Ь 6Ь 11001111Ь с1Ь 001л ¿Биты 0-15 предела. ¿Биты 0-15 о