§ Описание
Зачастую возникает желание создать свою ОС, но никак не знаешь, с чего начать? Так вот ответ простой — бутсектор! Если напишешь бутсектор, считай, половина ОС в твоем кармане. Ахаха! Поверил? А вот и нет. Это 0.01% от операционной системы.§ Исходный код
Код написан с использованием fasm.macro brk { xchg bx, bx } org 7c00h jmp short start db 00h ; ---------------------------------------------------------------------- ; BPB: Bios Parameter Block ; ---------------------------------------------------------------------- db "FLOPPY12" ; 03 Signature dw 200h ; 0B Байт в секторе db 1 ; 0D Секторов на кластер dw 1 ; 0E Количество зарезервированных секторов db 2 ; 10 Количество FAT dw 00E0h ; 11 Количество Root Entries (224) dw 0B40h ; 13 Всего секторов db 0F0h ; 15 Параметр media dw 9 ; 16 Секторов в FAT dw 12h ; 18 Секторов на дорожке (18) dw 2 ; 1A Количество дорожек dd 0 ; 1C Скрытых секторов (large mode) dd 0 ; 20 Всего секторов (large mode) db 0 ; 24 Номер физического девайса db 1 ; 25 Флаги db 29h ; 26 Расширенная сигнатура dd 07E00000h ; 27 Серийный номер, но используется для ES:BX db 'DEMO BIN' ; 2B Лейбл, используется для файла загрузки db 'FAT12 ' ; 36 Тип файловой системы ; ---------------------------------------------------------------------- start: cli ; IF=0 cld ; DF=0 xor ax, ax ; Очистка DS: ES: SS: сегментов mov ds, ax mov es, ax mov ss, ax mov sp, 7c00h ; Установка стека mov ax, 19 ; Сектор 19-й содержит первый сектор dir: les bx, [7c27h] ; root-каталога и он читается в $7E00 call ReadSector ; с диска, сектор задается через LBA (AX) mov di, bx ; ES:DI - Начало записей в ROOT mov bp, 16 ; 16 файлов в секторе из 512 байт item: mov si, 7c2bh ; DS:SI - Проверка имени формата 8.3 mov cx, 12 ; 11 + 1 - Сравниваем 11 символов (+1) push di repe cmpsb ; Сравнение строк pop di jcxz file_found ; Файл был найден, перейти к загрузке add di, 32 ; Иначе искать следующую строку dec bp jne item ; Если просмотр в секторе закончился inc ax ; Перейти к следующему сектору sub word [7c11h], 16 ; Кол-во оставшихся записей jne dir ; Сектора еще не закончились в ROOT? int 18h ; Нет запускного файла ; ---------------------------------------------------------------------- ; Загрузка файла по адресу 8000h ; ---------------------------------------------------------------------- file_found: mov ax, [es: di + 1Ah] ; Номер кластера mov [7c22h], word 800h ; Адрес, где начинатся программа next: push ax ; В AX содержится номер читаемого кластера add ax, 31 ; 33-сектор находится DATA-секция les bx, [7c20h] ; Область памяти, куда будет читать call ReadSector add [7c22h], word 20h ; +20h сегментов (32*16=512 байт) pop ax ; Искать следующий кластер по текущему mov bx, 3 ; Умножить на 3 полубайта (по 4 бита) mul bx ; Поскольку FAT12 -- 12-битная push ax shr ax, 1 + 9 ; Найти номер сектора FAT inc ax ; Пропуск +1 BPB mov si, ax ; Сохранить номер этого сектора на потом les bx, [7c27h] ; Скачать сюда ES:BX=07e0:0000 call ReadSector pop ax ; Восстановить номер кластера mov bp, ax ; Теперь он в BP mov di, ax shr di, 1 ; Найти кластер в загруженном секторе FAT and di, 0x1FF ; Срезать лишние биты mov ax, [es: di] ; Загрузка в AX указателя на следующий кластер cmp di, 0x1FF ; Если не хватает данных (конец сектора FAT) jne @f push ax ; Сохраняем AX xchg ax, si inc ax ; Следующий сектор FAT call ReadSector ; Читается в 7E00:0000 pop ax mov ah, [es: bx] ; И дополняем AH (которого не хватало) @@: test bp, 1 ; Если младший бит кластера равен 0 jz @f ; То ничего не делать shr ax, 4 ; Иначе, нечетные кластеры сдвинуть вправо на 4 бита @@: and ax, 0x0FFF ; Ограничить от 0 до 4095 cmp ax, 0x0FF0 ; Если следующий кластер < 4080 jb next ; Продолжить чтение, если так jmp 0 : $8000 ; Иначе запускает программу ; ---------------------------------------------------------------------- ; AX - номер сектора от 0 до n, ES:BX указывает на данные ; ---------------------------------------------------------------------- ReadSector: push ax bx ; Сохранить AX, BX mov cx, 12h ; 18 секторов на дорожку cwd ; DX=0 div cx ; Разделить LBA на 18 xchg ax, cx ; Результат в CX mov dh, cl ; Сохранить CL в DH and dh, 1 ; В DH будет номер головки (0 или 1) shr cx, 1 ; В CX будет номер цилиндра xchg ch, cl ; В CL будет старший цилиндр, в CH младший shr cl, 6 ; В старших 2-х битах старшие 2 бита цилиндра inc dx ; Номер головки 1 или 2 or cl, dl ; Объединить биты [5:0] сектора и старшего цилиндра mov dl, 0 ; Номер диска 00 - Floppy mov ax, 0201h ; Чтение данных int 13h ; ES:BX, параметры CHS в CX/DX pop bx ax ; Восстановить AX, BX ret ; ---------------------------------------------------------------------- ; Оставшееся пространство заполнить нулями ; ---------------------------------------------------------------------- times 7c00h + (512 - 2) - $ db 0x00 dw 0xAA55