§ Загрузка BIOS
Когда компьютер начинает работу, то он проходит множество этапов загрузки. Самым первым делом, устанавливается адрес F000:FFF0, в реальном режиме работы процессора (правда, я сейчас не знаю, как современные компьютеры загружаются), и вот оттуда начинает работать биос (или его аналог), который проверяет диски, память, все внутренние подсистемы, инициализирует все что может.И вот как раз именно после всех инициализации, условно будем называть это биосом (efi, uefi, bios, у него куча разных названий сейчас появилось), вызывает первый сектор (Master Boot Record, если не по-нашему) с какого-нибудь диска, даже с сети может, неважно, и укладывает этот сектор адресу в памяти 0000h : 7C00h. Понятное дело, что размер сектора равен 512 байтам. Попробуй развернись в этом количестве байт и сделай что-то! Нет, находятся умельцы, которые и кубы крутят, и шахматы мутят.
§ Что делать дальше
Чем заняться после загрузки в память? Конечно, надо что-то инициализировать, как же без инициализации, все инициализируют, а я что, хуже что ли? Я тоже буду.org 7C00h ; Указываем ассемблеру, что код начинается с 7C00h cli ; IF=0 теперь прерывания не вызываются cld ; DF=0 теперь все lods/movs/stos/etc возрастают xor ax, ax ; AX=0000 mov ds, ax ; DS=0000 mov es, ax ; ES=0000 mov ss, ax ; SS=0000 mov sp, 7C00h ; SP=7C00 ; ... остальной код ... times (7C00h-$)+510 db 255 ; Заполнить FFh оставшиеся 510 байт dw 0xAA55 ; Сигнатура бутсектораЗамечу, что если у бутсектора не будет в конце сектора 2 байта с сигнатурой
55 AA
, то такой бутсектор будет считаться биосом не бутсектором, а мусором и ничего он не загрузит.А где же
CS=0000
? Он и так ноль, так что все в порядке. После инициализации, конечно, интересно узнать, а как же этот бутсектор записать, чтобы он вообще как-нибудь заработал? И вот тут начинаются проблемы вселенского масштаба.Как и обычно, надо ассемблер включить. Он всегда находится под рукой и называется flat assembler. Очень удобный.
После сложных установок, настроек, калибровки, интеграции и инкапсуляции в хост-систему, можно будет написать приблизительно такой запускной файл, например, makefile:
fasm boot.asm boot.binС помощью этого набора команд будет сформирован новый файл
boot.bin
, в котором и будет содержаться бутсектор.§ Отладчик bochs
Про этот отладчик я узнал очень давно, еще когда сидел наwindows xp
, а не в линуксе, как сейчас, и потому пользоваться я им, конечно, не научился толком, но кое-что загружать получалось. Как настроить отладчик, я уже сто раз писал везде где ни попадя. Настраиваю я его под winxp, конечно же. А как же линукс? Какой еще линукс? Нет никакого линукса, есть винда и она навсегда.Проблема следующая. Файловую систему разметить с помощью винды мне не удастся, потому придется изобретать свои велосипеды на языке программирования
php
, чем далее я и буду заниматься после того, как бутсектор напишу.Для того, чтобы загрузить сектор, надо диск создать. Утилита bximage в этом мне поможет хотя бы:
- Тип диска — hd
- Способ записи — flat
- Количество мегабайт — 256 (сойдёт для сельской местности)
- Имя диска — c.img
"c.img", mode=flatata0-master: type=disk, path=Поэтому эту строку можно добавить в файл конфигурации c.bxrc.
megs: 32 romimage: file=c:/bochs/BIOS-bochs-latest vgaromimage: file=c:/bochs/VGABIOS-lgpl-latest ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata0-master: type=disk, path="c.img", mode=flat, biosdetect=auto, translation=auto boot: c display_library: win32, options="gui_debug" log: bochsout.txt mouse: type=ps2, enabled=0, toggle=ctrl+mbutton cpu: ips=15000000 clock: sync=both keyboard: keymap=c:/bochs/keymaps/x11-pc-us.map magic_break: enabled=1Тут есть зависимая конфигурация keymap, если она находится в другом месте, надо поправить путь. Тут есть такая опция как
magic_break
, если она активирована, то отладчик будет останавливаться на инструкции xchg bx,bx
что просто крайне полезно, потому что без этого отладка почти что невозможна.Запускать этот файл надо так (предварительно в makefile какой-нибудь оформить или bat-файл):
bochsdbg -f c.bxrc -qЯ сейчас проверил, у меня все заработало. Конечно, чтобы это все заработало, надо, чтобы все было правильно настроено. Без точной настройки ничего работать не будет.
§ Как запустить загрузчик
Есть несколько идей, как это сделать. Первая — велосипедом, вторая... не знаю. Придется велосипедом. Создам файлmain.cc
, например:#include <stdlib.h> #include <stdio.h> int main(int argc, char* argv[]) { return 0; }Компилировать известно как:
g++ main.cc -o bootwriter
. Должно заработать. Makefile будет выглядеть примерно так:all: $(NAME) fasm boot.asm boot.bin $(NAME): main.cc g++ main.cc -o $(NAME) strip $(NAME)NAME=bootwriter.exe То есть, если нет файла bootwriter.exe, то он его создает. На линуксе это может и не будет работать, не проверял — страшно.
Вопрос такой — как нарисовать сову? Делается очень легко! Сначала сделайте два кружочка. Если два кружочка готовы, нарисуйте сову целиком. Сова готова! Следующий код для
main.cc
будет это правило демонстрировать:unsigned char buf[512] = {0}; if (argc < 3) return -1; // Аргументов должно быть 2 // Открыть файл на чтение и второй файл на запись FILE* fr = fopen(argv[1], "rb"); FILE* fw = fopen(argv[2], "rb+"); // Если один из них открыть не удалось if (fr == NULL || fw == NULL) return -2; // Прочесть и записать 446 байт (не 512!) fread(buf, 1, 446, fr); fwrite(buf, 1, 446, fw); // Подготовить 55 AA и записать в последние 2 байта первого сектора buf[0] = 0x55; buf[1] = 0xAA; fseek(fw, 510, SEEK_SET); fwrite(buf, 1, 2, fw); // Закрыть файлы fclose(fr); fclose(fw);Что делает этот код?
$(NAME) boot.bin c.imgЕсли его запустить так, то код перепишет первые 446 байт в первый сектор и запишет сигнатуру, чтобы биос распознал этот сектор. Вот теперь можно уже попробовать написать что-нибудь, например, Hello World, в самом main.asm:mov si, Hello ; Ссылка на строку Hello @@: lodsb ; Загрузка нового символа в AL and al, al ; Проверить AL на 0 je $ ; Если 0, то остановить процессор mov ah, 0Eh ; AH=0Eh код печати символа int 10h ; Печать символа jmp @b ; Повтор Hello: db "Hello World",0Осталось только скомпилировать и запустить. У меня все нормально получилось.
Самое главное в программировании, это конечно, написать "HELLO WORLD". Если этого не будет, то зачем тогда программировать?
Файл как обычно, можно скачать: hello-world.zip