Восстановление данных - страница 44
>CL
и восемь битов регистра >CH
определяют номер цилиндра, который мы хотим прочитать. Регистровая пара >ES:BX
указывает на адрес буфера-приемника. Вот, собственно говоря, и все. После выполнения команды >INT 13h
считываемые данные окажутся в буфере, а если произойдет ошибка (например, головка "споткнется" о BAD-сектор), то BIOS установит флаг переноса (carry flag), и мы будем вынуждены либо повторить попытку, либо вывести грустное сообщение на экран.Код этой программы на языке ассемблера представлен в листинге 5.6.
Листинг 5.6. Код, считывающий загрузочный сектор или расширенную таблицу разделов
>MOV SI, 1BEh ; Перейти к первому разделу
>MOV AX, CS ; Настраиваем ES
>MOV ES, AX
>MOV BX, buf ; Смещение буфера
>...
>read_all_partitions:
> MOV AX, bud ; Читать 1 сектор с диска
> MOV DL, 80h ; Читать с первого диска
> MOV DH, [SI+1] ; Стартовый номер головки
> MOV CX, [SI+2] ; Стартовый сектор с цилиндром INT 13h
> JC error ; Ошибка чтения
> ;Обрабатываем считанный boot-сектор или расширенную таблицу разделов
> ;===================================================================
> ;
> CMP byte [SI], 80h
> JZ LOAD_BOOT ; Это загрузочный сектор
> ; Передаем на него управление
> 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
равен не >02h
, a >03h
. С режимом LBA разобраться намного сложнее, но мы, как настоящие хакеры, его обязательно осилим.
Чтение сектора осуществляется функцией >42h
(>AH = 42h
). В регистр >DL
, как и прежде, заносится номер привода, а вот регистровая пара >DS:SI
указывает на адресный пакет (disk address packet), представляющий собой продвинутую структуру формата, описанного в табл. 5.4.
Таблица 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
содержит не >42h
, a >43h
. Регистр >AL
определяет режим: если бит 0 равен 1, BIOS выполняет не запись, а ее эмуляцию. Бит 2, будучи взведенным, задействует запись с проверкой. Если регистр >AL
равен 0, выполняется обыкновенная запись по умолчанию.