00:16
Бутсектор для флоппи-диска — Лисья нора
§ Описание
Зачастую возникает желание создать свою ОС, но никак не знаешь, с чего начать? Так вот ответ простой — бутсектор! Если напишешь бутсектор, считай, половина ОС в твоем кармане. Ахаха! Поверил? А вот и нет. Это 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