Пишем свой загрузочный сектор - Процедура загрузки секторов

ОГЛАВЛЕНИЕ

 

Процедура загрузки секторов

Теперь разберем процедуру загрузки секторов. Процедура получает номер сектора в dx:ax (нумерация с нуля) и преобразует его к формату CSH (цилиндр, сектор, сторона), используемому прерыванием BIOS int 0x13.

<>; *************************************************
 ; *          Чтение секторов с диска              *
 ; *************************************************
 ; * Входные параметры:                            *
 ; * dx:ax       - (LBA) номер сектора             *
 ; * cx          - количество секторов для чтения  *
 ; * es:bx       - адрес буфера                    *
 ; *************************************************
 ; * Выходные параметры:                           *
 ; * cx       - Количество не прочтенных секторов  *
 ; * es:bx    - Указывает на конец буфера          *
 ; * cf = 1   - Произошла ошибка при чтении        *
 ; *************************************************
 ReadSectors	;proc
 next_sector:
 	; Читаем очередной сектор
 	mov	byte [bp+fails], 3	; Количество попыток прочесть сектор
 try:
 	; Очередная попытка
 	pusha
 	; Преобразуем линейный адрес в CSH
 	; dx:ax = a1:a0
 	xchg	ax, cx		; cx = a0
 	mov	ax, [byte bp+BPB_SecPerTrk]
 	xchg	ax, si		; si = Scnt
 	xchg	ax, dx		; ax = a1
 	xor	dx, dx
 	; dx:ax = 0:a1
 	div	si		; ax = q1, dx = c1
 	xchg	ax, cx		; cx = q1, ax = a0
 	; dx:ax = c1:a0
 	div	si		; ax = q2, dx = c2 = c
 	inc	dx		; dx = Sector?
 	xchg	cx, dx		; cx = c, dx = q1
 	; dx:ax = q1:q2
 	div	word [byte bp+BPB_NumHeads]	; ax = C (track), dx = H
 	mov	dh, dl		; dh = H
 	mov	ch, al
 	ror	ah, 2
 	or	cl, ah
 	mov	ax, 0201h		; ah=2 - номер функции, al = 1 сектор
 	mov	dl, [byte bp+BS_DrvNum]
 	int	13h
 	popa
 	jc	Failure	; Ошибка при чтении
 	; Номер следующего сектора
 	inc	ax
 	jnz	next
 	inc	dx
 next:
 	add	bx, [byte bp+BPB_BytsPerSec]
 	dec	cx	; Все сектора прочтены?
 	jnz	next_sector	; Нет, читаем дальше
 return:
 	ret
 Failure:
 	dec	byte [bp+fails]	; Последняя попытка?
 	jnz	try	; Нет, еще раз
 	; Последняя, выходим с ошибкой
 	stc
 	ret
 ;ReadSectors	endp
>

Осталось всего ничего:

; Сообщения об ошибках
NotFound: ; Файл не найден
mov si, BOOT_ADDR + mLoaderNotFound
call print
jmp short die
DiskError: ; Ошибка чтения
mov si, BOOT_ADDR + mDiskError
call print
;jmp short die
die: ; Просто ошибка
mov si, BOOT_ADDR + mReboot
call print
_die: ; Бесконечный цикл, пользователь сам нажмет Reset
jmp short _die
; Процедура вывода ASCIIZ строки на экран
; ds:si - адрес строки
print: ; proc
pusha
print_char:
lodsb ; Читаем очередной символ
test al, al ; 0 - конец?
jz short pr_exit ; Да конец
; Нет, выводим этот символ
mov ah, 0eh
mov bl, 7
int 10h
jmp short print_char ; Следующий
pr_exit:
popa
ret
;print endp
; Перевод строки
%define endl 10,13,0
; Строковые сообщения
mLoading db 'Loading...',endl
mDiskError db 'Disk I/O error',endl
mLoaderNotFound db 'Loader not found',endl
mReboot db 'Reboot system',endl
; Выравнивание размера образа на 512 байт
times 499-($-$$) db 0
LoaderName db 'BOOTOR     ' ; Имя файла загрузчика
BootMagic dw 0xAA55 ; Сигнатура загрузочного сектора