§ Устройство MBR
Начнем с того, что бутсектор должен располагаться в MBR. Дело в том, что после разметки диска, начиная с 446-го байта и заканчивая 512-м, на диске уже есть разметка 4 primary разделов. По этой причине, код бутсектора для диска (hd) а не флоппи (fd), должен быть не более 446 байт. Это очень важно. Сам же код сектора загружается биосом по адресу 0000h:7C00h (CS=0000h, IP=7C00h) в реальном режиме работы процессора. Это так всегда происходит. Наша задача что-то сделать с этим.000 Программный код бут загрузчика 1BE Дескриптор 1-го раздела диска (16 байт) 1CE Дескриптор 2-го раздела диска (16 байт) 1DE Дескриптор 3-го раздела диска (16 байт) 1EE Дескриптор 4-го раздела диска (16 байт) 1FE Сигнатура 0xAA55 (или 55h AAh)Сама же структура раздела такая
00 1 Признак активности раздела 01 1 Начало раздела — головка 02 1 Начало раздела — сектор (биты 0—5), цилиндр (биты 6, 7) 03 1 Начало раздела — цилиндр (старшие биты 8, 9 хранятся в байте номера сектора) 04 1 Код типа раздела 05 1 Конец раздела — головка 06 1 Конец раздела — сектор (биты 0—5), цилиндр (биты 6, 7) 07 1 Конец раздела — цилиндр (старшие биты 8, 9 хранятся в байте номера сектора) 08 4 Смещение первого сектора 0C 4 Количество секторов разделаВ современных дисках головка, сектор и цилиндр вообще ни к чему. К тому же, даже смещение или первого сектора количество секторов на диске, описанных через 4 байта, может быть не таким большим. Ну сколько он может быть? Допустим, сектор занимает 512 байт, а максимально адресуемый размер диска получится 2^32*2^9 = 2^41 байт. Так как 1 гигабайт = 2^30 байт, то тогда 2^41/2^30 = 2^11 гигабайт (2048 Гб), что равно 2 терабайта. Сейчас диски есть на 4 Тб, какой там 2 Тб. И вот как с этим справляется наш герой? Все на просмотр картины второй! (Шутка) На самом деле для больших дисков используется GPT-механизм, который только в UEFI есть, а в старом BIOS этого нет. Никто не знал, что 4Тб диски вообще будут в природе. Но поскольку мои диски более 512 Гб не особо превышают, то мне норм.
§ Обновление сектора
Я думаю, что нужно написать простой makefile для обновления сектораall: rm -f *.lock fasm boot.asm dd conv=notrunc if=boot.bin of=disk.img bs=446 count=1 bochs -f c.bxrc -q > /dev/null 2>&1Сначала удаляются лок-файлы, если они были, потом ассемблируется файл boot.asm, далее с помощью утилиты dd заменяются первые 446 байта на диске и запускается bochs.
Сам же код boot.asm максимально прост:
org 7C00h cld ; На всякий случай sti ; Чтобы реагировал на CTRL+ALT+DEL xor ax, ax mov ds, ax mov es, ax mov ss, ax mov sp, 7C00h jmp $В этом коде просто устанавливаются сегментные регистры в 0 и стек ставится под кодом бут-сектора.
Напишу Hello World, используя функцию BIOS INT 10h
mov si, ab ; Ссылка на строку @@: mov ah, 0Eh ; 0Eh печать символа в терминале lodsb ; Загрузка символа из DS:SI and al, al ; Проверка AL на 0 je $ ; Если 0, остановить процессор int 10h ; Напечатать символ jmp @b ; Перейти к следующему ab: db "Hello World",0Чтобы выгрузить данный бут-сектор на реальную флешку, можно воспользоваться такой командой
sudo dd conv=notrunc if=boot.bin of=/dev/sdX bs=446 count=1Где /sdX - это устройство флешки, например, sdd или sde, это надо узнать через команду df -h
, там будет выведен список подключенных устройств.Я вот проверил свой код, все работает хорошо.
§ Вариант с загрузкой 32Кб
org 7c00h macro brk { xchg bx, bx } cli cld xor ax, ax mov ds, ax mov es, ax mov ss, ax mov sp, 7C00h ; Задача boot-сектора это загрузить и запустить программу ; Конечно же, лучше чтобы программа была в FAT, но пока что так mov [7C00h], dl ; Сохранить DL (Drive Letter ;) mov ah, 41h ; Проверка на поддержку режима DAP mov bx, 55AAh int 13h jc error mov ah, 42h ; Загрузить сектор в память mov si, DAP mov dl, [7C00h] int 13h jc error jmp 0 : 8000h ; Передача управления ; Ничего не делать error: jmp $ ; ------------------------------------------------------------------------------ DAP: dw 0010h ; 0 | размер DAP = 16 dw 0040h ; 2 | читать 64 секторов (32 кб) dw 0000h ; 4 | смещение (=0) dw 0800h ; 6 | сегмент (=800h) * 10h = 0000:8000 dq 1 ; 8 | номер сектора от 0 до N-1 (1 = второй сектор)
§ Загрузка с Floppy
macro brk { xchg bx, bx } org 7c00h jmp short start db 00h ; ---------------------------------------------------------------------- ; BPB: Bios Parameter Block ; ---------------------------------------------------------------------- db "FLOPPY12" ; 03 Signature dw 200h ; 0B Bytes in sector db 1 ; 0D Sectors by cluster dw 65 ; 0E Count reserver sectors (32K+Boot) db 2 ; 10 Count of FAT dw 00E0h ; 11 Count of Root Entries (224) dw 0B40h ; 13 Total count of sectors db 0F0h ; 15 Media dw 9 ; 16 Sectors in FAT dw 12h ; 18 Sectors on track dw 2 ; 1A Count of heads dd 0 ; 1C Hidden Sectors (large) dd 0 ; 20 Total Sectors db 0 ; 24 Number of Phys. db 1 ; 25 Flags db 29h ; 26 Ext Sig dd 07E00000h ; 27 Serial Numbers ES:BX db 'CORE BIN' ; 2B Label / Exec File db 'FAT12 ' ; 36 Type of FS ; ---------------------------------------------------------------------- start: cli cld xor ax, ax mov ds, ax mov es, ax mov ss, ax mov esp, 7c00h mov ax, 1 mov bx, $8000 mov cx, 64 @@: call ReadSector add bx, 512 inc ax loop @b jmp 0 : $8000 ret ; ---------------------------------------------------------------------- ; AX - number of sector, ES:BX pointer to data place ; ---------------------------------------------------------------------- ReadSector: push ax cx mov cx, 12h cwd div cx xchg ax, cx mov dh, cl and dh, 1 shr cx, 1 xchg ch, cl shr cl, 6 inc dx or cl, dl mov dl, 0 mov ax, 0201h int 13h ; es:bx, cx/dx pop cx ax ret ; ---------------------------------------------------------------------- ; ESTIMATED FILL ZERO ; ---------------------------------------------------------------------- times 7c00h + (512 - 2) - $ db 0x00 dw 0xAA55