Оглавление
§ Загрузка BIOS

Когда компьютер начинает работу, то он проходит множество этапов
загрузки. Самым первым делом, устанавливается адрес F000:FFF0, в реальном режиме работы процессора (правда, я сейчас не знаю, как современные компьютеры загружаются), и вот оттуда начинает работать биос (или его аналог), который проверяет диски, память, все внутренние подсистемы, инициализирует все что может.
И вот как раз именно после всех инициализации, условно будем называть это биосом (efi, uefi, bios, у него куча разных названий сейчас появилось), вызывает первый сектор (Master Boot Record, если не по-нашему) с какого-нибудь диска, даже с сети может, неважно, и укладывает этот сектор адресу в памяти 0000h : 7C00h. Понятное дело, что размер сектора равен 512 байтам. Попробуй развернись в этом количестве байт и сделай что-то! Нет, находятся умельцы, которые и кубы крутят, и шахматы мутят.
§ Что делать дальше
Чем заняться после загрузки в память? Конечно, надо что-то инициализировать, как же без инициализации, все инициализируют, а я что, хуже что ли? Я тоже буду.
org 7C00h
cli
cld
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 7C00h
times (7C00h-$)+510 db 255
dw 0xAA55
Замечу, что если у бутсектора не будет в конце сектора 2 байта с сигнатурой 55 AA, то такой бутсектор будет считаться биосом не бутсектором, а мусором и ничего он не загрузит.
А где же CS=0000? Он и так ноль, так что все в порядке. После инициализации, конечно, интересно узнать, а как же этот бутсектор записать, чтобы он вообще как-нибудь заработал? И вот тут начинаются проблемы вселенского масштаба.
Как и обычно, надо ассемблер включить. Он всегда находится под рукой и называется [[https://flatassembler.net/ flat assembler]]. Очень удобный.
После сложных установок, настроек, калибровки, интеграции и инкапсуляции в хост-систему, можно будет написать приблизительно такой запускной файл, например, makefile:
С помощью этого набора команд будет сформирован новый файл boot.bin, в котором и будет содержаться бутсектор.
§ Отладчик bochs
Про этот отладчик я узнал очень давно, еще когда сидел на windows xp, а не в линуксе, как сейчас, и потому пользоваться я им, конечно, не научился толком, но кое-что загружать получалось. Как настроить отладчик, я уже [[/help/os_bochs_win сто раз писал]] везде где ни попадя. Настраиваю я его под winxp, конечно же. А как же линукс? Какой еще линукс? Нет никакого линукса, есть винда и она навсегда.
Проблема следующая. Файловую систему разметить с помощью винды мне не удастся, потому придется изобретать свои велосипеды на языке программирования php, чем далее я и буду заниматься после того, как бутсектор напишу.
Для того, чтобы загрузить сектор, надо диск создать. Утилита bximage в этом мне поможет хотя бы:
- Тип диска – hd
- Способ записи – flat
- Количество мегабайт – 256 (сойдёт для сельской местности)
- Имя диска – c.img
Вот что он мне предлагает сделать:
ata0-master: type=disk, path="c.img", mode=flat
Поэтому эту строку можно добавить в файл конфигурации 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-файл):
Я сейчас проверил, у меня все заработало. Конечно, чтобы это все заработало, надо, чтобы все было правильно настроено. Без точной настройки ничего работать не будет.
§ Как запустить загрузчик
Есть несколько идей, как это сделать. Первая – велосипедом, вторая... не знаю. Придется велосипедом. Создам файл main.cc, например:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
return 0;
}
Компилировать известно как: g++ main.cc -o bootwriter. Должно заработать. Makefile будет выглядеть примерно так:
NAME=bootwriter.exe
all: $(NAME)
fasm boot.asm boot.bin
$(NAME): main.cc
g++ main.cc -o $(NAME)
strip $(NAME)
То есть, если нет файла bootwriter.exe, то он его создает. На линуксе это может и не будет работать, не проверял – страшно.
Вопрос такой – как нарисовать сову? Делается очень легко! Сначала сделайте два кружочка. Если два кружочка готовы, нарисуйте сову целиком. Сова готова! Следующий код для main.cc будет это правило демонстрировать:
unsigned char buf[512] = {0};
if (argc < 3) return -1;
FILE* fr = fopen(argv[1], "rb");
FILE* fw = fopen(argv[2], "rb+");
if (fr == NULL || fw == NULL) return -2;
fread(buf, 1, 446, fr);
fwrite(buf, 1, 446, fw);
buf[0] = 0x55; buf[1] = 0xAA;
fseek(fw, 510, SEEK_SET);
fwrite(buf, 1, 2, fw);
fclose(fr);
fclose(fw);
[/code]
Что делает этот код?
[code bat]
$(NAME) boot.bin c.img
Если его запустить так, то код перепишет первые 446 байт в первый сектор и запишет сигнатуру, чтобы биос распознал этот сектор. Вот теперь можно уже попробовать написать что-нибудь, например, Hello World, в самом main.asm:
mov si, Hello
@@: lodsb
and al, al
je $
mov ah, 0Eh
int 10h
jmp @b
Hello: db "Hello World",0
Осталось только скомпилировать и запустить. У меня все нормально получилось.
Самое главное в программировании, это конечно, написать HELLO WORLD. Если этого не будет, то зачем тогда программировать?