Теперь разберем процедуру загрузки секторов. Процедура получает номер сектора в dx:ax (нумерация с нуля) и преобразует его к формату CSH (цилиндр, сектор, сторона), используемому прерыванием BIOS int 0x13.
; * Чтение секторов с диска *
; *************************************************
; * Входные параметры: *
; * dx:ax - (LBA) номер сектора *
; * cx - количество секторов для чтения *
; * es:bx - адрес буфера *
; *************************************************
; * Выходные параметры: *
; * cx - Количество не прочтенных секторов *
; * es:bx - Указывает на конец буфера *
; * cf = 1 - Произошла ошибка при чтении *
; *************************************************
ReadSectors;proc
next_sector:
; Читаем очередной сектор
movbyte [bp+fails], 3; Количество попыток прочесть сектор
try:
; Очередная попытка
pusha
; Преобразуем линейный адрес в CSH
; dx:ax = a1:a0
xchgax, cx; cx = a0
movax, [byte bp+BPB_SecPerTrk]
xchgax, si; si = Scnt
xchgax, dx; ax = a1
xordx, dx
; dx:ax = 0:a1
divsi; ax = q1, dx = c1
xchgax, cx; cx = q1, ax = a0
; dx:ax = c1:a0
divsi; ax = q2, dx = c2 = c
incdx; dx = Sector?
xchgcx, dx; cx = c, dx = q1
; dx:ax = q1:q2
divword [byte bp+BPB_NumHeads]; ax = C (track), dx = H
movdh, dl; dh = H
movch, al
rorah, 2
orcl, ah
movax, 0201h; ah=2 - номер функции, al = 1 сектор
movdl, [byte bp+BS_DrvNum]
int13h
popa
jcFailure; Ошибка при чтении
; Номер следующего сектора
incax
jnznext
incdx
next:
addbx, [byte bp+BPB_BytsPerSec]
deccx; Все сектора прочтены?
jnznext_sector; Нет, читаем дальше
return:
ret
Failure:
decbyte [bp+fails]; Последняя попытка?
jnztry; Нет, еще раз
; Последняя, выходим с ошибкой
stc
ret
;ReadSectorsendp
>
Осталось всего ничего:
; Сообщения об ошибках
NotFound:; Файл не найден
movsi, BOOT_ADDR + mLoaderNotFound
callprint
jmpshort die
DiskError:; Ошибка чтения
movsi, BOOT_ADDR + mDiskError
callprint
;jmpshort die
die:; Просто ошибка
movsi, BOOT_ADDR + mReboot
callprint
_die:; Бесконечный цикл, пользователь сам нажмет Reset
jmpshort _die
; Процедура вывода ASCIIZ строки на экран
; ds:si - адрес строки
print:; proc
pusha
print_char:
lodsb; Читаем очередной символ
testal, al; 0 - конец?
jzshort pr_exit; Да конец
; Нет, выводим этот символ
movah, 0eh
movbl, 7
int10h
jmpshort print_char; Следующий
pr_exit:
popa
ret
;printendp
; Перевод строки
%defineendl 10,13,0
; Строковые сообщения
mLoadingdb 'Loading...',endl
mDiskErrordb 'Disk I/O error',endl
mLoaderNotFounddb 'Loader not found',endl
mRebootdb 'Reboot system',endl
; Выравнивание размера образа на 512 байт
times 499-($-$$) db 0
LoaderNamedb 'BOOTOR '; Имя файла загрузчика
BootMagicdw 0xAA55; Сигнатура загрузочного сектора