§ Описание

Зачастую возникает желание создать свою ОС, но никак не знаешь, с чего начать? Так вот ответ простой — бутсектор! Если напишешь бутсектор, считай, половина ОС в твоем кармане. Ахаха! Поверил? А вот и нет. Это 0.01% от операционной системы.

§ Исходный код

Код написан с использованием fasm.
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 Байт в секторе
12        db      1                   ; 0D Секторов на кластер
13        dw      1                   ; 0E Количество зарезервированных секторов
14        db      2                   ; 10 Количество FAT
15        dw      00E0h               ; 11 Количество Root Entries (224)
16        dw      0B40h               ; 13 Всего секторов
17        db      0F0h                ; 15 Параметр media
18        dw      9                   ; 16 Секторов в FAT
19        dw      12h                 ; 18 Секторов на дорожке (18)
20        dw      2                   ; 1A Количество дорожек
21        dd      0                   ; 1C Скрытых секторов (large mode)
22        dd      0                   ; 20 Всего секторов (large mode)
23        db      0                   ; 24 Номер физического девайса
24        db      1                   ; 25 Флаги
25        db      29h                 ; 26 Расширенная сигнатура
26        dd      07E00000h           ; 27 Серийный номер, но используется для ES:BX
27        db      'DEMO    BIN'       ; 2B Лейбл, используется для файла загрузки
28        db      'FAT12    '         ; 36 Тип файловой системы
29; ----------------------------------------------------------------------
30
31start:
32        cli                         ; IF=0
33        cld                         ; DF=0
34        xor     ax, ax              ; Очистка DS: ES: SS: сегментов
35        mov     ds, ax
36        mov     es, ax
37        mov     ss, ax
38        mov     sp, 7c00h           ; Установка стека
39        mov     ax, 19              ; Сектор 19-й содержит первый сектор
40dir:    les     bx, [7c27h]         ; root-каталога и он читается в $7E00
41        call    ReadSector          ; с диска, сектор задается через LBA (AX)
42        mov     di, bx              ; ES:DI - Начало записей в ROOT
43        mov     bp, 16              ; 16 файлов в секторе из 512 байт
44item:   mov     si, 7c2bh           ; DS:SI - Проверка имени формата 8.3
45        mov     cx, 12              ; 11 + 1 - Сравниваем 11 символов (+1)
46        push    di
47        repe    cmpsb               ; Сравнение строк
48        pop     di
49        jcxz    file_found          ; Файл был найден, перейти к загрузке
50        add     di, 32              ; Иначе искать следующую строку
51        dec     bp
52        jne     item                ; Если просмотр в секторе закончился
53        inc     ax                  ; Перейти к следующему сектору
54        sub     word [7c11h], 16    ; Кол-во оставшихся записей
55        jne     dir                 ; Сектора еще не закончились в ROOT?
56        int     18h                 ; Нет запускного файла
57
58; ----------------------------------------------------------------------
59; Загрузка файла по адресу 8000h
60; ----------------------------------------------------------------------
61
62file_found:
63
64        mov     ax, [es: di + 1Ah]  ; Номер кластера
65        mov     [7c22h], word 800h  ; Адрес, где начинатся программа
66
67next:   push    ax                  ; В AX содержится номер читаемого кластера
68        add     ax, 31              ; 33-сектор находится DATA-секция
69        les     bx, [7c20h]         ; Область памяти, куда будет читать
70        call    ReadSector
71        add     [7c22h], word 20h   ; +20h сегментов (32*16=512 байт)
72        pop     ax                  ; Искать следующий кластер по текущему
73        mov     bx, 3               ; Умножить на 3 полубайта (по 4 бита)
74        mul     bx                  ; Поскольку FAT12 -- 12-битная
75        push    ax
76        shr     ax, 1 + 9           ; Найти номер сектора FAT
77        inc     ax                  ; Пропуск +1 BPB
78        mov     si, ax              ; Сохранить номер этого сектора на потом
79        les     bx, [7c27h]         ; Скачать сюда ES:BX=07e0:0000
80        call    ReadSector
81        pop     ax                  ; Восстановить номер кластера
82        mov     bp, ax              ; Теперь он в BP
83        mov     di, ax
84        shr     di, 1               ; Найти кластер в загруженном секторе FAT
85        and     di, 0x1FF           ; Срезать лишние биты
86        mov     ax, [es: di]        ; Загрузка в AX указателя на следующий кластер
87        cmp     di, 0x1FF           ; Если не хватает данных (конец сектора FAT)
88        jne     @f
89        push    ax                  ; Сохраняем AX
90        xchg    ax, si
91        inc     ax                  ; Следующий сектор FAT
92        call    ReadSector          ; Читается в 7E00:0000
93        pop     ax
94        mov     ah, [es: bx]        ; И дополняем AH (которого не хватало)
95@@:     test    bp, 1               ; Если младший бит кластера равен 0
96        jz      @f                  ; То ничего не делать
97        shr     ax, 4               ; Иначе, нечетные кластеры сдвинуть вправо на 4 бита
98@@:     and     ax, 0x0FFF          ; Ограничить от 0 до 4095
99        cmp     ax, 0x0FF0          ; Если следующий кластер < 4080
100        jb      next                ; Продолжить чтение, если так
101        jmp     0 : $8000           ; Иначе запускает программу
102
103; ----------------------------------------------------------------------
104; AX - номер сектора от 0 до n, ES:BX указывает на данные
105; ----------------------------------------------------------------------
106
107ReadSector:
108
109        push    ax bx           ; Сохранить AX, BX
110        mov     cx, 12h         ; 18 секторов на дорожку
111        cwd                     ; DX=0
112        div     cx              ; Разделить LBA на 18
113        xchg    ax, cx          ; Результат в CX
114        mov     dh, cl          ; Сохранить CL в DH
115        and     dh, 1           ; В DH будет номер головки (0 или 1)
116        shr     cx, 1           ; В CX будет номер цилиндра
117        xchg    ch, cl          ; В CL будет старший цилиндр, в CH младший
118        shr     cl, 6           ; В старших 2-х битах старшие 2 бита цилиндра
119        inc     dx              ; Номер головки 1 или 2
120        or      cl, dl          ; Объединить биты [5:0] сектора и старшего цилиндра
121        mov     dl, 0           ; Номер диска 00 - Floppy
122        mov     ax, 0201h       ; Чтение данных
123        int     13h             ; ES:BX, параметры CHS в CX/DX
124        pop     bx ax           ; Восстановить AX, BX
125        ret
126
127; ----------------------------------------------------------------------
128; Оставшееся пространство заполнить нулями
129; ----------------------------------------------------------------------
130
131        times   7c00h + (512 - 2) - $ db 0x00
132        dw      0xAA55