Использование функций BIOS
Только что мы привели функции BIOS для работы с диском на физическом уровне. Когда и как ими пользоваться?
Доступ к диску на физическом уровне может потребоваться для чтения отдельных секторов диска, расположенных в фиксированных (или известных) местах диска - таблицы разделов диска, каталогов и т.п. С помощью функций BIOS можно выполнить низкоуровневое форматирование диска, как стандартное, так и использующее нестандартный формат дорожки.
В любом случае при записи информации в сектора следует внимательно анализировать работу программы - ошибки могут привести к разрушению логической структуры диска. В результате этого могут оказаться потеряны каталоги и файлы. Все "опасные" эксперименты лучше проводить на дискетах, и только когда вы уверены в безошибочной работе программы, можно "допустить" ее к жесткому диску.
Если вы используете дисковод с высокой плотностью записи (например, 1.2М) для работы с дискетами, использующими двойную плотность записи (360 К), перед началом работы вам надо правильно установить скорость передачи данных через контроллер НГМД. Лучше всего это сделать функцией 17h прерывания INT3h, указав тип диска.
Не следует забывать о задержке, необходимой для разгона двигателя НГМД до рабочей скорости. Некоторые функции BIOS могут вернуть признак ошибки, если двигатель не набрал нужной скорости. Если вы получили признак ошибки, вначале следует три раза повторить вызов функции, сбрасывая каждый раз перед этим контроллер НГМД функцией 0 прерывания INT 13h. Если и после этого ошибка не исчезла, следует провести ее углубленный анализ.
Приведем примеры использования функций прерывания INT 13h для работы с НГМД.
Первый пример - программа, составленная на языке ассемблера. Она читает самый первый сектор диска, расположенный на нулевой дорожке, нулевой стороне (нулевая головка). Этот сектор имеет номер 1.
.MODEL tiny
.STACK 100h
.DATA
; Буфер, в который будет прочитан сектор диска
buf db 512 dup(?)
.CODE .STARTUP
mov ch,00h ; Номер дорожки mov cl,01h ; Номер сектора
mov dh,00h ; Номер головки (стороны диска) mov dl,00h ; Номер дисковода - дисковод А:
; Готовим адрес буфера в ES:BX
mov ax,cs mov es,ax
mov bx,OFFSET buf
; Готовим код функции
mov ah,02h ; Код функции - чтение сектора mov al,01h ; Количество читаемых секторов - 1
; Вызываем прерывание
int 13h
.EXIT 0
END
Следующая программа - пример использования аппаратной поддержки проверки замены дискеты. Эта поддержка реализована в машинах класса AT, PS/2.
Сначала программа устанавливает тип дискеты. Это нужно для правильного выбора скорости передачи данных контроллером НГМД. При установке типа дискеты сбрасывается флаг замены дискеты.
Далее после чтения состояния НГМД программа делает паузу, во время которой вы можете заменить дискету или просто открыть и закрыть дверцу дисковода. Выполнив (или не выполнив) действия по замене дискеты, нажмите на любую клавишу. Программа выведет на экран новое состояние флага замены дискеты.
Попробуйте запустить эту программу без дискеты, обратите внимание на состояние порта 0x3F7.
Главное, что вы можете взять из приведенной ниже программы - это техника работы с флагом замены дискеты. Используя аппаратную поддержку проверки замены дискеты, ваша программа сможет более полно контролировать действия оператора по установке и замене дискет.
Текст программы:
#include <stdio.h> #include <conio.h> #include <dos.h> #include <stdlib.h>
union REGS inregs, outregs;
void main(void); void main(void) {
// Устанавливаем тип диска и сбрасываем // флаг замены дискеты
inregs.h.ah = 0x17; inregs.h.al = 3; inregs.h.dl = 0; int86(0x13, &inregs, &outregs);
// Определяем тип диска и наличие аппаратной // поддержки проверки замены дискеты
inregs.h.ah = 0x15; inregs.h.dl = 0; int86(0x13, &inregs, &outregs); printf("\nТип диска А: %d",outregs.h.ah);
// Определяем состояние флага замены дискеты
inregs.h.ah = 0x16; inregs.h.dl = 0; int86(0x13, &inregs, &outregs); printf("\nСостояние флага замены дискеты: %d",outregs.h.ah);
// Выводим состояние порта 0x3F7. // Бит 7 этого порта отображает состояние // флага замены дискеты
printf("\nПорт 0x3F7: %02.2x",inp(0x3f7));
// Сбрасываем контроллер НГМД
inregs.h.ah = 0; inregs.h.dl = 0; int86(0x13, &inregs, &outregs);
// Делаем паузу, во время которой можно // заменить дискету. Запуская программу несколько // раз, попробуйте во время ожидания нажатия на клавишу // открыть и затем закрыть дверцу дисковода - это // приведет к установке флага замена дискеты
printf("\nЗамените дискету и нажмите на любую клавишу"); getch();
// Определяем заново состояние флага замены дискеты
inregs.h.ah = 0x16; inregs.h.dl = 0; int86(0x13, &inregs, &outregs); printf("\nСостояние флага замены дискеты: %d",outregs.h.ah);
// Выводим состояние порта 0x3F7.
printf("\nПорт 0x3F7: %02.2x",inp(0x3f7));
}
Еще один пример - нестандартное форматирование дорожки флоппи-диска - мы приведем в следующем разделе.