§ Устройство 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 максимально прост:
1 org 7C00h 2 cld ; На всякий случай 3 sti ; Чтобы реагировал на CTRL+ALT+DEL 4 xor ax, ax 5 mov ds, ax 6 mov es, ax 7 mov ss, ax 8 mov sp, 7C00h 9 jmp $В этом коде просто устанавливаются сегментные регистры в 0 и стек ставится под кодом бут-сектора.
Напишу Hello World, используя функцию BIOS INT 10h
1 mov si, ab ; Ссылка на строку 2@@: mov ah, 0Eh ; 0Eh печать символа в терминале 3 lodsb ; Загрузка символа из DS:SI 4 and al, al ; Проверка AL на 0 5 je $ ; Если 0, остановить процессор 6 int 10h ; Напечатать символ 7 jmp @b ; Перейти к следующему 8 9ab: db "Hello World",0Чтобы выгрузить данный бут-сектор на реальную флешку, можно воспользоваться такой командой
1sudo dd conv=notrunc if=boot.bin of=/dev/sdX bs=446 count=1
Где /sdX - это устройство флешки, например, sdd или sde, это надо узнать через команду df -h
, там будет выведен список подключенных устройств.Я вот проверил свой код, все работает хорошо.
§ Вариант с загрузкой 32Кб
1 2 org 7c00h 3 macro brk { xchg bx, bx } 4 5 cli 6 cld 7 xor ax, ax 8 mov ds, ax 9 mov es, ax 10 mov ss, ax 11 mov sp, 7C00h 12 13 ; Задача boot-сектора это загрузить и запустить программу 14 ; Конечно же, лучше чтобы программа была в FAT, но пока что так 15 16 mov [7C00h], dl ; Сохранить DL (Drive Letter ;) 17 mov ah, 41h ; Проверка на поддержку режима DAP 18 mov bx, 55AAh 19 int 13h 20 jc error 21 mov ah, 42h ; Загрузить сектор в память 22 mov si, DAP 23 mov dl, [7C00h] 24 int 13h 25 jc error 26 jmp 0 : 8000h ; Передача управления 27 28; Ничего не делать 29error: jmp $ 30 31; ------------------------------------------------------------------------------ 32DAP: dw 0010h ; 0 | размер DAP = 16 33 dw 0040h ; 2 | читать 64 секторов (32 кб) 34 dw 0000h ; 4 | смещение (=0) 35 dw 0800h ; 6 | сегмент (=800h) * 10h = 0000:8000 36 dq 1 ; 8 | номер сектора от 0 до N-1 (1 = второй сектор)
§ Загрузка с Floppy
1 macro brk { xchg bx, bx } 2 org 7c00h 3 4 jmp short start 5 db 00h 6 7; ---------------------------------------------------------------------- 8; BPB: Bios Parameter Block 9; ---------------------------------------------------------------------- 10 db "FLOPPY12" ; 03 Signature 11 dw 200h ; 0B Bytes in sector 12 db 1 ; 0D Sectors by cluster 13 dw 65 ; 0E Count reserver sectors (32K+Boot) 14 db 2 ; 10 Count of FAT 15 dw 00E0h ; 11 Count of Root Entries (224) 16 dw 0B40h ; 13 Total count of sectors 17 db 0F0h ; 15 Media 18 dw 9 ; 16 Sectors in FAT 19 dw 12h ; 18 Sectors on track 20 dw 2 ; 1A Count of heads 21 dd 0 ; 1C Hidden Sectors (large) 22 dd 0 ; 20 Total Sectors 23 db 0 ; 24 Number of Phys. 24 db 1 ; 25 Flags 25 db 29h ; 26 Ext Sig 26 dd 07E00000h ; 27 Serial Numbers ES:BX 27 db 'CORE BIN' ; 2B Label / Exec File 28 db 'FAT12 ' ; 36 Type of FS 29; ---------------------------------------------------------------------- 30 31start: cli 32 cld 33 xor ax, ax 34 mov ds, ax 35 mov es, ax 36 mov ss, ax 37 mov esp, 7c00h 38 mov ax, 1 39 mov bx, $8000 40 mov cx, 64 41@@: call ReadSector 42 add bx, 512 43 inc ax 44 loop @b 45 jmp 0 : $8000 46 ret 47 48; ---------------------------------------------------------------------- 49; AX - number of sector, ES:BX pointer to data place 50; ---------------------------------------------------------------------- 51 52ReadSector: 53 54 push ax cx 55 mov cx, 12h 56 cwd 57 div cx 58 xchg ax, cx 59 mov dh, cl 60 and dh, 1 61 shr cx, 1 62 xchg ch, cl 63 shr cl, 6 64 inc dx 65 or cl, dl 66 mov dl, 0 67 mov ax, 0201h 68 int 13h ; es:bx, cx/dx 69 pop cx ax 70 ret 71 72; ---------------------------------------------------------------------- 73; ESTIMATED FILL ZERO 74; ---------------------------------------------------------------------- 75 76 times 7c00h + (512 - 2) - $ db 0x00 77 dw 0xAA55