Восстановление данных. Практическое руководство
CMP byte [SI+4], 05h
JZ LOAD_CHS_EXT ; Это расширенная таблица разделов
; в формате CHS
CMP byte [SI+4], 0Fh
JZ LOAD_LBA_EXT ; Это расширенная таблица разделов
; в формате LBA
ADD SI, 10h ; Переходим на следующий раздел
CMP SI, 1EEh
JNA read_all_partitions ; Читаем все разделы один за другим
...
buf rb 512 ; Буфер на 512 байт
Запись сектора в режиме CHS происходит практически точно так же, только регистр
равен неAH
, a02h
. С режимом LBA разобраться намного сложнее, но мы, как настоящие хакеры, его обязательно осилим.03h
Чтение сектора осуществляется функцией
(42h
). В регистрAH = 42h
, как и прежде, заносится номер привода, а вот регистровая параDL
указывает на адресный пакет (disk address packet), представляющий собой продвинутую структуру формата, описанного в табл. 5.4.DS:SI
Таблица 5.4. Формат адресного пакета, используемый для чтения и записи секторов в режиме LBA
Смещение Тип Описание 00h
BYTE
Размер пакета — или10h
18h
01h
BYTE
Поле зарезервировано и должно быть равно нулю 02h
WORD
Сколько секторов читать 04h
DWORD
32-разрядный адрес буфера-приемника в формате seg:offs
08h
QWORD
Стартовый номер сектора для чтения 10h
QWORD
64-разрядный плоский адрес буфера-приемника. Используется только в случае, если 32-разрядный адрес равен FFFF:FFFF
Код, читающий сектор в режиме LBA, в общем случае выглядит так, как показано в листинге 5.7.
Листинг 5.7. Код, осуществляющий чтение сектора с диска в режиме LBA
MOV DI, 1BEh ; Перейти к первому разделу
MOV AX, CS ; Настраиваем...
MOV buf_seg ; ...сегмент
MOV EAX, [DI+08h] ; Смещение partition относительно
; начала раздела
ADD EAX, EDI ; EDI должен содержать номер сектора
; текущего MBR
MOV [X_SEC] ;
...
read_all_partitions:
MOV АН, 42h ; Читать сектор в режиме LBA
MOV DL, 80h ; Читать с первого диска
MOV SI, dap ; Смещение адресного пакета INT 13h
JC error ; Ошибка чтения
...
dap:
packet_size db 10h ; размер пакета 10h байт
reserved db 00h ; "Заначка" для будущих расширений
N_SEC dw 01h ; Читаем один сектор
buf_seg dw 00h ; Сюда будет занесен сегмент буфера-приемника
buf_off dw buf ; Смещение буфера-приемника
X_SEC dd 0 ; Сюда будет занесен номер сектора для чтения
dd 0 ; Реально не используемый хвост
; 64-битного адреса
buf rb 512 ; Буфер на 512 байт
Запись осуществляется аналогично чтению, только регистр
содержит неAH
, a42h
. Регистр43h
определяет режим: если бит 0 равен 1, BIOS выполняет не запись, а ее эмуляцию. Бит 2, будучи взведенным, задействует запись с проверкой. Если регистрAL
равен 0, выполняется обыкновенная запись по умолчанию.AL
Теперь, освоившись с дисковыми прерываниями, перейдем к обсуждению остальных аспектов программирования.
Создаем код загрузчикаЛучше всего загрузчики программируются на FASM. С точки зрения ассемблера загрузчик представляет собой обыкновенный двоичный файл, предельно допустимый объем которого составляет
(443) байт. Немного? Но не будем спешить с выводами. Всякий раздел всегда начинается с начала цилиндра, а это значит, что между концом MBR и началом раздела имеется, по меньшей мере, n свободных секторов, где1BBh
. Практически все современные винчестеры имеют по 64 сектора на дорожку, что дает нам:n == sectors per track
байт или приблизительно 32 Кбайт. Да в этот объем даже графический интерфейс с мышью уместить можно! Однако делать этого мы не будем. Настоящие хакеры работают в текстовом режиме с командной строкой.443 + 63*512 == 32 699
Как уже говорилось, BIOS загружает MBR по адресу
, поэтому в начале ассемблерного кода должна стоять директива7C00h
, а еще —ORG 7C00h
, ведь загрузчик выполняется в 16-разрядном реальном режиме. Позже, при желании, он может перейти в защищенный режим, но это будет уже потом. Не будем лезть в такие дебри.USE16