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

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

Уроки ОСдева №2: схемы адресации и твоя первая программа на ассемблере

Если кто-то решил следовать этим туторам, самое время обзавестись необходимыми инструментами. Скачайте turbo assembler (TASM) или любой другой привычный вам. Установите виртуальную машину с Windows XP. Работать с большинством используемых программ проще в ней. Я бы посоветовал Oracle VirtualBox.


CHS


В прошлый раз мы выяснили несколько важных вещей:

- для того, чтобы загрузить ОС с дискеты, нам нужна программа-загрузчик.

- программа-загрузчик должна занимать ровно 512 байт, причём последние два байта должны содержать метку загрузчика (AA55h).

- программа-загрузчик должна располагаться в первом физическом секторе носителя.


Эта информация в свою очередь ставит перед нами новый вопрос: как поместить загрузчик на полагающееся ему место? Придётся разбираться в схемах адресации данных на цифровых носителях. Тема не очень простая, но необходимая, так что крепитесь.


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


На картине выше - структура дискового носителя. Это может быть жёсткий диск, дискета или CD, суть не поменяется. Головка, она же лицо, - это одна сторона поверхности носителя (пластины). У жёсткого диска на рисунке 4 двусторонних пластины, то есть 8 головок. Головка в свою очередь разбита на концентрические дорожки (они же цилиндры), а те - на одинакового размера (как правило 512 байт) секторы. Независимо от радиуса цилиндра в каждом из них одинаковое число секторов, что позволяет для доступа к любому конкретному сектору использовать трёхкомпонентную координату Цилиндр-Головка-Сектор (Cylinder-Head-Sector, CHS). Важно помнить, что в системе CHS цилиндры и головки нумеруются с 0, а секторы - с 1. То есть для доступа к первому физическому сектору носителя наши координаты будут иметь значения: 0(цилиндр), 0(головка), 1(сектор).


Проблема в том, что привычные нам файловые системы скрывают физическую геометрию носителей за набором абстракций вроде файлов и папок. К счастью, есть альтернативы. Например, в Windows есть команда debug. Выглядит так:


debug boot.bin(имя файла, загружается в память по адресу 100h)

-w(запись) 100(адрес загруженного файла) 0(номер привода) 0(номер первого сектора) 1(число секторов для загрузки)

-q(выход)


Я выше писал, что секторы нумеруются с 1, но debug закон не писан. Всё остальное время правило в силе.


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


LBA


Информацию из этого раздела мы пока использовать не будем, но позже она пригодится. Формат CHS на сегодняшний день устарел. Практически все устройства нативно поддерживают схему адресации под названием LBA (Linear Block Addressing), в которой к секторам обращаются просто по их порядковому номеру, без учёта геометрии носителя. Тем не менее, CHS поддерживается на уровне эмуляции и для работы с дискетами пользоваться мы будем именно ей.


boot.asm


Итак, мы разобрались, как поместить нашу программу в нужное место на дискете. Самое время приступать к написанию кода! Мы, конечно, не будем в этот раз писать полный загрузчик. Это будет просто небольшая вводная в турбо ассемблер. Она предназначена для людей без опыта в ассемблере и подразумевает, что вы будете пользоваться TASM. Если вы уже знаете x86 ассемблер и намерены пользоваться каким-то другим - смело пропускайте конец статьи.


Скачали TASM? Отлично, инсталлируйте его в какое-нибудь легкодоступное место на диске и в папке BIN/ создайте папки OS/boot/stage1/.


Теперь в stage1/ создайте пустой текстовый файл, переименуйте его в boot.asm и откройте текстовым редактором. В файле создайте следующий текст:


.386p

CSEG segment use16

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

begin:


CSEG ends

end begin


Сделали? Сохраните и давайте разбираться. Сразу скажу, что собственно программы здесь пока нет. Всё, что вы видите - набор инструкций для компилятора, в исполняемый файл они не попадут.


.386p - указание компилятору сверять инструкции с набором для 386 процессора в защищённом (protected, отсюда p) режиме. Соответственно, если компилятор встретит инструкцию, которую данный процессор не поддерживает, он выдаст ошибку.


CSEG - название сегмента, в котором будет содержаться код нашей программы.


Следующую строчку будет сложно объяснить, т.к. мы пока не касались устройства процессора, так что просто примите как есть: это указание компилятору считать, что все сегментные регистры процессора указывают на сегмент CSEG.


begin - метка начала программы. Отсюда будет начинаться собственно код.


CSEG ends - конец сегмента CSEG.


end begin - метка конца программы.


Скомпилировать программу в таком виде не выйдет, так как в ней нет ни одной инструкции. Давайте добавим парочку.


.386p

CSEG segment use16

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

begin:                    cli

                             hlt

CSEG ends

end begin

Мы добавили 2 команды: cli и hlt. Первая запрещает прерывания, то есть не даёт устройствам отправить сигнал процессору, а вторая останавливает сам процессор. Таким образом, сейчас наша программа при запуске просто "вешает" компьютер. Тем не менее, её уже можно превратить в исполняемый файл.


Откройте командную строку, перейдите в папку BIN/ и введите: tasm OS/boot/stage1/boot.asm. После нажатия enter в папке BIN/ появится файл BOOT.OBJ. Это ещё не конец. Файл .obj - это инструкция для линкера, так что пишите: tlink boot.obj. Теперь у вас добавились два новых файла, BOOT.MAP и BOOT.EXE, последний из которых - и есть исполняемый файл, который нам нужен! Незадача в том, что мы пишем не приложение под DOS, а операционную систему, которая должна будет работать на голом железе. exe-формат содержит таблицы релокации и всякие прочие данные, которые нам будут мешать. В нашем исполняемом файле должны быть только инструкции программы и больше ничего. К счастью, и тут есть готовое решение. Пишите в командной строке exe2bin boot.exe и жмите enter. Появился файл boot.bin. Проверьте его размер, он должен занимать ровно 2 байта, по одному байту на инструкции cli и hlt. Успех!


В качестве ДЗ предлагаю всем желающим самостоятельно загнать файл в первый сектор дискеты, вся нужная информация в тексте статьи есть.


Подробнее

geek,Прикольные гаджеты. Научный, инженерный и айтишный юмор,OSDev,Операционная система,разработка,программирование,ассемблер,песочница
Еще на тему
Развернуть
Забавная идея но вы кажется свою статью на джойреактор запостили.
А ты предлагаешь на Хабр запостить? Ну уж нет, пусть лучше здесь будет.
На хабре нечто подобное уже в наличии, скорее всего.
На Хабре есть все, но это "все" тонет в куче рекламы и статей типа: "Смотрите какая наша организация классная и она смогла достигнуть цели с помощью 1 селекта и 1 апдейта"
Так плотность на дисках разная? И изменив алгоритм возможен иновационный рост объема!
В принципе возможен. Я в одной из следующиx статей напишу. На 1,44 дискетку можно больше инфы вместить в принципе, но с оговоркой что стабильность чтения пострадает.
А, ну и есть модель адресации ZBR. В ней как раз на внешниx дорожкаx больше секторов, чем на внутренниx, но есть неудобство в виде разной скорости чтения/записи с разныx участков диска.
в debuge же есть встроенный ассемблер, который напрямую com делает.
по крайней мере был 20 лет назад, когда я этим занимался.
Нам не нужен ком, нам нужен бин. Совсем плоский бинарник без всего лишнего.
Офигеть, это всё такое древнючее легаси! Оно было устаревшим уже десятки лет назад. TASM, debug, 16-битный ассемблер. Зачем тратить время на изучение протухшего синтаксиса TASM, когда современные утилиты ассемблера используют совершенно другую нотацию? И вообще нынче другой инструментарий и окружение.
dadv dadv 20.10.201900:17 ответить ссылка 1.0
Это какой сейчас инструментарий?
32, 64 и 128-битный (SSE) ассемблер GNU as или LLVM-as под юниксы в качестве ассемблера и соответствующие binutils или аналоги; что под 64-битную Windows сейчас используется, даже не в курсе, возможно MASM 9 или новее.

И уж точно никаких 16-битных сегментов, а плоская модель памяти с учётом работы под управлением UEFI или операционной системы.
dadv dadv 20.10.201903:38 ответить ссылка 0.0
Я не знаю, в каком виде загрузчик UEFI оставляет систему по окончании работы, но практически на 100% уверен, что любой BIOS оставляет процессор в реальном (16-битном) режиме, так что задача переключить его в 32-битный, а затем по необxодимости в 64-битный всё-таки остается на пользовательском загрузчике. Значит, всё-таки сегменты и вся xуйня.

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

Зачем изучать устаревшие на твой взгляд теxнологии? Затем, что философия обратной совместимости говорит нам, что пока теxнология не устарела как говно мамонта, она поддерживается большим числом машин, чем та, которая идет ей на смену.
> Я не знаю, в каком виде загрузчик UEFI оставляет систему по окончании работы

А поинтересуйся. В 32-битном или 64-битном, в зависимости от возможностей CPU. Соответственно, пользовательский загрузчик адресует всю память непосредственно безо всяких сегментов.

> большим числом машин, чем та, которая идет ей на смену.

На самом деле нет. Потому что новых машин выпускается больше, чем раньше выпускалось старых. Плюс старые выбывают. В случае ассемблера "старые" это 16-битные, то есть все старше 80386DX, который был уже полностью 32-битным. А в случае загрузки спецификация UEFI версии 2.1 датируется 2007-м годом, то есть 12-летней давностью.
dadv dadv 20.10.201904:43 ответить ссылка 0.1
x86й ассемблер сосет -___-
Fedorchik Fedorchik 20.10.201901:17 ответить ссылка -0.5
А шо, стаковерфлоу SJWшники закрыли и он преехал сюда? Не я не против, но как же тогда шутеечки. Вот если бы это была программа на перле в стиле rm -rf /
GreKo GreKo 20.10.201902:14 ответить ссылка 0.0
rm -rf / есть в виде регулярного выражения для sed.
"Ты бы ещё консервных банок насобирал" ©
Современный OSdev не нуждается в том, что здесь написано.
nonnname nonnname 20.10.201908:08 ответить ссылка -0.6
А, ок. Сорян, ребята, сворачиваю лавочку. Начальник осдева подъехал.
UEFI - это по сути однопотоковая, однопользовательская ОС, в которой можно запустить драйвера для ФС, видюх, сетевух и т.д., при наличии оных от производителя. USBFlash, SATA, PXE, а также поддержка ФС FAT32 идут по умолчанию. CHS уже давно был послан нахер. Везде LBA. MBR потихоньку вымирает.
Спецификация UWFI однозначно определяет в каком режиме работает. API UEFI позволяет организовать что угодно, кроме многопользовательского и многопоточного режима.
nonnname nonnname 20.10.201916:51 ответить ссылка -0.1
Только зарегистрированные и активированные пользователи могут добавлять комментарии.
Похожие темы

Похожие посты
Programmers in Enterprise Company
Programmers in Startup Company
Programmers in Government 		i-^ * TI Кто-нибудь хочет что-то сказать?
Я юзаю линукс