В предыдущей заметке я рассказывал о том, как написать на ассемблере программу HelloWorld, которая будет запускаться на голом железе (без операционной системы), как скомпилировать ее и записать образ загрузочной дискеты, и как заставить виртуальную машину загружаться с этой дискеты. Я собираюсь и дальше писать подобные программы. Каждая последующая программа будет делать что-то новое по сравнению с предыдущими. Но для начала я собираюсь немного систематизировать процесс разработки этих программ.
- Я создал удаленный репозиторий под названием osdevlearning. О том, как создать репозиторий, я рассказывал здесь.
- В папке своего локального репозитория osdevlearning я создаю папку HelloWorld_RealMode. В эту папку я помещу файлы программы HelloWorld, описанной в предыдущей заметке. В дальнейшем для каждой новой программы я буду создавать отдельную папку в папке osdevlearning.
-
В папке osdevlearning я создаю файл .gitignore, в который записываю расширения тех файлов, которые не хочу добавлять в систему управления версиями — это двоичные файлы, генерируемые ассемблером FASM и утилитой dd. Они имеют расширения
.bin
и.img
соответственно.
Что за файлы я собираюсь добавить в папку HelloWorld_RealMode? Вот они (такое вот красивое дерево генерирует программа tree в среде Cygwin):
├── HelloWorld_RealMode
│ ├── bochsrc.bxrc
│ ├── boot_sector.asm
│ └── makefile
└── README.txt
- boot_sector.asm — исходный код программы HelloWorld. Я обозвал его так потому, что он представляет собой содержимое загрузочного сектора дискеты, с которой будет грузиться наша виртуальная машина.
-
bochsrc.bxrc — файл настроек виртуальной машины Bochs, который содержит информацию о том, что в системе есть дисковод гибких дисков, и что в этот дисковод вставлена дискета, и где на находится образ этой дискеты. Каждая новая программа, которую я буду писать будет иметь такой вот файл bochsrc.bxrc. Двойным щелчком по этому файлу я смогу запускать программу на выполнение. Файл bochsrc.bxrc содержит помимо прочего одну важную строку:
floppya: type=1_44, 1_44="floppy.img", status=inserted, write_protected=0
floppy.img — это имя файла образа загрузочной дискеты, который находится в той же папке, что и bochsrc.bxrc. Это важно, что в той же папке, так как путь к файлу floppy.img здесь указан относительно той папки, где находится bochsrc.bxrc.
- makefile — текстовый файл, который содержит инструкции, которые запускают ассемблер FASM и утилиту dd.
О файле makefile стоит поговорить подробнее. Это специальный файл, который содержит инструкции по построению нашего проекта. Выполняет эти инструкции утилита make, которая входит в состав среды Cygwin. Существует аналогичная утилита от Microsoft, которая входит в состав Windows SDK и называется nmake. Когда вы запускаете утилиту make, она ищет в текущей папке файл под названием makefile. Найдя его, она начинает выполнять записанные в нем инструкции. Содержимое файла makefile имеет специальный формат. Дело в том, что в проекте файлы зависят друг от друга. Поясню на примере. Вначале у меня есть файл исходного кода boot_sector.asm — я создаю его сам. Затем при помощи ассемблера FASM я генерирую из файла boot_sector.asm файл boot_sector.bin. Затем при помощи утилиты dd я генерирую из файла boot_sector.bin файл floppy.img. Таким образом, файл floppy.img зависит от файла boot_sector.bin, а файл boot_sector.bin зависит от файла boot_sector.asm. Если изменился исходный код в файле boot_sector.asm, то нужно обновить (путем запуска программ FASM и dd) файлы boot_sector.bin и floppy.img. Если же, допустим, изменился файл boot_sector.bin, то надо обновить только файл floppy.img (путем запуска программы dd). Структура файла makefile отражает эти зависимости между отдельными файлами:
инструкция1
инструкция2
инструкция3
файл2 : файл4 файл5 файл6
инструкция4
инструкция5
инструкция6
В приведенном примере файл 1 зависит от файлов 2 и 3, а файл 2 зависит от файлов 4, 5 и 6. Если изменится файл 3, то утилита make запустит инструкции 1, 2 и 3, а если изменится, скажем, файл 6, то make запустит инструкции 4, 5, 6, а потом 1, 2 и 3.
makefile в папке HelloWorld_RealMode выглядит вот так:
dd if="/dev/zero" of="floppy.img" bs=1024 count=1440
dd if=boot_sector.bin of=floppy.img conv=notrunc
boot_sector.bin : boot_sector.asm
fasm boot_sector.asm boot_sector.bin
Всё. В следующей заметке переведем процессор в защищенный режим и выведем на экран сообщение «Hello World!» уже из защищенного режима.