§ Устройство 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