Функции dos int 25h26h прямая дисковая операция чтениязаписи

Содержание

Функции dos int 25h/26h: прямая дисковая операция чтения/записи

Итак, в прошлом шаге мы с Вами немного посмотрели, как можно работать с жестким диском, теперь мы с Вам воспользуемся нашими знаниями для чтения информации из загрузочного сектора. Пишем:

А теперь запускаем:

А теперь проверим все это в Norton Disk Edit:

Все нормально вроде как, Norton Disk Edit показывает все точно также. У меня строит Win98&Windows 2000 с чем и связана надпись PMSWIN4.1, конечно, если это не вирус, у Вас может быть по другому.

Функции dos int 25h/26h: прямая дисковая операция чтения/записи

На этом шаге мы рассмотрим посекторные чтение и запись .

Для непосредственного доступа к диску можно использовать операции абсолютного чтения и записи с помощью функций DOS INT 25H и 26Н . В этом случае теряются преимущества использования каталога диска и блокирования и разблокирования записей, обеспечиваемые функцией DOS INT 21Н .

Абсолютные операции предполагают, что все записи имеют размер сектора, поэтому прямой доступ осуществляется к полному сектору или блоку секторов. Адресация диска выполняется по «логическому номеру записи» (абсолютный сектор). Для определения логического номера записи на двусторонних дискетах с восемнадцатью секторами счет секторов ведется с дорожки 0 сектора 1 следующим образом:

Таким образом, используется следующая формула:

Например, логический номер записи на дорожке 2 и секторе 9 определяется как

Фрагмент программы для абсолютных операций ввода-вывода:

Операции абсолютного чтения или записи разрушают содержимое всех регистров, кроме сегментных, и устанавливают флаг CF для индикации успешной (0) или безуспешной (1) операции. В случае безуспешной операции содержимое регистра AL описывает характер ошибки:

  • 10000000 (80H) — устройство не отвечает;
  • 01000000 (40H) — ошибка установки головок;
  • 00100000 (20H) — ошибка контроллера;
  • 00010000 (10H) — ошибка дискеты;
  • 00001000 (08H) — переполнение DMA при чтении;
  • 00000100 (04H) — сектор не найден;
  • 00000011 (03H) — попытка записи на защищенной дискете;
  • 00000010 (02H) — не найден адресный маркер.

Команда INT записывает содержимое флагового регистра в стек. После завершения команды INT следует восстановить флаги, но проверив перед этим флаг CF .

На следующем шаге мы проиллюстрируем использование этих функций .

Ассемблер

Прерывание 21h: общие функции DOS

Все функции DOS вызываются с помощью прерывания 21h (в десятичной нотации 33). Первая версия DOS содержала 42 функции. Во второй к ним добавлено еще 33 функции, которые сохраняются во всех последующих версиях. Выбор конкретной функции осуществляется путем записи соответствующего номера в регистр AH.

Функция 02: вывод одного символа на экран

Для вывода одного символа на экран ПК используется

функция 02 прерывания 21h:

Выводимый символ высвечивается в позиции курсора (что бы там ни было записано), после чего курсор сдвигается на одну позицию вправо. Если курсор находился в конце строки экрана, то он перемещается на начало следующей строки, а если курсор был в конце последней строки экрана, то содержимое экрана сдвигается на одну строку вверх, а внизу появляется пустая строка, в начало которой и устанавливается курсор.

Особым образом осуществляется вывод символов с кодами 7, 8, 9, 10 (0Ah) и 13 (0Dh). Символ с кодом 7 (bell, звонок) на экране не высвечивается (и курсор не сдвигается), а вызывает звуковой сигнал. Символ с кодом 8 (backspase, шаг назад) возвращает курсор на одну позицию влево, если только он не был в самой левой позиции строки. Символ с кодом 9 (tab, табуляция) смещает курсор вправо на ближайшую позицию, кратную 8. Символ с кодом 10 (line feed, перевод строки) перемещает курсор в следующую строку экрана, оставляя его в той же колонке. Символ с кодом 13 (carrige returne, возврат каретки) устанавливает курсор на начало текущей строки; вывод подряд символов с кодами 13 и 10 означает перевод курсора на начало следующей строки.

Функция 9: вывести строку на экран дисплея

Для вывода на экран строки (последовательности символов) можно, конечно, использовать функцию 02, однако сделать это можно и за один прием с помощью функции 09 прерывания 21h:

DS:DX := начальный адрес строки

Перед обращением к этой функции в регистр DS должен быть помещен номер того сегмента памяти, в котором находится выводимая строка, а в регистр DX — смещение строки внутри этого сегмента. При этом в конце строки должен находиться символ $ (код 24h), который служит признаком конца строки и сам не выводится.

Хотя эта функция может оказаться намного удобнее функций побайтового вывода на экран (функция 2 и 6), она имеет тот недостаток, что вполне обычный символ $ используется как ограничитель строки. Это еще один побочный продукт совместимости с CP/M.

Расширенные функции операционной системы DOS в качестве ограничителя строки используют CHR$(0). Это соответствует соглашениям, принятым в операционной системе UNIX и языке программирования Си.

Среди функций DOS нет такой, которая выводит числа. Такую операцию, если надо, приходится реализовывать на основе рассмотренных функций.

Функция 4Ch: завершение программы

Завершив все свои действия, программа обязана вернуть управление операционной системе, чтобы пользователь мог продолжить работу на ПК. Такой возврат реализуется функцией 4Ch прерывания 21h, которую помещают в конце программы:

Каждая программа, вообще говоря, обязана сообщить, успешно или нет она завершила свою работу. Дело в том, что любая программа вызывается из какой-то другой программы (например, из операционной системы), и иногда вызвавшей программе, чтобы правильно продолжить работу, надо знать, выполнила ли вызванная программа все, что надо, или она проработала с ошибкой. Такая информация передается в виде кода завершения программы (некоторого целого числа), который должен быть нулевым, если программа проработала правильно, и ненулевым (каким именно — оговаривается в каждом случае особо) в противном случае. (Узнать код завершения вызванной программы можно с помощью функции 4Dh прерывания 21h.) Потребуется этот код или нет, программа все равно должна выдать его.

Операции ввода-вывода на диск

Таблица распределения файлов

Оглавление диска (каталог)

Дисковая память

Диск является распространенным средством для более или менее долговременного хранения данных. Процессы обработки данных на твердом диске (винчестре) аналогичны процессам для гибких дисков (дискет), за исключением того, что возможно потребуется обеспечить пути для доступа к многочисленным подоглавлениям винчестера. Для обработки файлов полезно ознакомиться с организацией дисковой памяти.

Каждая cторона 3 ½ дюймовой дискеты содержит 80-160 концентрических дорожек, пронумерованных от 00 до 79-159. На каждой дорожке форматируется девять секторов по 512 байтов каждый. На жестком диске вместо термина дорожки используются цилиндры.

Данные записываются на диск в виде файлов, аналогично тому, как вы записываете ассемблерные программы. На типы данных, которые можно хранить в файле, не существует каких-либо ограничений.

Для программирования дисковых файлов следует, в общих чертах ознакомится только с концепцией и терминологией.

Для того, чтобы организовать хранение информации на диске, операционная система DOS резервируют определенные сектора для своих нужд. Организация данных на дискете или на твердом диске существенно зависит от их емкости. Форматированная двухстороняя дискета содержит следующую системную информацию:

А) Запись начальной загрузки (один кластер);

Б) Таблицу распределения файлов (FAT);

Размеры FATа, каталога зависят от емкости диска. Записи заносятся сначала на 0-ю сторону n-й доpожки, затем на 1-ю сторону n-й дорожки, затем на 0-ю сторону n+1-й дорожки и т.д. Такая особенность заполнения дисковой памяти на противоположных дорожках снижает число перемещений головки дисковода. Данный метод используется как для гибких, так и для твердых дисков.

При использовании утилиты FORMAT/S для форматизации дискеты, модули DOS IBMBIO.COM и IBMDOS.COM записывается в первые сектора области данных.

Все файлы, даже меньшие 512 байт (или кратные 512), начинаются на границе сектора. Для каждого файла DOS создает элемент оглавления. Каждый такой элемент описывает элементы, определяющие имя, тип, атрибуты, дату, начальный сектор и pазмер файла.

Элементы оглавления имеют следующий формат:

0-7 Имя файла, определяемое из программы, создавшей

данный файл. Первый байт может указывать на статус

файла: шест.00 обозначает, что данный файл не

используется, шест.E5 — файл удален, шест. 2E —

11 Атрибут файла, определяющий его тип:

шест.00 — обычный файл;

шест.01 — файл можно только читать;

шест.02 — «спрятанный» файл;

шест.04 — системный файл DOS;

шест.08 — метка тома;

шест.20 — архивный файл (для твердого диска).

12-21 Зарезервировано для DOS.

22-23 Время дня, когда файл был создан или последний раз

изменялся, в следующим двоичном формате:

24-25 Дата создания или последнего изменения файла, сжатая

в два слова в следующем двоичном формате:

где год начинается с 1980 и может принимать значения

от 0 до 119, месяц — от 1 до 12, а день — от 1 до 31.

26-27 Начальный кластер файла. Относительный номер

последних двух секторов каталога. Первый файл данных

(без COM-модулей DOS) начинается на относительном

кластере 002. Текущая сторона, дорожка и кластер

зависят от емкости диска.

28-31 Размер файла в байтах. При создании файла DOS

вычисляет и записывает размер файла в это поле.

Все поля в каталоге диска, превышающие один байт, записываются в обратной последовательности байтов.

Назначение таблицы распределения файлов (FAT — File Allocation Table) — распределение дискового пространства для файлов. Если вы создаете новый файл или изменяете существующий, то DOS меняет элементы таблицы файлов в соответствии с расположением файла на диске. FAT содержит элементы для каждого кластера, длина элементов FAT зависит от устройства дисковой памяти. Кластер представляет собой один или несколько секторов.

Элементы FAT определяют кластеры. Каждый такой элемент имеет длину 12-16 битов. Два первых элемента FAT, известные как относительные сектора 000 и 001, соответственно, указывают на два последних сектора оглавления, определяя его размер и формат. Первый файл данных начинается на относительном секторе 002. Каждый элемент FAT состоит из трех шестнадцатиричных цифр (для 12-битового FATа), которые указывают на характер использования конкретного сектора:

000 свободный кластер,

nnn относительный номер следующего кластера для файла,

FF7 неиспользуемый кластер (сбойная дорожка),

FFF последний кластер файла.

Предположим, например, что дискета содержит только один файл с именем TEST.ASM, занимающий относительные сектора 002, 003 и 004. Элемент оглавления для этого файла содержит имя файла TEST, тип — ASM, шест.00 для обычного файла, дату создания, 002 — номер первого относительного сектора файла и размер файла в битах. Таблица FAT в этом случае может выглядеть следующим образом (кроме того, что в каждой паре байты в обратной последовательности):

Элемент FAT: ¦FDF¦FFF¦003¦004¦FFF¦000¦000¦. ¦000¦

Относительн.сектор: 0 1 2 3 4 5 6 . конец

Первые два элемента FAT указывают расположение каталога на относительных секторах 000 и 001. Для ввода рассматриваемого файла в память, система выполняет следующие действия:

1. DOS получает доступ к дискете и ищет в каталоге имя

2. Затем DOS определяет по каталогу положение первого относительного сектора файла (002) и загружает содержимое этого сектора в буферную область в основной памяти.

3. Номер второго сектора DOS получает из элемента FAT, соответствующего относительному сектору 002. Этот элемент содержит 003. Это обозначает, что файл продолжается в относительном секторе 003. DOS загружает содержимое этого сектора в буфер в основной памяти.

4. Номер третьего сектора DOS получает из элемента FAT, соответствующего относительному сектору 003. Этот элемент содержит 004, значит файл продолжается в относительном секторе 004. DOS загружает содержимое этого сектора в буфер в основной памяти.

5. Элемент FAT для относительного сектора 004 содержит FFF, что свидетельствует о том, что больше нет данных для этого файла.

Элемент каталога содержит номер начального кластера для каждого файла, а FAT — шест.трехзначные элементы, указывающие на расположение каждого дополнительного кластера, если он имеется. Для того, чтобы указать, например, что файл содержит все записи только в первом кластере, таблица FAT должна содержать FFF в элементе, представляющем первый относительный кластер.

Все файлы начинаются на границе кластеpа. Кроме того, совсем не обязательно файл должен храниться в соседних кластерах, он может быть разбросан на диске по разным секторам.

Управление вводом и выводом осуществляется специальными прерываниями. Запись файла на диск требует, чтобы прежде он был «создан» и DOS смогла сгенерировать соответствующий элемент в оглавлении. Когда все записи файла будут записаны, программа должна «закрыть» файл, так, чтобы DOS завершила обработку оглавления. Чтение файла требует, чтобы он был сначала «открыт» для того, чтобы убедиться в его существовании. Так как записи имеют фиксированную длину и в силу соответствующей организации оглавления, обработка записей дискового файла может осуществляться как последовательно, так и произвольно.

Метод доступа к дисковой памяти, поддерживающий использование оглавления, «блокирование» и «разблокирование» записей, обеспечивается прерыванием DOS 21H. Более низкий уровень, обеспечивающий абсолютную адресацию дисковых секторов, также через DOS, выполняется посредством прерываний 25H и 26H. Самый низкий уровень обеспечивается прерыванием BIOS 13H, которое позволяет выполнить произвольную адресацию в дисковой памяти по номеру дорожки и сектора. Методы DOS осуществляют некоторую предварительную обработку до передачи управления в BIOS.

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Увлечёшься девушкой-вырастут хвосты, займёшься учебой-вырастут рога 9792 — | 7667 — или читать все.

Группа дисковых функций MS-DOS

В эту группу входят прерывания, предназначенные для выполнения основных функций операционной системы, в том числе для выполнения операций с логическими дисками, файлами и каталогами [3, 10]. Дисковые функции DOS обладают достаточной полнотой и универсальностью для решения любых задач в реальном режиме DOS. Они могут применяться и в режиме линейной адресации памяти, но информацию в расширенную память приходится пересылать через промежуточный буфер в первом мегабайте адресного пространства процессора. Впрочем, дополнительные пересылки не особенно замедляют работу: поиск данных на диске и передача информации между диском и процессором занимает гораздо больше времени, чем копирование такого же объема данных с одного участка оперативной памяти в другой.’

Ниже описаны функции DOS, выполняющие основные операции над логическими дисками, каталогами и файлами. При описании используются следующие термины:

• строка ASCIIZ — текстовая строка в ASCII-коде, которая завершается нулевым значением;

• дескриптор файла — уникальный номер, который операционная система присваивает создаваемому или открываемому файлу в качестве идентификатора (чтобы потом обращаться к файлу по этому номеру вплоть до его закрытия).

Классические функции для работы с дисками

К этой группе относятся функции, появившиеся в ранних версиях операционной системы MS-DOS и сохранившиеся с тех пор практически без изменений. Такие функции отличаются крайне примитивной обработкой ошибок:

• в случае успешного завершения операции флаг CF сбрасывается в 0;

• в случае ошибки флаг CF устанавливается в 1.

Для обращения к дисковым функциям DOS используется прерывание Int 21h.

Прерывание Int 21 h, функция OEh: сменить текущий логический диск

Функция позволяет выбрать логический диск. Перед вызовом прерывания требуется записать в регистры следующие значения:

• в АН — значение OEh;

• в AL — код логического диска (0 — А:, 1 — В: и т. д.).

После завершения операции функция возвращает в регистре AL максимально возможный в данной системе номер логического дисковода (определяется параметром LASTDRIVE в файле CONFIG.SYS).

Прерывание Int 21 h, функция 19h: определить номер текущего дисковода

Функция определяет номер дисковода, который в данный момент считается текущим, то есть используется по умолчанию.

Перед вызовом прерывания требуется записать в регистр АН значение 19h.

После завершения операции функция возвращает в регистре AL код логического диска (0 — А:, 1 — В: и т. д.).

Прерывание Int 21 h, функция 1Ah: изменить адрес области обмена с диском

Функция устанавливает адрес буфера, используемого в операциях ввода-вывода и поиска в каталогах.

Перед вызовом прерывания требуется записать в регистры следующие значения:

• в АН — значение lAh;

• в DS: DX — указатель на новый адрес буфера обмена DTA. ПРИМЕЧАНИЕ

При запуске программы ее область DTA первоначально установлена по адресу PSP:0080h.

Прерывание Int 21 h, функция 2Fh: получить адрес области обмена с диском

Функция определяет текущий адрес буфера, используемого в операциях ввода-вывода и поиска в каталогах.

Перед вызовом прерывания требуется записать в регистр АН значение 2Fh.

После завершения операции функция возвращает в ES: ВХ указатель на адрес буфера обмена DTA.

Прерывание Int 21 h, функция 36h: определить объем свободного места на диске

Функция определяет объем свободного места на заданном логическом диске.

Перед вызовом прерывания требуется записать в регистры следующие значения:

• в АН — значение 36h;

• в AL — код логического диска (0 — А:, 1 — В: и т. д.).

В случае ошибки в регистре АХ будет возвращен код OFFFFh (недопустимый код логического диска).

В случае успешного завершения операции функция возвращает:

• в АХ — число секторов в кластере;

• в ВХ — число свободных кластеров;

• в СХ — число байтов в секторе;

• в DX — полное число кластеров на диске.

Объем свободного пространства определяется произведением содержимого регистров АХ, ВХ и СХ, а полный объем диска в байтах — произведением АХ, СХ и DX.

Улучшенные функции для работы с дисками

По мере развития MS-DOS в набор функций постоянно вносились дополнения, упрощающие выполнение тех или иных операций и улучшающие контроль за их выполнением. Для вызова функций данной группы также используется прерывание Int 21h.

Перечисленные ниже функции DOS имеют усовершенствованные средства контроля: в случае ошибки, кроме установки флага CF, выдают в регистре АХ код ошибки, по которому можно определить причину ее возникновения. Возможные значения кодов ошибок приведены в табл. 6.1. Однако следует учитывать, что содержимое регистра АХ в случае успешного завершения данных функций не сохраняется.

Таблица 6.1. Значения расширенных кодов ошибки

MS-DOS для программиста

1. Работа с дисками на физическом уровне

В распоряжении программиста имеются средства разного уровня, предназначенные для работы с дисковой системой в среде MS-DOS.

Во-первых, любая программа может обращаться непосредственно к аппаратуре контроллера жесткого диска или контроллера накопителя на гибких магнитных дисках.

Это самый низкий уровень, применение которого оправдано далеко не всегда. Более того, мы настоятельно рекомендуем не работать с контроллером на уровне портов, если вы точно не знаете, зачем вам это нужно. Большинство задач решается с применением функций MS-DOS или BIOS (даже такие нетрадиционные задачи, как защита от несанкционированного копирования). Однако иногда программист бывает вынужден использовать самый низкий уровень, рискуя потерять совместимость с многочисленными типами дисковых контроллеров.

Во-вторых, программа MS-DOS может работать с дисками при помощи прерывания BIOS. Мы рассмотрим различные функции прерывания INT 13h , предназначенного для выполнения операций чтения, записи и форматирования.

Использование функций прерывания INT 13h намного предпочтительнее, чем непосредственное программирование контроллера, так как BIOS скрывает особенности аппаратной реализации контроллера.

В-третьих, программа может обращаться к прерываниям MS-DOS, специально предназначенным для доступа к дисковой системе. Сервис, предоставляемый этими прерываниями также можно разделить на низко- и высокоуровневый, поэтому у программиста всегда есть выбор.

Выбирая средства обращения к дисковой системе, программист должен вначале рассмотреть возможность использования наиболее высокоуровневых документированных средств, таких как прерывания MS-DOS. И лишь затем имеет смысл обратиться к функциям BIOS или к программированию портов контроллера.

Несмотря на все сказанное выше, мы будем вам рассказывать о средствах работы с дисковой системой, придерживаясь обратного порядка. Вначале мы расскажем вам об использовании наиболее низкоуровневых средств, и лишь затем перейдем к описанию прерываний BIOS и MS-DOS. Это позволит вам подойти к изучению высокоуровневых средств, имея полное представление о том, как устроена дисковая система.

1.1. Обзор дисковых устройств

Первые персональные компьютеры типа IBM PC не имели жесткого диска («винчестера», или, по отечественной терминологии, накопителя на жестком магнитном диске — НМД). Они были оборудованы двумя флоппи-дисками (накопителями на гибком магнитном диске — НГМД), которые и представляли собой дисковую систему. В таких компьютерах установлены, как правило, два накопителя для флоппи-дисков (дискет).

Эти накопители подключены к контроллеру — специальному устройству, выполняющему функции управления. Контроллер обычно выполнен в виде платы и вставлен в разъем системной шины, который находится на основной плате компьютера.

В компьютере IBM PC использовали дискеты диаметром 5,25″. Сейчас все большее число пользователей отказываются от громоздких дискет диаметром 5,25″, отдавая предпочтение более компактным дискетам диаметром 3,5″. Компьютер IBM XT имел один или два НГМД для дискет диаметром 5,25″ и, как правило, один НМД емкостью 20 Мбайт. Все дисководы подключались к одному общему контроллеру. Модель IBM AT и компьютеры более высокого класса могут иметь несколько дисковых контроллеров, два НГМД с различным диаметром (3,5″ и 5,25″) и несколько НМД.

Емкость современных НМД составляет сотни Мбайт. Сейчас, когда стоимость одного Мбайт дисковой памяти не превышает пятидесяти центов, многие пользователи устанавливают в своем компьютеры диски емкостью 540 Мбайт или даже 1 Гбайт. Тем не менее, и такого объема памяти часто оказывается недостаточно.

Пожалуй, самая интересная разновидность современных дисковых накопителей — оптические, или лазерные. Только оптические накопители способны полностью решить проблему хранения огромных объемов информации.

В настоящее время существует несколько типов оптических дисковых накопителей. Это устройство чтения компакт-дисков CD-ROM , устройство записи CD Recordable , накопители WORM и магнитооптические накопители .

Диски CD-ROM (Compact-Disk, Read-Only Memory) — это диски, которые по своему формату и технологии записи информации напоминают звуковые компакт-диски. Они имеют диаметр 120 мм и могут содержать порядка 650 Мбайт информации. Эта информация записывается один раз и впоследствии может только читаться, как из постоянного запоминающего устройства.

Диски CD Recordable внешне очень похожи на диски CD-ROM , однако с помощью специального устройства стоимостью 1000 — 3000 долларов пользователь может записать на него свою информацию. При необходимости можно на один и тот же диск дозаписывать новые данные. Диск CD Recordable можно прочитать с помощью обычного устройства чтения компакт-дисков CD-ROM.

WORM -диски (Write Once, Read Many) предназначены для однократной записи и многократного считывания данных. Эти диски, как и CD Recordable , наилучшим образом подходят для архивного хранения информации, например, содержимого обширных баз данных.

Магнитооптические накопители могут многократно записывать информацию на один и тот же носитель (как обычные магнитные диски). Это самые дорогостоящие дисковые накопители. Их производительность сравнима с производительностью обычных жестких дисков (например, один из накопителей MaxOptix имеет емкость 1,3 Гбайт при среднем времени доступа 19 мсек).

Основной недостаток лазерных накопителей (кроме магнитооптических) — относительно невысокое быстродействие по сравнению с традиционными накопителями на жестких дисках. Однако этот недостаток постепенно преодолевается и, по-видимому, оптические накопители скоро получат широкое распространение, особенно для работы с большими архивами и базами данных.

1.2. Секторы, головки , цилиндры.

Что же, собственно, представляет из себя диск?

Дискета (флоппи-диск) — это круглая пластинка в квадратном конверте, покрытая с двух сторон магнитным материалом. Этот материал похож на тот, что используется в магнитных лентах обычных бытовых магнитофонов, но отличается по некоторым характеристикам (например, по форме и ширине петли гистерезиза). Ближе к центру в диске находится маленькое отверстие, предназначенное для синхронизации.

Когда дискета вставляется в дисковод, с обеих сторон (сверху и снизу) к ней прижимаются магнитные головки . При этом нет никакого зазора между головками и поверхностью дискеты.

С помощью специального шагового двигателя головки могут перемещаться скачкообразно вдоль радиуса диска, как бы прочерчивая при вращении диска концентрические окружности. Эти окружности называются дорожками, треками или цилиндрами — в литературе можно встретить различные названия.

Жесткий диск состоит из нескольких жестких круглых пластинок, покрытых магнитным материалом. Пластинки вращаются с огромной скоростью (порядка 3600 — 7000 оборотов в минуту) в герметичном корпусе. Около каждой стороны пластинки располагается по одной магнитной головке, но эти головки не соприкасаются с диском, а плавают на воздушной подушке в непосредственной близости от его поверхности.

Подавая команды дисковому контроллеру, программа может перемещать блок головок вдоль радиуса диска, переходя таким образом от одного цилиндра к другому.

Перемещаясь вдоль окружности дорожки, магнитная головка может записывать или считывать информацию примерно так, как это происходит в бытовом магнитофоне. Запись выполняется по битам, при этом добавляется различная служебная информация и информация для контроля данных.

Данные записываются не сплошным потоком, а блоками определенного размера. Эти блоки называются секторами. Сектор представляет собой наименьший объем данных, который записывается или прочитывается контроллером.

Для каждого сектора выполняется контроль записи или чтения. При записи сектора вычисляется контрольная сумма всех байтов, находящихся в секторе, и эта контрольная сумма записывается на диск в служебную область, расположенную после сектора. При чтении эта контрольная сумма вычисляется заново и сравнивается с контрольной суммой, считанной из служебной области. При несовпадении контроллер сообщает программе об ошибке.

Дорожки нумеруются начиная от нулевой, головки тоже начиная от нулевой, а вот секторы — начиная с первого. Почему так было сделано — сказать трудно, но именно такая нумерация используется при работе с контроллером диска и функциями прерывания BIOS, обслуживающими дисковую подсистему. В операциях чтения или записи на физическом уровне необходимо указывать номер дорожки (0, 1, . ), головки (0, 1, . ), номер сектора (1, 2, . ).

Для правильной работы с дисками на физическом уровне программа должна располагать существенно большей информацией о дисках, чем просто номер нужной дорожки или головки . Например, она должна знать, сколько головок и сколько дорожек имеет то или иное дисковое устройство, сколько байт содержится в одном секторе и многое другое.

Из следующего раздела книги вы узнаете, как определить конфигурацию дисковой системы и основные параметры установленных дисковых накопителей.

1.3. Характеристики дисковых накопителей

Прежде чем начать работу с дисками на физическом уровне, необходимо выяснить конфигурацию дисковой системы — сколько дисководов и какого типа подключено к компьютеру, сколько дорожек и головок имеется на каждом из дисководов и т. д. Способ, которым определяется конфигурация дисковой системы, зависит от модели компьютера (PC, XT, AT), поэтому вначале займемся определением типа персонального компьютера.

Определение типа компьютера

ПЗУ базовой системы ввода/вывода BIOS содержит по адресу FFFFh:FFFEh байт конфигурации, значение которого можно использовать для идентификации типа компьютера:

Значение Тип компьютера
FFh Оригинальный IBM PC
FEh IBM PC/XT, Portable PC
FDh PCjr
FCh IBM PC/AT
FBh IBM PC/XT с памятью 640 Кбайт на материнской плате
F9h Convertible PC

Для компьютеров IBM PC и IBM PC/XT конфигурация дисковой системы определяется установкой переключателей на основной плате, в частности, переключателями устанавливается количество подключенных к системе НГМД.

Компьютеры IBM PC/AT (и более высокого класса) имеют на основной плате CMOS-память с малым энергопотреблением, которая питается от аккумулятора. В CMOS-памяти хранится информация о конфигурации дисковой системы. В процессе инициализации BIOS считывает эту информацию и записывает ее в свою внутреннюю область данных.

Проанализировав значение байта конфигурации, можно сделать предварительное заключение о составе дисковой системы компьютера. Если оно равно FFh, FDh, F9h, то наш компьютер не имеет НМД — это одна из разновидностей IBM PC. Значения FEh, FBh могут соответствовать IBM PC/XT и совместимым с ним компьютерам. Такие компьютеры могут быть оборудованы НМД. И, наконец, значение FCh соответствует IBM PC/AT. Для этого компьютера конфигурация дисковой системы должна определяться исходя из содержимого CMOS-памяти.

Следует заметить, что новые модели компьютеров могут иметь и другие, не перечисленные выше, коды идентификации.

Прерывание INT 11h

Прерывание базовой системы ввода/вывода INT 11h возвращает в регистре AX байт конфигурации системы, который можно использовать для определения количества НГМД и наличия НМД. Самый младший бит байта конфигурации (бит 0) — признак наличия в системе НМД. Если этот бит установлен в 1, то компьютер оборудован НМД, иначе дисковая система состоит только из накопителей на гибких магнитных дисках.

Биты 7 и 6 содержат информацию о количестве НГМД:

Содержимое бит 7 и 6 Количество установленных НГМД
00 1
01 2
10 3
11 4

Это прерывание лучше всего использовать для IBM PC/XT и IBM PC. Для IBM PC/AT необходимо исследовать содержимое CMOS-памяти. Займемся этим.

Анализ содержимого CMOS-памяти

Программа не может непосредственно адресовать CMOS-память , как обычную оперативную память. Для работы с CMOS-памятью необходимо использовать порты ввода/вывода с адресами 70h и 71h, причем процедура записи или чтения состоит из двух шагов.

На первом шаге операции чтения или записи программа должна записать в порт 70h номер нужной ячейки CMOS-памяти (0. 3Fh). На втором шаге программа должна обратиться к порту 71h для выполнения записи в указанную ячейку памяти или чтения из нее.

Приведем фрагмент программы, составленной на языке ассемблера, который считывает байт из CMOS-памяти с адресом 12h:

Запись в CMOS-память выполняется аналогично.

При анализе конфигурации дисковой системы для нас представляют наибольший интерес ячейки CMOS-памяти со следующими адресами:

  • 14h — байт конфигурации

Биты 7, 6 этого байта имеют такое же значение, что и в младшем байте слова конфигурации, возвращаемого прерыванием INT 11h — они содержат информацию о количестве установленных в компьютере НГМД.

Значение бита 0, равное нулю, говорит о том, что в системе нет ни одного НГМД.

  • 10h — тип НГМД

Младшая и старшая тетрады этого байта описывают, соответственно, второй и первый НГМД:

Значение Емкость, Кбайт Диаметр Количество секторов на одну дорожку Количество дорожек
0000 НГМД не установлен
0001 360 5,25″ 9 40
0010 1200 5,25″ 15 80
0011 720 3,5″ 9 40
0100 1440 3,5″ 18 80
  • 12h — тип НМД C: и D:

Этот байт разделен на две тетрады аналогично байту, который описывает НГМД. Однако в тетраде можно закодировать только 16 значений, а различных типов НМД значительно больше. Поэтому тип 15 используется специальным образом — если тип НМД в младшей тетраде (диск C:) равен 15, то правильное значение типа находится в CMOS-памяти по адресу 19h. Аналогично для диска D: этот тип можно взять из байта по адресу 1Ah (если содержимое старшей тетрады байта с адресом 12h равно 15).

Если в вашем компьютере установлен НМД с интерфейсом ESDI , SCSI или другим специализированным интерфейсом, то, как правило, для работы с ними используется специальная «дисковая» базовая система ввода/вывода. Соответствующая микросхема ПЗУ может быть расположена непосредственно в контроллере. При этом в CMOS-памяти в ячейке 12h для типа диска может быть указано нулевое значение, несмотря на то, что диск установлен. Прерывание INT 11h , тем не менее, скажет вам, что в системе имеется НМД.

Если используется «дисковая» базовая система ввода/вывода, то она сама инициализирует таблицу параметров диска (будет описана позже) и выполняет обработку прерывания INT 13h . Так как MS-DOS при обращении к дискам использует именно это прерывание, то не возникает никаких проблем, связанных с отсутствием типа диска в CMOS-памяти. Другие операционные системы, такие как Windows NT и OS/2 , используют для работы с дисками специальные драйверы.

Приведем сокращенную таблицу параметров для стандартных типов НМД (зависит от версии BIOS):

Тип Количество цилиндров Количество головок Емкость диска в байтах
1 306 4 10.653.696
2 615 4 21.411.840
3 615 6 32.117.760
4 940 8 65.454.080
5 940 6 49.090.560
6 615 4 21.411.840
7 462 8 32.169.984
8 733 5 31.900.160
9 900 15 117.504.000
10 820 3 21.411.840
11 855 5 37.209.600
12 855 7 52.093.440
13 306 8 21.307.392
14 733 7 44.660.224
15
16 612 4 21.307.392
17 977 5 42.519.040
18 977 7 59.526.656
19 1024 7 62.390.272
20 733 5 31.900.160
21 733 7 44.660.224
22 733 5 31.900.160
23 306 4 10.653.696
24 977 5 42.519.040
25 1024 9 80.216.064
26 1224 7 74.575.872
27 1224 11 117.190.656
28 1224 15 159.805.440
29 1024 8 71.303.168
30 1024 11 98.041.856
31 918 11 87.892.992
32 925 9 72.460.800
33 1024 10 89.128.960
34 1024 12 106.954.752
35 1024 13 115.867.648
36 1024 14 124.780.544
37 1024 2 17.825.792
38 1024 16 142.606.336
39 918 15 119.854.080
40 820 6 42.823.680

Для всех приведенных в таблице типов дисков на одной дорожке располагается 17 секторов.

Стандартный компьютер IBM PC/XT комплектуется обычно НМД с типом 1, тип 2 используется в стандартном компьютере IBM PC/AT. Остальные типы НМД используются главным образом старыми версиями BIOS.

Таблицы параметров НМД и НГМД

Для работы с диском на физическом уровне необходимо знать такие его характеристики, как количество головок, секторов и др. Эти характеристики можно определить из таблиц параметров НГМД и НМД, заполняемых BIOS в процессе инициализации системы.

Анализируя содержимое CMOS-памяти в компьютерах IBM PC/AT или установку переключателей конфигурации на основной плате в компьютерах IBM PC и IBM PC/XT, BIOS в процессе инициализации создает таблицу параметров дискеты DPT (Diskette Parameter Table ), а также одну или две таблицы параметров жесткого диска HDPT (Hard Disk Parameter Table). Если имеется специальная «дисковая» система ввода/вывода, то она сама создает таблицы HDPT.

Таблица параметров дискеты DPT имеет длину 10 байт, ее адрес располагается в области данных BIOS по адресу 0000h:0078h, что соответствует вектору прерывания INT 1Eh . Таблица содержит следующие параметры:

Смещение, байт Размер, байт Имя поля Описание
1 srt_hut Биты 0. 3:SRT (Step Rate Time) — задержка для переключения головок, лежит в пределах 1 — 16 мс и задается с интервалом 1 мс (0Fh — 1 мс, 0Eh — 2 мс, 0Dh — 3 мс, . ).Биты 4. 7:Задержка разгрузки головки , лежит в пределах 16 — 240 мс и задается с интервалом 16 мс (1 — 16 мс, 2 — 32 мс, . 0Fh — 240 mc)
1 1 dma_hlt Бит 0:Значение этого бита, равное 1, говорит о том, что используется прямой доступ к памяти;
Биты 2. 7:Время загрузки головок HLT — интервал между сигналом загрузки головок и началом операции чтения или записи, лежит в пределах 2 — 254 мс и задается с интервалом 2 мс (1 — 2 мс, 2 — 4 мс, . 0FFh — 254 мс)
2 1 motor_w Задержка перед выключением двигателя
3 1 sec_size Код размера сектора в байтах:0 — 128;1 — 256;2 — 512;3 — 1024
4 1 eot Номер последнего сектора на дорожке
5 1 gap_rw Длина межсекторного промежутка для чтения или записи
6 1 dtl Максимальная длина передаваемых данных. Используется, когда не задана длина сектора
7 1 gap_f Длина межсекторного промежутка для операции форматирования
8 1 fill_char Байт-заполнитель для форматирования, обычно используется F6h
9 1 hst Время установки головки в мс
10 1 mot_start Время запуска двигателя в 1/8 долях секунды

Все времена зависят от частоты тактового генератора контроллера НГМД, приведенные значения соответствуют частоте 8 МГц.

Адреса таблиц параметров жестких дисков HDPT расположены по адресам, соответствующим векторам прерываний INT 41h (для первого физического диска) и INT 46h (для второго физического диска). Эти таблицы имеют следующий формат:

Смещение, байт Размер, байт Имя поля Описание
2 max_cyl Максимальное количество дорожек на диске
2 1 max_head Максимальное количество магнитных головок
3 2 srwcc Начальная дорожка для предварительной записи (Starting reduced-write current cylinder)
5 2 swpc Начальная дорожка для предварительной компенсации при записи (Starting write precompensation cylinder)
7 1 max_ecc Максимальная длина блока коррекции ошибок ECC (Maximum ECC data burst length)
8 1 dstopt Параметры устройства:
бит 7 — запрет восстановления;
бит 6 — запрет восстановления по блоку коррекции ошибок ECC (Error Correction Code);
биты 2-0 — дополнительные параметры устройства
9 1 st_del Стандартная величина задержки
10 1 fm_del Величина задержки для форматирования диска
11 1 chk_del Величина задержки для проверки диска
12 4 reserve Зарезервировано

Наиболее полезная информация, которую можно извлечь из таблицы параметров дискеты — это код размера сектора . Если вам когда-либо придется работать с нестандартным размером сектора (отличным от 512 байт), вам не обойтись без этой таблицы.

Таблица параметров жесткого диска содержит такие важнейшие значения, как максимальное количество дорожек и максимальное количество головок. Если вам не удалось определить тип диска, то таблица HDPT — единственное надежное место, откуда можно получить информацию о количестве дорожек и головок.

Программа DISKINFO

Для иллюстрации описанных выше приемов определения конфигурации дисковой системы компьютера приведем исходные тексты программы DISKINFO (листинг 1.1). Она определяет конфигурацию дисковой подсистемы и отображает основные характеристики используемых дисководов. Программа DISKINFO обращается к таблицам параметров НГМД и НМД.

В процессе своей работы программа вызывает функцию disk_cfg, которая заполняет поля структуры DISK_CONFIG сведениями о конфигурации дисковой системы:

Имя поля Описание
n_floppy Количество НГМД, установленных в системе
n_hard Количество НМД, установленных в системе
t_floppy1 Тип первого НГМД
t_floppy2 Тип второго НГМД
t_hard1 Тип первого НМД
t_hard2 Тип второго НМД

Листинг 1.1. Файл diskinfo\diskinfo.cpp

1.4. Программирование контроллера НГМД

Большинство дисковых операций можно выполнить на уровне функций BIOS. Это самый простой и надежный способ работы с диском на физическом уровне. Однако в отдельных случаях вам может потребоваться непосредственный доступ к контроллеру НГМД — например, если вы разрабатываете систему защиты данных от несанкционированного копирования.

Информация, приведенная в этом разделе, ориентирована прежде всего не на выполнение операций чтения или записи (которые лучше выполнять с помощью функций BIOS), а на управление контроллером и получение состояния контроллера. Именно эти операции требуются для организации защиты данных от несанкционированного копирования.

Формат дорожки дискеты

Для лучшего понимания работы контроллера мы приведем схему расположения зон данных на дорожке дискеты (рис. 1.1).

Рис. 1.1. Схема расположения зон данных на дорожке дискеты

Каждый сектор на дорожке состоит из областей индекса и данных . Секторы разделены промежутками. В конце дорожки располагается конечный промежуток, его размер зависит от скорости вращения диска, длин секторов и других промежутков. Область индекса содержит информацию о номере дорожки, головки , сектора, код длины сектора. Область данных, очевидно, содержит данные, которые хранятся на диске. Приведем формат сектора (рис. 1.2).

Рис. 1.2. Формат сектора

Порты контроллера НГМД

Программа обращается к контроллеру для выполнения различных операций с помощью команд ввода/вывода. Для IBM PC и IBM PC/XT используются три порта с адресами 3F2h, 3F4h и 3F5h. В компьютерах IBM PC/AT дополнительно используются два порта с адресами 3F6h и 3F7h.

Порт 3F2h работает только на запись, это порт вывода. С его помощью можно выбирать для работы один из НГМД (одновременно можно работать только с одним НГМД), сбрасывать контроллер в исходное состояние, разрешать или запрещать прерывания от контроллера и работу схем прямого доступа к памяти, включать или выключать двигатели НГМД.

Приведем назначение отдельных бит этого порта:

Биты Назначение
0-1 Выбор НГМД. Компьютеры IBM PC/AT не используют бит 1, так как в них установлены только два НГМД
2 0 — сброс контроллера;
1 — разрешение работы контроллера
3 1 — разрешение прерываний и прямого доступа к памяти
4-7 Значение 1 в каждом разряде вызывает включение соответствующего двигателя НГМД. Для компьютеров IBM PC/AT биты 6-7 не используются

Порт 3F4h предназначен только для чтения. С его помощью можно получить байт основного состояния контроллера. Назначение отдельных бит приведено ниже:

Биты Назначение
0-3 Значение 1 говорит о том, что соответствующий НГМД занят, он выполняет операцию поиска. Для IBM PC/AT биты 2-3 не используются
4 Контроллер занят выполнением команды чтения или записи
5 0 — используется режим прямого доступа к памяти;
1 — режим прямого доступа к памяти не используется
6 Направление передачи данных:
0 — от процессора к контроллеру;
1 — от контроллера к процессору
7 Запрос на передачу данных — контроллер готов к записи или чтению данных

Порт 3F5h предназначен для записи или чтения данных. Он используется для всех операций.

Выполнение любой операции начинается с того, что программа посылает в этот порт байт кода операции, за которым следует один или несколько байт параметров. Количество байт параметров и их назначение зависит от кода операции (т. е. от первого байта). После выполнения операции программа считывает несколько байт результата для анализа результата выполнения операции.

Порт 3F7h работает на запись и чтение, он используется только в IBM PC/AT.

При записи в этот порт биты 0-1 определяют скорость передачи данных:

Биты Скорость передачи данных, Кбайт/с
00 500 (высокая плотность HD)
01 300 (двойная плотность DD)
10 250 (одинарная плотность SD)
11 Зарезервировано

Приведем назначение отдельных бит порта 3F7h при чтении из него:

Биты Назначение
1 — выбран НГМД 0
1 1 — выбран НГМД 1
2-5 Выбраны головки : бит 2 соответствует головке 0, бит 3 — головке 1 и т. д.
6 Переключатель записи
7 1 — признак замены дискеты

Команды для контроллера НГМД

Контроллер НГМД может выполнять 15 операций, или команд. Команда разделяется на три фазы — командная фаза, фаза выполнения, фаза результата. В командной фазе программа должна передать контроллеру всю информацию, необходимую для команды. В фазе выполнения команда выполняется, и в фазе результата программа получает от контроллера информацию о состоянии контроллера.

Информация, необходимая для команды, передается контроллеру через порт данных 3F5h. В соответствии с форматом команды программа должна последовательно вывести в этот порт код команды и все параметры.

Прежде чем программа начнет командную фазу, она должна убедиться в том, что контроллер завершил выполнение предыдущей операции и готов к приему команды. Для этого программа должна прочитать байт основного состояния контроллера из порта с адресом 3F4h и проверить биты 6 и 7. Бит 6 должен быть установлен в 0. Это означает, что данные будут передаваться от процессора к контроллеру. Бит 7 должен быть установлен в 1 — это готовность контроллера к приему команды.

Фаза выполнения начинается после установки битов 6 и 7 байта основного состояния в 1. После завершения команды контроллер формирует сигнал запроса прерывания.

В фазе результата процессор считывает состояние контроллера. Это состояние хранится в нескольких внутренних регистрах контроллера:

  • RS — регистр основного состояния ;
  • ST0, ST1, ST2, ST3 — регистры дополнительного состояния .

Регистр основного состояния доступен через порт 3F4h, содержимое остальных регистров процессор считывает после выполнения контроллером команды через порт данных 3F5h.

В форматах команд и таблицах, приведенных ниже, используются следующие обозначения:

Как запустить программу без операционной системы: часть 6. Поддержка работы с дисками с файловой системой FAT

В пятой части нашей серии статей мы показали, как можно использовать прерывания BIOS’а после перехода в защищенный режим, и в качестве примера определили размер оперативной памяти. Сегодня мы разовьем этот успех и реализуем полноценную поддержку работы с дисками с файловой системой FAT16 и FAT32. Работу с файлами на диске можно разбить на 2 части: работа с файловой системой и работа с диском на уровне чтения/записи секторов. Можно сказать, что для этого нам нужно написать «драйвер» файловой системы и «драйвер» диска.

Работа с диском на уровне чтения/записи секторов

Для начала научимся работать с диском.
Итак, мы можем вызывать прерывания BIOS’а. Помимо прочих возможностей, BIOS предоставляет интерфейс для работы с диском, а именно — прерывание int 0x13. Со списком сервисов, предоставляемых прерыванием, можно ознакомиться на википедии. Нас интересуют сервисы чтения и записи дисков.

Существует два способа адресации сектора на диске, с которыми работает BIOS – CHS(cylinder-head-sector) и LBA(logical block addressing). Адресация CHS основана на использовании геометрии диска, и адресом сектора является совокупность трех координат: цилиндр, головка, сектор. Способ позволяет адресовать до 8Гб. Прерывание int0x13 предоставляет возможность читать и писать на диск с использованием этой адресации.

Понятно, что 8Гб — это очень мало, и данный способ адресации является устаревшим, а все современные (и не очень) контроллеры жестких дисков поддерживают адресацию LBA. Адресация LBA абстрагируется от геометрии диска и присваивает каждому сектору собственный номер. Нумерация секторов начинается с нуля. LBA для задания номера блока использует 48 бит, что позволяет адресовать 128 ПиБ, с учетом размера сектора в 512 байт. Прерывание int0x13 предоставляет два сервиса для чтения и записи секторов на диск с использованием LBA. Их мы и будем использовать. Для чтения сектора прерывание in0x13 ожидает следующие параметры:

Прерывание возвращает следующие значения:

Один из параметров – номер диска. Нужно как-то узнать номер диска, с которым мы собрались работать. Нумерация происходит следующим образом: флоппи-диски (fdd), и все, что эмулируется как флоппи, нумеруются с нуля, а жесткие диски (hdd), и все, что эмулируется как они(usb-флешки, например), нумеруются с 0x80. Этот номер никак не связан с последовательностью загрузки в настройках BIOS’а. В нашем случае, диск, с которым мы собираемся работать, является тем диском, с которого мы загрузились.

Когда BIOS передает управление MBR, он загружает его по адресу 0000h:7C00h, а в регистре DL передает нужный нам номер загрузочного устройства. Это является частью интерфейса взаимодействия между BIOS и MBR. Таким образом, этот номер попадает в GRUB, где далее используется для работы с диском. GRUB, в свою очередь, передает этот номер ОС как часть структуры Multiboot information.

Сразу после передачи управления от GRUB’а к ОС в регистре EBX находится указатель на эту структуру. Первое поле структуры – это flags, и если в нем выставлен 2-й бит, то поле boot_device корректно. Это поле так же принадлежит структуре Multiboot information и в его старшем байте (размер поля – 4 байта) хранится нужный нам номер диска, который понимает прерывание int0x13. Таким образом, используя GRUB, мы получили недостающий параметр для чтения/записи секторов на диск.

Мы научились читать и писать сектора на диск, это, безусловно, важно. Но файловая система привязана не к целому диску, а только к его части – разделу. Для работы с файловой системой нужно найти сектор, с которого начинается раздел, на котором она располагается. Информация об имеющихся на диске секторах хранится в первом секторе диска, там же, где располагается MBR. Существует много различных форматов MBR, но для всех них верна следующая структура:

Информация о разделах хранится в таблице разделов. На диске может быть только 4 первичных раздела, с которых можно загрузиться. На запись о разделе приходится 8 байт. Первый байт — это флаги, если его значение 0x80, то раздел загрузочный. Код MBR в процессе своей работы пробегает по этим 4-м разделам в поиске загрузочного раздела. После его обнаружения, MBR копирует содержимое первого сектора этого раздела на адрес 0000h:7C00h и передает туда управление. Нас интересует LBA адрес первого сектора загрузочного раздела, так как именно на нем располагается наше ядро, и присутствует файловая система, которую мы собираемся читать. Для того чтобы получить этот адрес, нужно прочитать первый сектор диска, найти на нем таблицу разделов, в таблице разделов найти загрузочный раздел, а из его записи прочитать нужное поле.

Итак, у нас есть механизм для чтения сектора с диска и знание о расположении нужного нам раздела на диске. Осталось научиться работать с файловой системой на этом разделе.

Работа с файловой системой

Для работы с файловой системой мы будем использовать библиотеку fat_io_lib. Библиотека доступна под лицензией GPL. Она предоставляет интерфейс для работы с файлами и директориями, аналогичный имеющемуся в libc. Реализованы такие функции, как fopen(), fgets(), fputc(), fread(), fwrite() и т.д. Библиотека для своей работы требует всего лишь две функции: записать сектор и прочитать сектор, причем первая является необязательной. Функции имеют следующий прототип:

Библиотека написана на чистом С, что опять-таки нам на руку. Для использования в своей мини-ОС нам не придется менять в ней ни строчки. Библиотека ожидает, что чтение секторов происходит в рамках раздела с файловой системой.

Итак, у нас есть функции чтения/записи сектора на раздел и есть библиотека для работы с FAT16/32, которая использует эти функции. Осталось собрать все воедино и продемонстрировать результат. Но прежде чем перейти к коду, хотелось бы показать, что подход, который мы собираемся использовать, вполне применим в реальной жизни. Ниже представлена небольшая часть VBR windows 7, в которой происходит чтение сектора диска посредством прерывания int0x13. Этот код многократно вызывается в процессе загрузки системы, вплоть до момента отрисовки загрузочной анимации.

Для вызова этого кода, Windows 7, подобно тому, как это делаем мы, переходит из защищенного режима в реальный, и обратно. Это несложно проверить, запустив Windows 7 в QEMU. QEMU должен ожидать подключения отладчика. После подключения отладчика (gdb) ставим breakpoint на адрес (0x7c00 + 0x11d). Срабатывание breakpoint’а будет означать вызов этой функции. Кстати в Windows XP этот механизм отсутствует, для вызова прерываний BIOS’а там переходят в режим VM86.

! ВАЖНО! Все дальнейшие действия могут успешно осуществляться только после успешного прохождения всех шагов из пятой части нашей серии статей

Шаг 1. Изменим основную логику в kernel.c

1. Добавим в файле kernel.c следующие объявления:

Код, печатающий размер оперативной памяти

заменим на следующий код:

Память под переменные mbd и magic зарезервирована в файле loader.s, так что их можно использовать аналогично глобальным переменным из кода на С. Переменная magic содержит сигнатуру, подтверждающую, что для загрузки использовался стандарт Multiboot, эталонной реализацией которого является GRUB. Переменная mbd указывает на структуру multiboot_info_t, которая объявлена в multiboot.h. Номер загрузочного диска определяется следующим выражением — p_multiboot_info->boot_device >> 24. Функция InitBootMedia запоминает номер диска и ищет первый сектор файловой системы, чтобы затем все смещения считать от него.

Библиотека fat_io_lib для инициализации требует вызова двух функций: fl_init и fl_attach_media. Первая функция обнуляет внутренние структуры библиотеки, а вторая получает в качестве параметров функции чтения и записи секторов на диск, которые затем используются для обращения к файлам. Далее идет демонстрация работы с библиотекой: выводится список файлов в папке /boot/grub и распечатывается содержимое файла menu.lst.

2. Добавляем файл multiboot.h в папку include. Содержимое файла берем с сайта спецификации предыдущей версии.

Шаг 2. Добавим функции для работы с диском

1. В файл include\callrealmode.h добавим прототипы следующих функций:

2. В файле include\callrealmode_asm.h добавим в enum callrealmode_Func новое значение так, чтобы получилось следующее:

Добавим в union внутри структуры callrealmode_Data только что объявленную структуру callrealmode_read_disk. Должно получиться следующее:

3. В файл include\string.h добавим функции strncmp и strncpy, используемые в библиотеке fat_io_lib.

4. Добавим в файл callrealmode.c следующие объявления:

И несколько функций:

Функции ReadBootMedia и WriteBootMedia используются библиотекой fat_io_lib для чтения/записи секторов. Функция WriteBootMedia не обязательная и является заглушкой, так как в данном примере нет записи на диск. Ее реализация выглядела бы аналогично функции ReadBootMedia. Функция ReadBootMedia похожа на функцию GetRamsize из прошлой статьи с точностью до типа param.func, а вместо param.getsysmemmap используется param.readdisk. Функция InitBootMedia должна быть вызвана раньше двух остальных, так как она инициализирует значения g_BootPartitionStart и g_BootDeviceInt13Num.

5. Изменим callrealmode_asm.s. Добавим еще один тип CALLREALMODE_FUNC_READ_DISK вызываемых функций, должно получиться следующее:

Далее добавим еще одну проверку на тип функции и непосредственно код, читающий с диска. Должно получиться следующее:

Метка readdisk указывает на код, который формирует структуру DAP из структуры callrealmode_Data и вызывает int0x13. В коде после метки callrealmode_switch добавилось 2 инструкции, проверяющие, не нужно ли вызывать readdisk.

6. Добавим файл include\mbr.h, содержащий определения для работы с MBR. Его содержимое:

Структура MBRSector используется в функции InitBootMedia.

Шаг 3. Добавим библиотеку fat_io_lib и запустим

1. Скачаем архив fat_io_lib.zip и распакуем его в папку fat_io_lib в корне проекта.
2. Добавим пустые файлы assert.h и stdlib.h в папку include. Они нужны, что бы библиотека скомпилировалась.
3. Исправим Makefile. Добавим файлы из библиотеки в список целей для компиляции. Должно получиться следующее:

Теперь размер образа равен 10Mb. Это делается для того, чтобы команда mkdosfs отформатировала раздел в FAT16 вместо FAT12. FAT12 не поддерживается библиотекой fat_io_lib.

С этим дефайном библиотека не будет включать stdio.h, но будет использовать готовый прототип функции printf, который совпадает с нашим, и который уже реализован.

4. Пересоберем проект

sudo make image

Должно получиться следующее:

Как и в предыдущих частях, можно сделать dd образа hdd.img на флешку и проверить код на реальном железе, загрузившись с нее.

В результате мы реализовали работу с файловыми системами FAT16 и FAT32. Мы немного схитрили, использовав готовую библиотеку, но разбираться в устройстве FAT’а было бы менее интересно, да и вряд ли бы мы тогда уложились в 1 статью. Надеюсь, вам было интересно читать. Пишите в комментариях, если у вас возникнут проблемы в прохождении описанных шагов!

indbooks

Читать онлайн книгу

Приложение Б Функции DOS (INT 21h)

DOS, функция 00h

CS – сегмент PSP завершающегося процесса

Описание. Передает управление на вектор завершения в PSP (выходит в родительский процесс). Идентична функции INT 20h (Terminate). Регистр CS должен указывать на PSP. Восстанавливает векторы прерываний DOS 22h-24h (Завершение, Ctrl-Break и Критическая ошибка), устанавливая значения, сохраненные в родительском PSP. Выполняет сброс файловых буферов. Файлы должны быть предварительно закрыты, если их длина изменилась.

Данная функция не рекомендуется к использованию. Для выхода из программы лучше использовать функцию DOS 4Ch.

DOS, функция 01h Считать со стандартного устройства ввода

Выход: AL – символ, полученный из стандартного ввода

Описание. Считывает (ожидает) символ со стандартного входного устройства. Отображает этот символ на стандартное выходное устройство (эхо). При обнаружении Ctrl-Break выполняется INT 23h.

Ввод расширенных клавиш ASCII (F1-F12, PgUp, курсор и другие) требует двух обращений к этой функции. Первый вызов возвращает AL=0. Второй вызов возвращает в AL расширенный код ASCII.

DOS, функция 02h Записать в стандартное устройство вывода

DL – символ, выводимый в стандартный вывод

Посылает символ из DL в стандартное устройство вывода. Обрабатывает символ Backspace (ASCII 8), перемещая курсор влево на одну позицию и оставляя его в новой позиции. При обнаружении Ctrl-Break выполняется INT 23h.

DOS, функция 03h Считать символа со стандартного вспомогательного устройства

Выход: AL – символ, введенный со стандартного вспомогательного устройства

Описание. Считывает (ожидает) символ со стандартного вспомогательного устройства, COM1 или AUX и возвращает этот символ в AL.

Ввод не буферизуется и должен опрашиваться (не управляется прерываниями). При запуске DOS порт AUX (COM1) инициализируется так: 2400 бод, без проверки на четность, 1 стоп-бит, 8-битные слова. Команда DOS MODE используется для установки иных характеристик.

DOS, функция 04h Записать символ в стандартное вспомогательное устройство

DL – символ, выводимый в стандартное вспомогательное устройство

Посылает символ, находящийся в регистре DL, на стандартное вспомогательное устройство, COM1 или AUX.

DOS, функция 05h Вывести на принтер

DL – символ, записываемый на стандартный принтер

Посылает символ в DL на стандартное устройство печати, обычно LPT1.

DOS, функция 06h Консольный ввод-вывод

DL=00h-FEh – символ, посылаемый на стандартный вывод

DL=FFh – запрос ввода со стандартного ввода

ZF=0, если осуществлялся ввод символа и символ готов при запросе ввода

AL – считанный символ

ZF=1, если осуществлялся ввод символа и символа в консоли нет

При DL=0FFh выполняет ввод с консоли «Без ожидания», возвращая включенный флаг нуля ZF, если на консоли нет готового символа. Если символ готов, сбрасывает флаг ZF и возвращает считанный символ в AL. Если DL не равен 0FFh, то DL направляется на стандартный вывод.

DOS, функция 07h Нефильтрующий консольный ввод без эха

Выход: AL – символ, полученный через стандартный ввод

Описание. Считывает (ожидает) символ со стандартного входного устройства и возвращает этот символ в AL. Не проверяет на Ctrl-Break, BackSpace и другие.

Для ввода расширенного символа ASCII должна быть вызвана дважды. Для проверки статуса используется функция DOS 0Bh (чтобы не ожидать нажатия клавиши).

DOS, функция 08h Консольный ввод без эха

Выход: AL – символ, полученный через стандартный ввод

Описание. Считывает (ожидает) символ со стандартного входного устройства и возвращает этот символ в AL. При обнаружении Ctrl-Break выполняется прерывание INT 23h.

Для ввода расширенного символа ASCII должна быть вызвана дважды.

DOS, функция 09h Запись строки на стандартный вывод

DS:DX – адрес строки, заканчивающейся символом «$» (ASCII 24h)

Строка, исключая завершающий ее символ «$», посылается на стандартный вывод. Символы Backspace обрабатываются как в функции 02h (вывод на дисплей). Чтобы перейти на новую строку, обычно включают в текст пару CR/LF (ASCII 0Dh и ASCII 0Ah). Строки, содержащие «$», можно передать на стандартное устройство вывода с помощью функции 40h (BX=0).

DOS, функция 0Ah Ввод строки в буфер

DS:DX – адрес входного буфера (Таблица Б-1)

Таблица Б-1. Формат входного буфера

Буфер содержит введенные данные, в конце – символ CR (ASCII 0Dh)

DOS, функция 0Bh Проверка статуса ввода

Выход: AL=FFh, если символ доступен со стандартного ввода AL=00h, если нет доступного символа

Описание. Проверяет состояние стандартного ввода. При распознавании Ctrl-Break выполняется INT 23h.

Используется перед функциями 01h, 07h и 08h, чтобы избежать ожидания нажатия клавиши.

Эта функция дает простой неразрушающий способ проверки Ctrl-Break в процессе длинных вычислений или другой обработки, обычно не требующей ввода. Это позволяет снимать счет по нажатию Ctrl-Break.

DOS, функция 0Ch Ввод с очисткой

AL – номер функции ввода DOS:

AL=01h – ввод с клавиатуры

AL=06h – ввод с консоли

AL=07h – нефильтрующий без эха

AL=08h – ввод без эха

AL=0Ah – буферизованный ввод

Очищает буфер опережающего ввода стандартного ввода, а затем вызывает функцию ввода, указанную в AL. Это заставляет систему ожидать ввод очередного символа.

DOS, функция 0Dh Сброс диска

Сбрасывает диск (записывает на диск все файловые буферы). Файл, размер которого изменился, должен быть предварительно закрыт (при помощи функций 10h или 3Eh).

DOS, функция 0Eh Установить текущий диск DOS

DL – номер диска (0 – A, 1 – B и так далее), который становится текущим

Выход: AL – общее число дисководов в системе

Описание. Диск, указанный в DL, становится текущим. Проверка: используется функция 19h (дать текущий диск). В регистре AL возвращается число дисководов всех типов, включая жесткие диски и «логические» диски (как диск B: системе с одним гибким диском).

AL имеет то же значение, что и LASTDRIVE, указанное в файле CONFIG.SYS, и по умолчанию равно 5.

DOS, функция 0Fh Открыть файл через FCB

DS:DX – адрес неоткрытого FCB (Таблица Б-2)

Таблица Б-2. Формат FCB

AL=00h, если функция выполнена успешно (FCB заполнен)

AL=FFh, если файл не найден или доступ к файлу не разрешен

Файл, описываемый неоткрытым FCB, должен существовать в текущем оглавлении на диске, специфицированном в FCB (0 – текущий, 1 – A, 2 – B и так далее). Если файл не существует, возвращается AL=0FFh. Файл открывается в режиме совместимости. Если поле «Номер диска» в FCB равно нулю в момент вызова, то оно заполняется номером текущего дисковода (1 – A, 2 – B и так далее). Поле FCB «Номер текущего блока» устанавливается в ноль. Поле FCB «Размер логической записи» устанавливается в 80h. Поля даты и размера файла в FCB устанавливаются из оглавления.

DOS, функция 10h Закрыть файл через FCB

DS:DX – адрес открытого FCB (Таблица Б-2)

AL=00h, если функция выполнена успешно

AL=FFh, если файл не найден там, где он находился при открытии с помощью функции 0Fh

Закрывает файл, открытый функцией 0Fh. Файл должен находиться на своем первоначальном месте в текущем оглавлении диска, на котором он был открыт. Если файл найден, оглавление обновляется, файловые буфера сбрасываются и возвращается AL=00h. Если файл не найден, оглавление не обновляется и возвращается AL=FFh.

DOS, функция 11h Найти первый совпадающий файл через FCB

DS:DX – адрес неоткрытого FCB (Таблица Б-2)

AL=00h, если подходящее имя найдено

AL=FFh, если подходящего имени нет

В текущем оглавлении DOS происходит поиск файлов с именем, соответствующим заданному шаблону. При неудаче возвращается AL=0FFh. Если имя найдено, AL очищается, в первый байт DTA помещается номер дисковода (A – 1, B – 2 и так далее), а в следующие 32 байта помещается элемент оглавления для найденного файла.

Можно использовать при вызове расширенный FCB, чтобы выбирать файлы с указанными атрибутами. В этом случае в DTA помещаются: байт FFh, 7 байт нулей, номер диска и элемент оглавления.

DOS, функция 12h Найти следующий совпадающий файл через FCB

DS:DX – адрес неоткрытого FCB (Таблица Б-2)

AL=00h, если подходящее имя найдено

DTA заполнен AL=FFh, если подходящего имени нет

Используется после вызова функции 11h (Найти первый совпадающий файл через FCB) с обобщенным именем файла. Каждый последующий вызов заполняет DTA очередным подходящим элементом оглавления и возвращает AL=00h. Если подходящих имен больше нет, возвращается AL=FFh.

Резервируемая область в FCB сохраняет информацию, необходимую для продолжения поиска. Поэтому не стоит открывать и изменять FCB между вызовами.

DOS, функция 13h Удалить файл через FCB

DS:DX – адрес неоткрытого FCB (Таблица Б-2)

AL=00h, если функция выполнена успешно

AL=FFh, если файл не найден или доступ к файлу не разрешен

Эта функция удаляет все подходящие файлы в текущем оглавлении указанного диска согласно спецификации в FCB. Если подходящие файлы не найдены или если доступ отвергнут (как при попытке удалить файл с атрибутом Read-Only), функция возвращает в регистре AL значение FFh.

DOS, функция 14h Последовательное чтение из файла через FCB

DS:DX – адрес открытого FCB (Таблица Б-2)

AL=00h, если чтение было успешным и DTA содержит данные

AL=01h, если достигнут конец файла (EOF) и данные не считаны

AL=02h, если произошел выход за сегмент (чтения не было)

AL=03h, если EOF и считана усеченная запись (дополнена нулями)

Функция читает файл, специфицированный в FCB. Затем соответственно увеличивает значения полей в FCB.

Перед началом последовательной обработки файла нужно сбрасывать CurRec в ноль, так как функция 0Fh не инициализирует это поле.

DOS, функция 15h Последовательная запись в файл через FCB

DS:DX – адрес открытого FCB (Таблица Б-2)

AL=00h, если запись была успешной

AL=01h, если ошибка переполнения диска (данные не записаны)

AL=02h, если произошел выход за сегмент (записи не было)

Функция записывает файл, специфицированный в FCB. Затем соответственно увеличивает значения полей в FCB.

Перед началом последовательной обработки файла нужно сбрасывать «Номер текщей записи» в ноль, так как функция 0Fh не инициализирует это поле.

DOS буферизует данные, записывая полный сектор за один раз.

DOS, функция 16h Создание файла через FCB

DS:DX – адрес неоткрытого FCB (Таблица Б-2)

AL=00h, если функция выполнена успешно FCB заполнен

AL=FFh, если при выполнении функции возникли ошибки

Описание. Файл, специфицированный неоткрытым FCB, создается на диске, указанном в FCB (0 – текущий, 1 – A и так далее). Он открывается в текущем оглавлении этого диска. FCB заполняется аналогично функции 0Fh. Если файл существует в момент вызова, его элемент оглавления перекрывается новым файлом, а длина файла сбрасывается в ноль.

Handle-ориентированные функции DOS 2.0+ гораздо удобнее в работе.

DOS, функция 17h Переименовать файл через FCB

DS:DX – адрес измененного FCB (Таблица Б-2)

AL=00h, если функция выполнена успешно

AL=FFh, если при выполнении функции возникли ошибки

Переименовывает файл в текущем оглавлении.

DOS, функция 19h Получить текущий диск DOS

Выход: AL – номер текущего диска (0 – A, 1 – B, и так далее)

Возвращает номер дисковода текущего диска DOS.

DOS, функция 1Ah Установить адрес DTA

DS:DX – адрес DTA

Устанавливает адрес DTA. Все FCB-ориентированные операции работают с DTA. DOS не позволяет операциям ввода/вывода пересекать границу сегмента. Функции поиска 11h, 12h, 4Eh и 4Fh помещают данные в DTA. DTA глобальна, поэтому надо проявлять осторожность при назначении ее в рекурсивной процедуре. При запуске программы ее DTA устанавливается по смещению 80h относительно PSP.

DOS, функция 1Bh Получить информацию FAT для текущего диска

DS:BX – адрес байта FAT ID, отражающего тип диска (Таблица Б-3)

DX – всего кластеров (единиц распределения) на диске

AL – секторов на кластер

CX – байт на сектор

Таблица Б-3. Значения ID

Возвращает информацию о размере и типе текущего диска. Размер диска (в байтах) равен DX*AL*CX. Свободную память можно найти функциями 36h или 32h.

Версии: DOS 1.x держит FAT в памяти и возвращает DS:BX => FAT. DOS 2.0+ может держать в памяти лишь часть всей FAT.

Эта функция изменяет содержимое регистра DS.

DOS, функция 1Ch Получить информацию FAT для указанного диска

DL – номер диска (0 – текущий, 1 – A и так далее)

DS:BX – адрес байта FAT ID, отражающего тип диска (приведен в описании функции 1Bh)

DX – всего кластеров (единиц распределения)

AL – секторов на кластер

CX – байт на сектор

Аналогична функции 1Bh с той разницей, что регистр DL указывает диск, для которого нужно получить информацию.

DOS, функция 21h Считать произвольную запись файла

DS:DX – адрес открытого FCB (Таблица Б-2)

AL=00h, если чтение было успешным и DTA заполнена данными

AL=01h, если достигнут конец файла (EOF) и чтения не было

AL=02h, если произошел выход за сегмент (чтения нет)

AL=03h, если встречен EOF и усеченная запись дополнена нулями

Данная функция читает из файла с текущей позиции как с указанной в полях FCB «Запись с текущей позиции» и «Номер записи при непосредственном доступе к файлу».

DOS, функция 22h Писать произвольную запись файла

DS:DX – адрес открытого FCB (Таблица Б-2)

AL=00h, если запись была успешной

AL=01h, при переполнении диска

AL=02h, если DTA+FCB выходит за сегмент (нет записи)

Данная функция записывает в файл с текущей позиции как с указанной в полях FCB «Запись с текущей позиции» и «Номер записи при непосредственном доступе к файлу».

DOS, функция 23h Получить размер файла через FCB

DS:DX – адрес неоткрытого FCB (Таблица Б-2)

AL=00h, если функция выполнена успешно

AL=FFh, если при выполнении функции возникли ошибки

Проще определить размер файла при помощи функции 3Dh с последующим выполнением 42h (при AL=2).

DOS, функция 24h Установить адрес произвольной записи в файле

DS:DX – адрес открытого FCB (Таблица Б-2)

Устанавливает поле «Номер записи при непосредственном доступе к файлу» в FCB на файловый адрес, соответствующий значениям полей «Текущий блок» и «Запись с текущей позиции».

DOS, функция 25h Установить вектор прерывания

AL – номер прерывания

DS:DX – вектор прерывания – адрес программы обработки прерывания

Описание. Устанавливает значение элемента таблицы векторов прерываний для прерывания с номером AL, равным DS:DX. Это равносильно записи 4-байтового адреса в 0000:(AL*4), но, в отличие от прямой записи, DOS знает, что происходит, и гарантирует, что в момент записи прерывания будут заблокированы.

Восстановить DS (если необходимо) после этого вызова.

DOS, функция 26h Создать новый PSP

DX – адрес сегмента (параграфа) для нового PSP

CS – сегмент PSP, используемый как шаблон для нового PSP (Таблица Б-4)

Описание. Устанавливает PSP для порождаемого процесса по адресу DX:0000. Текущий PSP (100h байт, начиная с CS:0) копируется в DX:0000h, поле MemTop соответственно корректируется, векторы Terminate, Ctrl-Break и Critical Error копируются в PSP из векторов прерываний INT 22h, INT 23h и INT 24h. После этого можно загрузить программу с диска и передать ей управление посредством FAR JMP.

Если перехватывается INT 21h, нужно позаботиться о помещении в стек корректного CS: IP. Еще лучше использовать функцию 4Ch.

Таблица Б-4. Формат PSP

DOS, функция 27h Читать произвольный блок файла

DS:DX – адрес открытого FCB (Таблица Б-2)

CX – число считываемых записей

Выход: AL=00h, если чтение успешно и DTA заполнена данными AL=01h если достигнут конец файла (EOF) и данные не считаны AL=02h, если при чтении произошел выход за границу сегмента AL=03h, если EOF и считана усеченная порция (дополнена нулями) CX – действительное число считанных записей

Читает несколько записей из файла, начиная с файлового адреса, указанного полем «Номер записи при непосредственном доступе к файлу» в FCB. Помещает данные в память, начиная с адреса DTA. Соответствующие поля FCB корректируются, чтобы указывать на следующую запись (первую за прочитанными).

DOS, функция 28h Писать произвольный блок файла

DS:DX – адрес открытого FCB (Таблица Б-2)

CX – число записываемых блоков (если CX равен нулю, то размер файла усекается до указанного в поле FCB «Номер записи при непосредственном доступе к файлу»)

AL=00h, если запись успешна

AL=01h, при переполнении диска

AL=02h, если при записи произошел выход за границу сегмента

CX – действительное число сделанных записей

Описание. Записывает несколько блоков в файл, начиная с файлового адреса, указанного полем «Номер записи при непосредственном доступе к файлу» в FCB. Читает данные из памяти, начиная с адреса DTA. Соответствующие поля FCB корректируются, чтобы указывать на следующую запись (первую за прочитанными).

DOS, функция 29h Разобрать имя файла

DS:SI – адрес исходной текстовой строки для разбора

ES:DI – адрес буфера для результирующего неоткрытого FCB (Таблица Б-2)

AL – битовые флаги, указывающие опции разбора (Таблица Б-5).

AL=00h, если результирующий FCB не содержит обобщенных символов

AL=01h, если результирующий FCB содержит обобщенные символы

AL=FFh, если неверно обозначение диска в имени файла

DS:SI – изменен – указывает на символ сразу вслед за именем файла

ES:DI – не изменен – указывает на неоткрытый FCB

Создает неоткрытый FCB из строки текста или параметра команды. Текст, начиная с DS:SI, анализируется как имя файла в формате D: FILENAME.EXT, и буфер по адресу ES:DI заполняется как соответственно форматированный FCB.

Таблица Б-5. Битовые флаги

DOS, функция 2Ah Получить системную дату

AL – день недели (0 – воскресенье, 1 – понедельник, … 6 – суббота), DOS 3.0+

CX – год (от 1980 до 2099)

DH – месяц (1 до 12)

DL – день (1 до 31)

Описание. Возвращает текущую дату, которая известна системе.

DOS 2.x не гарантирует возврата в AL значения дня.

DOS 1.0+ возвращает правильный день недели.

Версии до 2.1 имеют проблемы с переходом через дату.

DOS, функция 2Bh Установить системную дату

CX – год (от 1980 до 2099)

DH – месяц (от 1 до 12)

DL – день (от 1 до 31)

AL=00h, если дата корректна

AL=FFh, если дата некорректна и не изменена

Устанавливает системную дату DOS.

DOS, функция 2Ch Получить время DOS

CH – часы (от 0 до 23)

CL – минуты (от 0 до 59)

DH – секунды (от 0 до 59)

DL – сотые доли секунды (от 0 до 99)

Описание. Возвращает текущее время, которое известно системе.

Поскольку системные часы имеют частоту 18.2 Гц (интервал 55мс), DL имеет точность примерно 0.04 сек.

DOS, функция 2Dh Установить время DOS

CH – часы (от 0 до 23)

CL – минуты (от 0 до 59)

DH – секунды (от 0 до 59)

DL – сотые доли секунды (от 0 до 99)

AL=00h, если время корректно

AL=FFh, если время некорректно и не изменено

Устанавливает системное время DOS.

DOS, функция 2Eh Установить/сбросить переключатель верификации

AL=00h – отключить верификацию

AL=01h – включить верификацию

Описание. Задает, должна ли DOS верифицировать (считывать обратно) каждый сектор, записываемый на диск. Это замедляет операции записи на диск, но гарантирует максимальную надежность записи.

DOS, функция 2Fh Получить адрес текущей DTA

Выход: ES:BX – адрес начала текущей DTA

Описание. Возвращает адрес начала области ввода-вывода (DTA). Поскольку DTA глобальна для всех процессов, в рекурсивной процедуре (например, при проходе по дереву оглавления) может потребоваться сохранить адрес DTA, а впоследствии восстановить его посредством функции 1Ah.

Примечание. Эта функция изменяет сегментный регистр ES.

Версии: DOS 2.00 и выше DOS, функция 30h Получить номер версии DOS

AL – старший номер версии

AH – младший номер версии

BL:CX – 24-битный серийный номер (большинство версий не поддерживают этот параметр)

Описание. Возвращает в AX значение текущего номера версии DOS. Например, для DOS 3.20 в AL возвращается 03h, в AH – 14h.

Примечание. Если в AL возвращается 00h, можно предполагать, что работает DOS более ранней версии, чем DOS 2.0.

Версии: DOS 2.00 и выше. DOS, функция 31h Завершиться и остаться резидентным

DX – объем памяти, оставляемой резидентной (в параграфах)

Описание. Выходит в родительский процесс, сохраняя код выхода в AL. Код выхода можно получить через функцию 4Dh. DOS устанавливает начальное распределение памяти, как специфицировано в DX, и возвращает управление родительскому процессу, оставляя указанную память резидентной (число байт равно DX*16). Эта функция перекрывает функцию INT 27h, которая не возвращает код выхода и не способна установить резидентную программу, размер которой превышает 64 Кбайт.

Версии: DOS 2.00 и выше. DOS, функция 32h Получить информацию DOS о диске (Официально не документирована)

DL – номер диска (0 – текущий, 1 – A и так далее)

AL=00h, если в DL был задан корректный диск

DS:BX – адрес блока информации о диске для запрошенного устройства (Таблица Б-6)

AL=FFh, если в DL был задан некорректный диск

Возвращает блок информации, представляющей интерес для приложений и утилит, которые выполняют доступ к дискам, поддерживаемым драйверами устройств, на уровне секторов.

Некоторые дисководы (особенно незагружаемые) функционируют только через свои драйвера устройств. Такие диски могут содержать неверную информацию в корневой записи и таблице разделов, что делает очень трудным определение, например, размера корневого оглавления, числа таблиц FAT и прочего. Блок информации диска содержит такие данные в хорошо форматированной структуре.

Версии: DOS 2.00 и выше. Таблица Б-6. Формат блока информации о диске

DOS, функция 33h Установить/опросить статус Ctrl-Break

AL=00h – опросить текущий статус контроля Ctrl-Break

AL=01h – установить статус контроля Ctrl-Break

DL – требуемый статус (0 – выключен, 1 – включен)

Выход: DL – текущий статус (0 – выключен, 1 – включен)

Если AL=00h, в DL возвращается текущий статус контроля Ctrl-Break.

Если AL=01h, в DL возвращается новый текущий статус.

Когда статус «включен», DOS при выполнении большинства функций (исключая 06h и 07h) проверяет, нажаты ли клавиши Ctrl-Break. Если это обнаружено, выполняется прерывание INT 23h (если оно не перехватывается, то процесс снимается).

При статусе «выключен» DOS проверяет на нажатие Ctrl-Break лишь при выполнении операций стандартного ввода/вывода, стандартной печати и стандартного AUX.

Версии: DOS 2.00 и выше. DOS, функция 34h Получить адрес флага активности DOS (Официально не документирована)

Выход: ES:BX – адрес флага активности DOS

Функция возвращает флаг активности DOS, который показывает, можно ли на данный момент вызывать функции DOS. Эту функцию использует, например, функция фоновой печати PRINT.

Если ES: [BX] не нулевой, фоновая программа (TSR либо popup) не должна использовать никаких функций DOS.

Версии: DOS 2.00 и выше. DOS, функция 35h Получить вектор прерывания

AL – номер прерывания (00h до FFh)

Выход: ES:BX – адрес обработчика прерывания

Описание. Возвращает значение вектора прерывания для INT (AL), то есть загружает в BX 0000:[AL*4], а в ES – 0000:[(AL*4)+2].

Примечание. Эта функция изменяет сегментный регистр ES.

Версии: DOS 2.00 и выше. DOS, функция 36h Получить свободную память диска

DL – номер диска (0 – текущий, 1 – A и так далее)

AX=FFFFh, если AL содержал неверный номер диска

Если функция выполнена успешно:

AX – число секторов на кластер

BX – число доступных кластеров

CX – байт на сектор

DX – всего кластеров на диске

Описание. Возвращает данные, полезные для подсчета общей и доступной дисковой памяти. Если в AX возвращено FFFFh, значит задан неверный диск. Иначе свободная память (в байтах) составляет (AX*BX*CX), всего памяти (AX*CX*DX) байт.

Версии: DOS 2.00 и выше. DOS, функция 37h Установить/опросить символ-переключатель (Официально не документирована)

AL=00h – опросить текущий переключатель

AL=01h – установить символ-переключатель

AL=00h, если функция выполнена успешно

DL – текущий символ-переключатель DOS (если при вызове AL=00h)

AL=FFh, если использована неподдерживаемая подфункция

Описание. Устанавливает или опрашивает «Глобальный переключатель» DOS. Переключатель (SWITCHAR) – это символ, используемый в командной строке как признак опции. По умолчанию принимается «/» (например, DIR /w/p), но его можно изменить на «-» (DIR – w-p), если нужно, чтобы система была больше похожа на UNIX. Общепринято опрашивать значение SWITCHAR перед разбором области неформатированных параметров в PSP для выделения опций команды.

Примечание. Эта недокументированная команда может измениться в будущих версиях DOS. Не рекомендуется изменять SWITCHAR.

Версии: DOS 2.00 и выше. DOS, функция 38h Получить/установить информацию о стране

AL=00h – получить данные для текущей страны

DS:DX – адрес локального буфера для чтения блока данных страны (Таблица Б-7)

AL=01h-FEh – установить данные для указанной страны 255

BX – 16-битный код страны (Таблица Б-8)

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

Описание. Если DX=FFFFh, то текущий код страны устанавливается равным AL (если AL=FFh, то код страны устанавливается равным BX). Обычно код страны устанавливается в файле CONFIG.SYS. Если DX Таблица Б-7. Формат блока данных страны

DOS, функция 39h Создать новое оглавление

DS:DX – адрес строки ASCIZ с именем оглавления

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

Таблица Б-8. Коды некоторых стран

Если диск и/или корневой путь не указаны, то новое оглавление создается в текущей директории. Поддиректория создается и связывается с существующим деревом. Если флаг CF установлен при возврате, то AX содержит код ошибки, и оглавление не создается.

Версии: DOS 2.00 и выше. DOS, функция 3Ah Удалить оглавление

DS:DX – адрес строки ASCIZ с именем оглавления

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

Описание. Если диск и/или корневой путь не указаны, принимаются значения по умолчанию. Поддиректория удаляется из структуры оглавлений. Если флаг CF установлен при возврате, то AX содержит код ошибки, и оглавление не удаляется.

Примечание. Оглавление не должно содержать файлов и поддиректорий, оно не должно попадать под влияние возможных ограничений DOS (например, не должно быть задействовано в активных командах JOIN или SUBST).

Версии: DOS 2.00 и выше. DOS, функция 3Bh Установить текущую директорию

DS:DX – адрес строки ASCIZ с именем оглавления

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

Описание. Если диск и/или корневой путь не указаны, принимаются значения по умолчанию. Указанная поддиректория становится текущим оглавлением DOS для этого (или текущего) диска. Если флаг CF установлен при возврате, то AX содержит код ошибки, и текущее оглавление для выбранного диска не изменяется.

Версии: DOS 2.00 и выше. DOS, функция 3Ch Создать файл через описатель

DS:DX – адрес строки ASCIZ с именем файла

CX – атрибут файла (атрибуты приведены в описании функции DOS 43h)

CF=0, если функция выполнена успешно

AX – описатель файла

CF=1, если при выполнении функции возникли ошибки

Описание. Если диск и/или путь не указаны, принимаются значения по умолчанию.

Версии: DOS 2.00 и выше. DOS, функция 3Dh Открыть описатель файла

DS:DX – адрес строки ASCIZ с именем файла

AL – режим открытия:

AL=00h, чтобы открыть для чтения

AL=01h, чтобы открыть для записи

AL=02h, чтобы открыть для чтения и записи

CF=0, если функция выполнена успешно

AX – описатель файла

CF=1, если при выполнении функции возникли ошибки

Описание. Файл открывается в выбранном режиме доступа (режиме открытия). Если диск и/или путь не указаны, принимаются указанные по умолчанию. Файл должен существовать. Указатель чтения/записи устанавливается в ноль.

Версии: DOS 2.00 и выше. DOS, функция 3Eh Закрыть описатель файла

BX – описатель файла

CF=0, если функция выполнилась успешно

CF=1, если при выполнении функции возникли ошибки

Описание. BX содержит описатель файла (handle), возвращенный при открытии. Файл, представленный этим описателем, закрывается, его буферы сбрасываются и оглавление обновляется корректными размером, временем и датой. Из-за недостатка описателей файлов (максимум 20, по умолчанию установлено 8), возможно, придется закрыть часть текущих описателей, как, например, описатель 3 (стандартный AUX).

Версии: DOS 2.00 и выше. DOS, функция 3Fh Читать файл через описатель

BX – описатель файла

DS:DX – адрес буфера для чтения данных

CX – число считываемых байт

CF=0, если функция выполнена успешно

AX – число действительно прочитанных байт

CF=1, если при выполнении функции возникли ошибки

Описание. CX байт данных считываются из файла или устройства с описателем, указанным в BX. Данные читаются с текущей позиции указателя чтения/записи файла и помещаются в буфер вызывающей программы, адресуемый через DS:DX. Если необходимо установить позицию чтения/записи, можно использовать функцию 42h. Эта функция обновляет указатель чтения/записи файла, чтобы подготовиться к последующим операциям чтения или записи.

Версии: DOS 2.00 и выше. DOS, функция 40h Писать в файл через описатель

BX – описатель файла

DS:DX – адрес буфера, содержащего записываемые данные

CX – число записываемых байт

CF=0, если функция выполнена успешно

AX – число действительно записанных байт

CF=1, если при выполнении функции возникли ошибки

Описание. CX байт данных записываются в файл или на устройство с описателем, заданным в BX. Данные берутся из буфера, адресуемого через DS:DX, и записываются, начиная с текущей позиции указателя чтения/записи файла. Чтобы установить указатель файла, если необходимо, можно использовать функцию 42h. Обновляет указатель чтения/записи файла, чтобы подготовиться к последующим операциям чтения или записи.

Версии: DOS 2.00 и выше. DOS, функция 41h Удалить файл

DS:DX – адрес строки ASCIZ с именем файла

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

Описание. Файл удаляется из оглавления заданного диска. Если диск и/или путь не указаны, принимаются значения по умолчанию. Имя файла не может содержать обобщенные символы («?» и «*»). Если файл имеет атрибут «только чтение», то перед удалением необходимо изменить этот атрибут через функцию 43h.

Версии: DOS 2.00 и выше. DOS, функция 42h Переместить указатель файла

BX – описатель файла

CX:DX на сколько передвинуть указатель: (CX*65536)+DX

AL=00h переместить относительно начала файла +CX:DX

AL=01h переместить относительно текущей позиции +CX:DX

AL=02h переместить относительно конца файла +CX:DX

CF=0, если функция выполнена успешно

DX:AX новая позиция указателя файла (если нет ошибки)

CF=1, если при выполнении функции возникли ошибки

Описание. Перемещает логический указатель чтения/записи к нужной позиции. Очередная операция чтения или записи начнется с этого адреса.

Вызов с AL=2, CX=0, DX=0 возвращает длину файла в DX:AX.

Действительная длина файла равна (DX*65536)+AX.

Версии: DOS 2.00 и выше. DOS, функция 43h Установить/опросить атрибуты файла

DS:DX – адрес строки ASCIZ с именем файла

AL=00h – извлечь текущий атрибут файла

AL=01h – установить атрибут файла

CX – новый атрибут файла (для подфункции 01h)(Таблица Б-9)

CF=0, если функция выполнена успешно

CX – текущий атрибут файла (для подфункции 00h)(Таблица Б-9)

CF=1, если при выполнении функции возникли ошибки

Таблица Б-9. Атрибуты файла

Атрибут файла читается или устанавливается, согласно коду в AL. Если диск и/или путь не указаны, принимаются значения по умолчанию.

Примечание. Чтобы скрыть оглавление, нужно использовать CX=02h (а не 12h, как можно было ожидать).

Версии: DOS 2.00 и выше. DOS, функция 44h Управление устройством ввода/вывода

AL – код подфункции:

AL=00h – получить информацию об устройстве

AL=01h – установить информацию об устройстве

AL=02h – читать с символьного устройства

AL=03h – писать на символьное устройство

AL=04h – читать с блочного устройства

AL=05h – писать на блочное устройство

AL=06h – дать статус ввода

AL=07h – дать статус вывода

AL=08h – запрос съемного носителя

AL=09h – запрос удаленного устройства

AL=0Ah – запрос удаленного описателя

AL=0Bh – счет повторов разделения

AL=0Ch – кодовые страницы 3.3

AL=0Dh – общий IOCTL

AL=0Eh – получить логическое устройство

AL=0Fh – установить логическое устройство

Версии: DOS 2.00 и выше. DOS, функция 45h Дублировать описатель файла

BX – существующий описатель файла

CF=0, если функция выполнена успешно

AX – новый описатель файла, дублирующий оригинал

CF=1, если при выполнении функции возникли ошибки

Описание. Создает дополнительный описатель файла, ссылающийся на тот же поток ввода/вывода, что и существующий описатель. Любое продвижение указателя чтения/записи одного описателя (включая любые операции чтения, записи или перемещения указателя посредством функции 42h) действует на его дубликат.

Версии: DOS 2.00 и выше. DOS, функция 46h Переназначить описатель

BX – целевой описатель файла (должен уже существовать)

CX – исходный описатель файла (должен уже существовать)

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

Описание. Заставляет описатель файла (handle) ссылаться на другой файл или устройство. Если описатель в CX (источник) открыт, он закрывается, а затем становится дубликатом описателя в BX (назначения). Иными словами, описатели в CX и BX будут ссылаться на один и тот же физический файл или устройство.

Версии: DOS 2.00 и выше. DOS, функция 47h Получить текущее оглавление DOS

DS:SI – адрес локального буфера для результирующего пути – 64 байта

DL – номер диска (0 – текущий, 1 – A и так далее)

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

Описание. В буфер по адресу DS:SI помещается в форме ASCIZ путь текущего оглавления для диска, указанного в DL. Путь возвращается в формате: «путь\оглавление»,0. Впереди не подставляется буква диска, а сзади не подставляется символ «\». Например, если текущим является корневое оглавление, эта функция вернет пустую строку (DS: [SI]=0).

Версии: DOS 2.00 и выше. DOS, функция 48h Выделить память

BX – запрошенное количество памяти в 16-байтных параграфах

CF=0, если функция выполнена успешно

AX – сегментный адрес распределенного блока

CF=1, если при выполнении функции возникли ошибки

BX – размер максимального доступного блока памяти (в параграфах)

Описание. Распределяет блок памяти длиной BX параграфов, возвращая сегментный адрес этого блока в AX (блок начинается с AX:0000). Если распределение неудачно, устанавливается флаг CF, в AX возвращается код ошибки, а BX содержит максимальный размер доступной для распределения памяти (в параграфах). Чтобы определить наибольший доступный блок, общепринято устанавливать BX=FFFFh перед вызовом. Распределение завершится с ошибкой, возвратив размер максимального блока памяти в BX.

Версии: DOS 2.00 и выше. DOS, функция 49h Освободить блок памяти

ES – сегментный адрес освобождаемого блока памяти

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

Описание. Освобождает блок памяти, начинающийся с адреса ES:0000. Этот блок становится доступным для других запросов системы. Вообще говоря, нужно освобождать лишь те блоки памяти, которые получены через функцию 48h (распределить память). Родитель отвечает за освобождение памяти порожденных процессов. Тем не менее, ничто не препятствует освобождать память чужих процессов.

Версии: DOS 2.00 и выше. DOS, функция 4Ah Изменить размер блока памяти

ES – сегмент распределенного блока памяти

BX – нужный размер блока в 16-байтных параграфах

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

BX – размер максимального доступного блока памяти (в параграфах)

Описание. Изменяет размер существующего блока памяти. Когда программа получает управление, функция 4Bh уже распределила блок памяти, начиная с PSP, который содержит всю доступную память. Чтобы освободить память для запуска порождаемых процессов, блок памяти, начинающийся с PSP, необходимо сначала сжать.

Функция 31h и INT 27h (TSR) сжимают блок по адресу PSP.

Версии: DOS 2.00 и выше.

DOS, функция 4Bh Выполнить или загрузить программу

DS:DX – адрес строки ASCIZ с именем файла, содержащего программу

ES:BX – адрес EPB (блока параметров EXEC)

AL=00h – загрузить и выполнить

AL=01h – загрузить, но не выполнять

AL=03h – загрузить программный оверлей

CF=0, если функция выполнена успешно

BX, DX не сохранены

CF=1, если при выполнении функции возникли ошибки

Описание. Данная функция загружает в память и запускает программу, имя которой указано в регистрах DS:DX. Запущенная программа после завершения работы возвратит управление запускаемой. Если диск или путь не указаны, принимаются значения по умолчанию. ES:BX указывает на блок памяти, подготовленный как EPB, формат которого зависит от запрошенной подфункции в AL.

Версии: DOS 2.00 и выше. DOS, функция 4Ch Завершить программу

Описание. Возвращает управление от порожденного процесса его родителю, устанавливая код выхода (его можно опросить функцией 4Dh). Управление передается по адресу завершения в PSP завершающейся программы. Векторы Ctrl-Break и Critical Error восстанавливаются к старым адресам, сохраненным в родительском PSP.

Примечание. Значение ERRORLEVEL (используемое в пакетных файлах DOS) можно использовать для проверки кода выхода самой последней программы.

Версии: DOS 2.00 и выше. DOS, функция 4Dh Получить код выхода программы

AH – код выхода последнего завершившегося процесса

AH=00h – нормальное завершение

AH=01h – завершение через Ctrl-Break INT 23h

AH=02h – завершение по критической ошибке устройства INT 24h

AH=03h – завершение через функцию 31h

Описание. Возвращает код выхода последнего из завершившихся процессов. Эта функция возвращает правильную информацию только однажды для каждого завершившегося процесса.

Версии: DOS 2.00 и выше. DOS, функция 4Eh Найти первый совпадающий файл

DS:DX – адрес строки ASCIZ с именем файла (допускается использовать символы «?» и «*»)

CX – атрибут файла для сравнения

CF=0, если функция выполнена успешно

DTA заполнена данными (Таблица Б-10)

CF=1, если при выполнении функции возникли ошибки

Описание. Если диск и/или путь не указаны, принимаются значения по умолчанию. Обобщенные символы «*» и «?» допускается использовать в имени файла и расширении.

Версии: DOS 2.00 и выше. DOS, функция 4Fh Найти следующий совпадающий файл

DS:DX – адрес данных, возвращенных предыдущей 4Eh (Найти первый файл)

Таблица Б-10. Формат данных в DTA

CF=0, если функция выполнена успешно

DTA заполнена данными

CF=1, если при выполнении функции возникли ошибки

Описание. Эту функцию можно использовать после вызова 4Eh. Следующее имя файла, совпадающее по обобщенному имени и атрибуту файла, копируется в буфер по адресу DS:DX вместе с другой информацией (Таблица Б-10).

Примечание. Параметр DS:DX добавлен в DOS 3.0.

Версии: DOS 2.00 и выше. DOS, функция 52h Получить адрес векторной таблицы связи (Официально не документирована)

Выход: ES:BX – адрес векторной таблицы связи (Таблица Б-11)

Описание. Данная функция возвращает адрес векторной таблицы связи.

Версии: DOS 2.00 и выше. DOS, функция 54h Получить переключатель верификации DOS

AL=00h, если верификация выключена (OFF)

AL=01h, если верификация включена (ON)

Описание. Возвращает текущий статус верификации записи DOS. Если в AL возвращается 1, то DOS считывает обратно каждый сектор, записываемый на диск, чтобы проверить правильность записи. Функция DOS 2Eh позволяет установить/изменить режим верификации.

Версии: DOS 2.00 и выше. Таблица Б-11. Формат векторной таблицы связи

DOS, функция 56h Переименовать/переместить файл

DS:DX – адрес старого ASCIZ имени (путь/имя существующего файла)

ES:DI – адрес нового ASCIZ имени (новые путь/имя)

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

Описание. Старое имя DS:DX должно существовать и не может содержать обобщенных символов. Диск и путь необязательны (если они не указаны, принимаются значения по умолчанию). Новое имя ES:DI должно описывать несуществующий файл. Если указан диск, он должен быть тем же, что и в старом имени. Если диск или путь не указаны, принимаются текущие. Если старое и новое имя содержат разные пути (явные или принятые по умолчанию), то элемент оглавления для файла перемещается в оглавление, указанное в новом имени.

Версии: DOS 2.00 и выше. DOS, функция 57h Установить/опросить дату/время файла

AL=00h – получить дату/время файла

AL=01h – установить дату/время файла

BX – описатель файла (handle)

CX (если AL=1) – новая отметка времени в формате время файла

DX (если AL=1) – новая отметка даты в формате дата файла

CF=0, если функция выполнена успешно

CX – (если при вызове AL=0) отметка времени файла в формате время/дата файла (Таблица Б-12)

Таблица Б-12. Формат времени файла

DX – (если при вызове AL=0) отметка даты файла в формате время/дата файла (Таблица Б-13)

Таблица Б-13. Формат даты файла

CF=1, если при выполнении функции возникли ошибки

Описание. BX должен содержать описатель открытого файла (см. 3Ch или 3Dh). DX и CX задаются в формате памяти (например, младшие 8 бит даты находятся в DH).

Версии: DOS 2.00 и выше. DOS, функция 59h Получить расширенную информацию об ошибке

BX=0000h (номер версии: 0000h для DOS 3.0, 3.1 и 3.2)

AX – расширенный код ошибки (0, если ошибки не было)

BH – класс ошибки

BL – предлагаемое действие

CH – сфера (где произошла ошибка)

Описание. Эту функцию можно использовать, чтобы уточнить, что предпринять после сбоя функции DOS по ошибке (только DOS 3.0+). Ее можно вызывать: в обработчике критических ошибок INT 24h, после любой функции INT 21h, возвратившей флаг переноса после вызова FCB-функции, возвратившей AL=FFh.

Версии: DOS 3.00 и выше. DOS, функция 5Ah Создать уникальный временный файл

DS:DX – адрес строки ASCIZ с диском и путем (заканчивается символом «\»)

CX – атрибут файла

CF=0, если функция выполнена успешно

AX – описатель файла

DS:DX – (не изменяется) полное ASCIZ-имя нового файла

CF=1, если при выполнении функции возникли ошибки

Описание. Открывает (создает) файл с уникальным именем в каталоге, заданном строкой ASCIZ, на которую указывает DS:DX. COMMAND.COM вызывает эту функцию, когда создает временные «канальные» файлы, используемые при переназначении ввода-вывода. Описание пути должно быть готово к добавлению в его конец имени файла. Необходимо обеспечить минимум 12 байт в конце строки. Сама строка должна быть заполнена в одной из форм: «^: \путь\»,0 (указан диск и путь), «d:»,0 (текущее оглавление диска) или «d: \»,0 (корневое оглавление диска).

Версии: DOS 3.00 и выше. DOS, функция 5Bh Создать новый файл

DS:DX – адрес строки ASCIZ с именем файла

CX – атрибут файла

CF=0, если функция выполнена успешно

AX – описатель файла

CF=1, если при выполнении функции возникли ошибки

Описание. Файл открывается для чтения/записи в совместимом режиме доступа. Если диск и/или путь не указаны, принимаются значения по умолчанию. Этот вызов идентичен функции DOS 3Ch с тем исключением, что он вернет ошибку, если файл с заданным именем уже существует.

Версии: DOS 3.00 и выше. DOS, функция 5Ch Блокировать/разблокировать доступ к файлу

AL=00h – заблокировать область файла

AL=01h – разблокировать ранее заблокированную область

BX – описатель файла

CX:DX – смещение ((CX*65536)+DX) от начала файла

SI:DI – длина блокируемой области ((SI*65536)+DI) байт

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

Описание. Блокирует или освобождает доступ к участку файла, указанного в BX. Область файла с логическим смещением CX:DX и длиной SI:DI блокируется (захватывается) или разблокируется (освобождается). Смещение и длина обязательно должны быть указаны. Разделение файлов должно быть активизировано (командой SHARE), иначе функция вернет код ошибки «Неверный номер функции».

Версии: DOS 3.00 и выше (при обязательной загрузке SHARE). DOS, функция 62h Получить адрес PSP

Выход: BX – сегментный адрес PSP выполняющейся программы

Описание. Эта функция возвращает в BX адрес PSP текущей программы. Используется, для получения адреса параметров командной строки, адреса окружения DOS и другой полезной информации, содержащейся в PSP.

Версии: DOS 3.00 и выше. DOS, функция 65h Получить расширенную информацию страны

AL=01h – дать расширенную информацию страны DOS 3.3

AL=02h – дать таблицу преобразования строчных букв в прописные

AL=04h – то же для символов, допустимых в именах файлов

AL=06h – дать сопоставляющую последовательность

BX – кодовая страница (FFFFh – консоль)

CX – размер буфера возврата (должен быть минимум 5 байт)

ES:DI – адрес буфера возврата

CF=0, если функция выполнена успешно

ES:DI – адрес возвращенной информации

CF=1, если при выполнении функции возникли ошибки:

Описание. Эта функция возвращает различную национальную информацию. Используется для получения формата даты, символа валюты и других данных, необходимых для вывода и сортировки информации (во всех странах, кроме США).

Версии: DOS 3.30 и выше. DOS, функция 66h Получить/установить глобальную кодовую страницу

AL=01h – запросить текущую глобальную кодовую страницу

AL=02h – установить активную кодовую страницу

BX – (при AL=02h) кодовая страница (Таблица Б-14)

DX – (при AL=02h) системная кодовая страница (устанавливаемая при загрузке)

CF=0, если функция выполнена успешно

Таблица Б-14. Значения кодовых страниц

BX – (если при вызове AL=01h) текущая активная кодовая страница

DX – (если при вызове AL=01h) системная кодовая страница (устанавливаемая при загрузке)

CF=1, если при выполнении функции возникли ошибки

Описание. Эта функция выбирает новую кодовую страницу или получает значение текущей активной кодовой страницы (страниц). Программа DOS NLSFUNC должна быть загружена до этого вызова. Функция используется в сочетании с 65h или 38h.

Примечание. Устанавливая новую активную кодовую страницу, DOS читает данные из файла COUNTRY.SYS.

Версии: DOS 3.30 и выше. DOS, функция 67h Установить число описателей файлов

BX – максимальное число описателей (до FFFFh)

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

Описание. Эта функция устанавливает максимальное число описателей файлов, которые могут быть открыты одновременно. Если значение BX меньше 20, то принимается 20. Если значение BX меньше текущего максимума (нужно сократить число описателей), и в данный момент открыто более чем BX файлов, то изменение будет иметь место, когда число открытых файлов не будет превышать устанавливаемый максимум. Если BX больше текущего максимума (нужно увеличить число описателей), то DOS должна иметь доступную память, чтобы распределить ее под новые описатели. Функция 4Ah позволяет освободить память, чтобы она стала доступной DOS.

Версии: DOS 3.30 и выше. DOS, функция 68h Завершить файл

BX – описатель завершаемого файла

CF=0, если функция выполнена успешно

CF=1, если при выполнении функции возникли ошибки

Описание. Эта функция заставляет DOS сбросить (записать на диск) буфера основной памяти для указанного описателя файла. DOS обычно избегает обмена с дисками, записывая данные в буфера в основной памяти до заполнения сектора или закрытия файла. Эта функция заставляет DOS немедленно записать данные на диск. Это ускоряет операции с базами данных, позволяя приложению избежать неэффективного закрытия и повторного открытия файлов.

Версии: DOS 3.3 и выше. В версиях DOS от 2.0 до 3.2 можно использовать функцию DOS 45h, чтобы создать и затем закрыть дубликат.

Справочник программиста на персональном компьютере фирмы IBM. Дисковые накопители
Страница 31. Чтение/запись определенных секторов

5.4.2 Чтение/запись определенных секторов.

Чтение или запись определенных секторов диска в основном ис-
пользуется при доступе к каталогам диска или его таблице размеще-
ния файлов, сектора для которых всегда расположены в одном и том
же месте. В то время как чтение секторов достаточно безобидно,
запись абсолютного сектора требует чтобы код был тщательно прове-
рен перед первым использованием. Ошибка может сделать каталог или
таблицу размещения файлов нечитаемыми, что эквивалентно разруше-
нию всех данных на диске.
Как DOS так и BIOS предоставляют функции для чтения и записи
определенных секторов. Однако они указывают сектора по-разному.
Для IBM PC, XT и PCjr процедура BIOS требует информации о номере
стороны (0 или 1), номере дорожки (0-39) и номере сектора (1-8).
Из-за ограничения максимального номера сектора равного 8 этот
метод практически бесполезен для этих машин. Однако для AT номер
сектора может меняться до 8, 9 или 15, а число дорожек может
меняться до 39 или 79. Функции DOS указывают сектор одним номе-
ром, который называется логическим номером сектора. Начиная с
наружного обода диска, секторам присваиваются последовательно
возрастающие номера. Этот метод может быть использован для дисков
произвольного размера и типа.
Отсчет логисеких секторов начинается со стороны 0 дорожки 0
сектора 1 и продолжается на стороне 1 с дорожки 0, после чего
переходит на сторону 0 дорожку 1 и т.д. (На больших фиксированных
дисках сначала проходится весь внешний цилиндр.) В зависимости от
того как был форматирован диск, при переходе на следующую дорожку
логический номер сектора увеличивается на определенную величину.
Для дискет емкостью 360K каждая дорожка (с учетом обеих сторон)
добавляет к логическому номеру 18. Однако вычисления немного
усложняются тем, что отсчет начинается с нуля. Таким образом
первый сектор на дорожке 3 стороны 2 должен иметь номер равный
3*18 для дорожек 0-2 плюс 9 для стороны 0 дорожки 3 плюс единица,
указывающая на первый сектор дорожки 3 стороны 1. Эта сумма равна
64. Логический номер сектора на 1 меньше этого числа. На рис. 5-4
сравнивается методы указания сектора DOS и BIOS.

Высокий уровень.

Бейсик не предоставляет прямого доступа к секторам диска. Надо
использовать следующую процедуру на машинном языке. В приложении
Г объясняется логика взаимодействия с этой процедурой. В примере
читается 9 секторов дорожки 3 стороны 1 дискеты емкостью 360K.
Сама процедура размещается в памяти, начиная с адреса сегмента
&H1000, а содержимое секторов размещается, начиная с сегментного
адреса &H2000 (напоминаем, что абсолютный адрес равен сегментному
адресу, умноженному на 16). Для того чтобы записать на диск со-
держимое этого буфера надо изменить в данных программы седьмой
байт с конца &H25 на &H26. Все остальное остается неизменным.

100 DEFINT A-Z ‘все переменные будут целыми
110 DATA &H55, &H8B, &HEC, &H1E, &H8B, &H76, &H0C, &H8B
120 DATA &H04, &H8B, &H76, &H0A, &H8B, &H14, &H8B, &H76

130 DATA &H08, &H8B, &H0C, &H8B, &H76, &H06, &H8A, &H1C
140 DATA &H8E, &HD8, &H8B, &HC3, &H8B, &H00, &H00, &HCD
150 DATA &H25, &H59, &H1F, &H5D, &HCA, &H08, &H00

160 DEF SEG = &H1000 ‘помещаем процедуру по адресу &H10000
170 FOR N = 0 TO 38 ‘для каждого байта процедуры
180 READ Q: POKE N,Q ‘читаем байт и помещаем его в память
190 NEXT ‘следующий байт
200 READSECTOR = 0 ‘выполняем код, начиная с первого байта
210 BUFFER = &H2000 ‘буфер для данных имеет адрес &H20000
220 LOGICALNUMBER = 62 ‘логический номер сектора равен 62
230 NSECTORS = 9 ‘число считываемых секторов
240 DRIVE = 0 ‘номер накопителя (0 = A)
250 CALL READSECTOR (BUFFER, LOGICALSECTORS, NSECTORS, DRIVE)
260 ‘теперь сектора в памяти, начиная с адреса 2000:0000

Средний уровень.

BIOS использует функцию 2 прерывания 13H для чтения секторов и
функцию 3 прерывания 13H для записи секторов. В обоих случаях DL
должен содержать номер накопителя от 0 до 3, где 0 = A, 1 = B и
т.д., DH — номер головки (стороны), 0-1. CH должен содержать
номер дорожки от 0 до 39, а CL — номер сектора от 0 до 8. AL
содержит число секторов, которое необходимо считать. Допускается
сразу читать не более восьми секторов, что более чем достаточно
для большинства целей. ES:BX должны указывать на начало буфера в
памяти, куда будут помещаться данные или откуда они будут брать-
ся. При возврате AL будет содержать число прочитанных или запи-
санных секторов. Если операция успешна, то флаг переноса будет
равен нулю. Если он равен 1, то AH будет содержать байт статуса
дисковой операции, описанный в [5.4.8].

;—в сегменте данных
BUFFER DB 4000 DUP(?) ;создаем буфер

;—читаем сектора
MOV AX,SEG BUFFER ;ES:BX должны указывать на буфер
MOV ES,AX ;
MOV BX,OFFSET BUFFER ;
MOV DL,0 ;номер накопителя
MOV DH,0 ;номер головки
MOV CH,0 ;номер дорожки
MOV CL,1 ;номер сектора
MOV AL,1 ;число секторов для чтения
MOV AH,2 ;номер функции чтения
INT 13H ;

Прерывания DOS 25H и 26H читают и записывают абсолютные секто-
ра диска, соответственно. Надо поместить логический номер старто-
вого сектора в DX, а DS:BX должны указывать на буфер. CX содержит
число секторов для чтения или записи, а AL — номер накопителя,
где 0 = A, 1 = B и т.д. Процедуры портят все регистры, кроме

сегментных. При возврате регистр флагов остается на стеке, остав-
ляя стек невыровненным. Не забудьте вытолкнуть это значение со
стека сразу после возврата (в примере это значение выталкивается
в CX).

;—в сегменте данных
BUFFER DB DUP 5000(?) ;создаем буфер

;—читаем сектора
PUSH DS ;сохраняем регистры
MOV AX,SEG BUFFER ;DS:BX должны указывать на буфер
MOV DS,AX ;
MOV BX,OFFSET BUFFER ;
MOV DX,63 ;логический номер сектора
MOV CX,9 ;читаем всю дорожку
MOV AL,0 ;накопитель A
INT 25H ;функция чтения секторов
POP CX ;выталкиваем со стека флаги
POP DS ;восстанавливаем регистры
JNC NO_ERROR ;если нет ошибки, то на продолжение
CMP AH,3 ;проверка возможных ошибок
.
.
NO_ERROR: ;продолжение программы

Если при возврате флаг переноса равен 1, то произошла ошибка и
в этом случае AH и AL содержат два отдельных байта статуса ошиб-
ки. Если AH = 4, то указанный сектор не найден, а если AH = 2, то
диск неверно отформатирован. Если AH = 3, то была попытка записи
на дискету, защищенную от записи. Все остальные значения AH гово-
рят об аппаратной ошибке.

Низкий уровень.

Дисковые операции на низком уровне требуют прямого программи-
рования микросхем контроллера НГМД и прямого доступа к памяти.
Поскольку эти операции взаимосвязаны, то они рассматриваются
вместе в разделе [5.4.1].

Функции dos int 25h/26h: прямая дисковая операция чтения/записи

Представленная ниже страница, лишь часть огромного сайта посвященного различной компьютерной документации, на сайте собрано более 800 мб информации. Если Вы не нашли в этой статье, то что Вы ищите попробуте посмотреть здесь, cпросить на форуме или поискать необходимую Вам информацию в нашем каталоге ссылок сайтов компьтерной тематики.

Если же Вы хотите приобрести бумажную копию представленных здесь
материалов, обращайтесь в наш книжный магазин.

С уважением,
команда разработчиков eManual.ru

2. Логическая структура диска в DOS

До сих пор при работе с дисками мы не обращались за помощью к DOS, выполняя все дисковые операции либо на уровне команд ввода/вывода, либо на уровне функций BIOS. Операционная система предоставляет намного более удобные средства для работы с диском, чем обращение к отдельным секторам по их номеру, номерам дорожки и головки. К сожалению, некоторые операции можно выполнить только с помощью функций BIOS или даже только с помощью непосредственного программирования контроллера дисковода.

Если возможности DOS по обслуживанию диска вас устраивают, то лучше пользоваться именно функциями DOS — вам не придется заботиться о многих мелочах и вы будете застрахованы от некоторых ошибок. Есть и другие причины предпочтительного использования функций DOS — ваша программа будет меньше зависеть от типа и конфигурации конкретной машины, так как дисковые драйверы DOS скроют от вас многие детали и особенности конкретной системы.

Мы будем изучать возможности DOS по управлению дисковой подсистемой от простых функций ко все более сложным, постепенно вводя все необходимые определения.

Персональный компьютер обычно комплектуется одним или двумя НМД. Однако операционная система позволяет вам разбивать НМД на части, причем каждая часть будет рассматриваться DOS как отдельный, «логический» диск.

Зачем нужно разбивать диск на логические диски?

Первые персональные компьютеры IBM PC были укомплектованы только НГМД. Дискеты позволяют хранить относительно небольшие объемы информации, поэтому делить флоппи-диск на части не имеет смысла. Следующая модель компьютера — IBM XT- имела жесткий диск объемом 10 или 20 мегабайт. Диск объемом 20 мегабайтов имели и некоторые экземпляры IBM AT. При использовании таких дисков и операционных систем MS-DOS версий до 3.20 у пользователей не возникало никаких проблем и желания разбить диск относительно малого объема на еще меньшие части.

Проблемы возникли, когда производители НМД освоили выпуск дисков объемом 40 мегабайтов и больше. Оказалось, что используемый DOS механизм 16-ти разрядной адресации секторов не позволяет использовать диски объемом, большим, чем 32 мегабайта.

Операционная система MS-DOS версии 3.30 предложила некоторый выход из создавшегося положения. С помощью утилиты FDISK можно было разбить физический диск на логические, каждый из которых не должен превышать по объему 32 мегабайта.

Впоследствии в версиях 4.00 MS-DOS и 3.31 COMPAQ DOS указанное выше ограничение на размер логического диска было снято, однако схема разделения физического диска на логические полностью сохранилась. Существуют и другие причины, по которым может быть полезно разделение большого диска на части:

  • В случае повреждения логического диска пропадает только та информация, которая находилась на этом логическом диске.
  • Реорганизация и выгрузка диска маленького размера проще и быстрее, чем большого.
  • Возможно разделение дискового пространства между отдельными пользователями персонального компьютера. Такая практика «коллективной» работы на персональном компьютере очень распространена.
  • При использовании специальных утилит для разбиения диска на части (диск-менеджеров) возможна установка для отдельных логических дисков защиты от записи. Вы можете записывать на такие диски неизменяющуюся информацию. Вред от программ-вирусов также будет меньше — вирус не сможет записать себя на защищенный диск.
  • Один диск может содержать несколько различных операционных систем, расположенных в разных разделах диска. В ходе начальной загрузки вы можете указать раздел диска, из которого должна производиться загрузка операционной системы.

По своей внутренней структуре логический диск полностью соответствует дискете, поэтому сначала мы изучим логическую структуру жесткого диска, затем сделаем некоторые замечания, касающиеся дискет.

Самый первый сектор жесткого диска (сектор 1, дорожка 0, головка 0) содержит так называемую главную загрузочную запись (Master Boot Record). Эта запись занимает не весь сектор, а только его начальную часть. Сама по себе главная загрузочная запись является программой. Эта программа во время начальной загрузки операционной системы с жесткого диска помещается по адресу 7C00:0000 , после чего ей передается управление. Загрузочная запись продолжает процесс загрузки операционной системы.

В конце самого первого сектора жесткого диска располагается таблица разделов диска (Partition Table). Эта таблица содержит четыре элемента, описывающих максимально четыре раздела диска. В последних двух байтах сектора находится число 55AA . Это признак таблицы разделов.

Для просмотра и изменения содержимого таблицы разделов жесткого диска используется утилита DOS FDISK , или аналогичная утилита другой операционной системы.

Что представляет из себя элемент таблицы разделов диска?

Это структура размером 16 байтов, описывающая часть диска, называемую разделом. В структуре описаны границы раздела в терминах номеров сектора, дорожки и головки, там располагается информация о размере раздела в секторах и о назначении раздела. Разделы диска могут быть активными, активный раздел может быть использован для загрузки операционной системы. Заметьте, что диск может содержать одновременно несколько активных разделов, которые могут принадлежать разным операционным системам.

Приведем формат первого сектора жесткого диска:

Смещение Размер Содержимое
(+0) 1BEh Загрузочная запись — программа, которая загружается и выполняется во время начальной загрузки операционной системы
(+1BEh) 10H Элемент таблицы разделов диска
(+1CEh) 10H Элемент таблицы разделов диска
(+1DEh) 10H Элемент таблицы разделов диска
(+1EEh) 10H Элемент таблицы разделов диска
(+1FEh) 2 Признак таблицы разделов — 55AAh

Все элементы таблицы разделов диска имеют одинаковый формат:

Смещение Размер Содержимое
(+0) 1 Признак активного раздела:
0 — раздел не активный;
80h — раздел активный.
(+1) 1 Номер головки для начального сектора раздела.
(+2) 2 Номер сектора и цилиндра для начального сектора раздела в формате функции чтения сектора INT 13h.
(+4) 1 Код системы:
0 — неизвестная система;
1, 4 — DOS;
5 — расширенный раздел DOS.
(+5) 1 Номер головки для последнего сектора раздела.
(+6) 2 Номер сектора и цилиндра для последнего сектора раздела в формате функции чтения сектора INT 13h.
(+8) 4 Относительный номер сектора начала раздела.
(+12) 4 Размер раздела в секторах.

В самом первом секторе активного раздела расположена загрузочная запись (Boot Record), которую не следует путать с главной загрузочной записью (Master Boot Record). Загрузочная запись считывается в оперативную память главной загрузочной записью, после чего ей передается управление. Загрузочная запись и выполняет загрузку операционной системы.

Таким образом, загрузка операционной системы с жесткого диска — двухступенчатый процесс. Вначале модули инициализации BIOS считывают главную загрузочную запись в память по адресу 7C00:0000 и ей передается управление. Главная загрузочная запись просматривает таблицу разделов и находит активный раздел. Если активных разделов несколько, на консоль выводится сообщение о необходимости выбора активного раздела для продолжения загрузки.

После того как активный раздел найден, главная загрузочная запись считывает самый первый сектор раздела в оперативную память. Этот сектор содержит загрузочную запись, которой главная загрузочная запись и передает управление.

Загрузочная запись активного раздела выполняет загрузку операционной системы, находящейся в активном разделе.

Такой двухступенчатый метод загрузки операционной системы необходим по той причине, что способ загрузки зависит от самой операционной системы, поэтому каждая операционная система имеет свой собственный загрузчик. Фиксированным является только расположение загрузочной записи — самый первый сектор активного раздела.

Расскажем подробнее о некоторых полях элемента таблицы раздела диска.

Байт со смещением 0, как мы уже говорили, является флагом активного раздела и может принимать одно из двух значений — 0 или 80h соответственно для неактивного и активного разделов диска.

Двухбайтовое слово, расположенное со смещением 8 , содержит относительный номер первого сектора раздела. Как он вычисляется?

Значение 0 соответствует дорожке 0 , головке 0 , сектору 1 . При увеличении относительного номера сектора вначале увеличивается номер сектора на дорожке, затем номер головки, и, наконец, номер дорожки. Для вычисления относительного номера сектора можно использовать следующую формулу:

Замечание, касающееся границ разделов диска: обычно разделы начинаются с четных номеров дорожек, за исключением самого первого раздела. Этот раздел может начинаться с сектора 2 нулевой дорожки (головка 0 ), так как самый первый сектор диска занят главной загрузочной записью.

Байт со смещением 4 — это код системы, использующей раздел диска. Для DOS зарезервированы значения 0, 1, 4, 5 .

Значение 0 соответствует неиспользуемому разделу диска.

Если код системы в элементе таблицы раздела равен 1 или 4 , это означает, что раздел используется DOS в качестве первичного раздела (Primary Partition). Первичный раздел используется DOS как логический диск. Этот раздел обычно является активным и из него выполняется загрузка операционной системы. В зависимости от того, какой код системы используется для обозначения первичного раздела DOS (1 или 4) меняется одна из характеристик логического диска — размер элемента таблицы размещения файлов ( FAT ). Код 1 используется для обозначения 12-битовой FAT , 4 — для 16 -битовой FAT . Таблица размещения файлов будет описана ниже в этой главе.

Значение кода системы, равное 5 , обозначает расширенный раздел DOS (Extended DOS Partiton).

Нетрудно заметить, что даже используя все элементы таблицы разделов для создания логических дисков, невозможно создать более четырех дисков. А что делать с винчестерами объемом 300 или 700 мегабайтов? Использование расширенного раздела DOS позволит вам создать любое количество логических дисков. Все эти диски будут располагаться в пределах одного расширенного раздела.

Утилита MS-DOS FDISK позволяет вам создать один первичный раздел DOS и один расширенный раздел. Первичный раздел должен быть активным, он используется как диск С: и из него выполняется загрузка операционной системы. Расширенный раздел разбивается утилитой на логические диски D:, E: и т.д. Расширенный раздел не может быть активным, следовательно, невозможно выполнить загрузку операционной системы с логических дисков, расположенных в этом разделе.

Если в элементе таблицы разделов байт кода системы имеет значение 5 , то в начале раздела, указанном в этом элементе, располагается сектор, содержащий таблицу логических дисков. Фактически эта таблица является расширением таблицы разделов диска, расположенной в самом первом секторе физического диска. Таблица логических дисков имеет формат, аналогичный таблице разделов диска, но имеет только два элемента. Один из них указывает на первый сектор логического диска DOS, он имеет код системы 1 или 4 . Второй элемент может иметь код системы, равный 5 или 0 . Если этот код равен 5 , то элемент указывает на следующую таблицу логических дисков. Если код системы равен 0 , то соответствующий элемент не используется.

Из сказанного выше следует, что таблицы логических дисков связаны в список, на начало этого списка указывает элемент таблицы разделов диска с кодом системы, равным 5 .

Для таблицы логических дисков имеется отличие в использовании полей границ логических дисков: если код системы равен 1 или 4 , эти границы вычисляются относительно начала расширенного раздела; для элемента с кодом системы 5 используется абсолютная адресация (относительно физического начала диска).

Приведем конкретный пример. Пусть на диске создано два раздела — первичный и расширенный. Первичный раздел используется для загрузки MS-DOS (диск С: ), расширенный раздел содержит логические диски D:, E:, F: . На рисунке показано расположение разделов на диске:

Операционная система не предоставляет программам никаких средств для работы с главной загрузочной записью и таблицей разделов диска. Мы постараемся восполнить этот недостаток, подготовив свои функции для работы с этими данными.

Файл sysp.h содержит определения типов для главной загрузочной записи и таблицы разделов диска:

Для того, чтобы прочитать главную загрузочную запись для одного из установленных в компьютере НМД, вы можете использовать следующую функцию:

Как пример использования этой функции приведем текст программы, определяющей количество установленных в системе дисков и выводящей на экран для каждого диска содержимое таблицы разделов. В программе используется функция disk_cfg() , определяющая конфигурацию дисковой подсистемы.

Самый первый сектор логического диска (и самый первый сектор на системной дискете) занимает загрузочная запись (Boot Record). Эта запись считывается из активного раздела диска программой главной загрузочной записи (Master Boot Record) и запускается на выполнение. Задача загрузочной записи — выполнить загрузку операционной системы. Каждый тип операционной системы имеет свою загрузочную запись. Даже для разных версий одной и той же операционной системы программа загрузки может выполнять различные действия.

Кроме программы начальной загрузки операционной системы в загрузочной записи находятся параметры, описывающие характеристики данного логического диска. Все эти параметры располагаются в самом начале сектора, в его так называемой форматированной области. Формат этой области разный для DOS версий до 4.0 и версии 4.0.

Сначала приведем формат записи BOOT для DOS версий, более ранних, чем 4.0.

Смещение Размер Содержимое
(+0) 3 Команда JMP xxxx — переход типа NEAR на программу начальной загрузки
(+3) 8 Название фирмы-производителя операционной системы и версия, например: «IBM 5.0»
(+11) 13 BPB — блок параметров BIOS BIOS
(+24) 2 Количество секторов на дорожке
(+26) 2 Количество головок (поверхностей диска)
(+28) 2 Количество скрытых секторов, эти сектора могут использоваться для схемы разбиения физического диска на разделы

В самом начале BOOT -сектора располагается команда внутрисегментного перехода JMP . Она нужна для обхода форматированной зоны сектора и передачи управления загрузочной программе, располагающейся со смещением (+30).

Название фирмы-производителя не используется операционной системой.

Со смещением (+11) располагается BPB — блок параметров BIOS, о котором мы уже говорили в разделах книги, посвященных драйверам. Этот блок содержит некоторые характеристики логического диска, о которых мы будем говорить немного позже и используется дисковыми драйверами. Для DOS версий до 4.0 BPB имеет следующий формат:

(0) 2 sect_siz Количество байтов в одном секторе диска.
(+2) 1 clustsiz Количество секторов в одном кластере.
(+3) 2 res_sect Количество зарезервированных секторов.
(+5) 1 fat_cnt Количество таблиц FAT.
(+6) 2 root_siz Максимальное количество дескрипторов файлов, содержащихся в корневом каталоге диска.
(+8) 2 tot_sect Общее количество секторов на носителе данных (в разделе DOS).
(+10) 1 media Байт-описатель среды носителя данных.
(+11) 2 fat_size Количество секторов, занимаемых одной копией FAT.

Поля BOOT -сектора со смещениями 24 и 26 содержат соответственно количество секторов на дорожке и количество головок в дисководе. Поле со смещением 28 содержит количество «скрытых» секторов, которые не принадлежат ни одному логическому диску. Эти сектора могут содержать основную или вторичные таблицы разделов диска.

Для MS-DOS версии 4.0 BOOT -сектор имеет другой формат:

Смещение Размер Содержимое
(+0) 3 Команда JMP xxxx — переход типа NEAR на программу начальной загрузки
(+3) 8 Название фирмы-производителя операционной системы и версия, например: «IBM 4.0»
(+11) 25 Extended BPB — расширенный блок параметров BIOS BIOS
(+36) 1 Физический номер дисковода (0 -флоппи, 80h — жесткий диск)
(+37) 1 Зарезервировано
(+38) 1 Символ ‘)’ — признак расширенной загрузочной записи DOS 4.0
(+39) 4 Серийный номер диска (Volume Serial Number), создается во время форматирования диска
(+43) 11 Метка диска (Volume Label)
(+54) 8 Зарезервировано, обычно содержит запись типа ‘FAT12 ‘, которая идентифицирует формат таблицы размещения файлов FAT

Первые два поля в BOOT -секторе для DOS 4.0 аналогичны описанным раньше.

Поле со смещением (+38) всегда содержит символ ‘)’. Этот символ означает, что используется формат расширенной загрузочной записи операционной системы MS-DOS 4.0.

Серийный номер диска формируется во время форматирования диска на основе даты и времени форматирования. Это поле может быть использовано для определения факта замены диска в дисководе.

Метка диска формируется при форматировании и может быть изменена командой операционной системы LABEL . Одновременно метка диска помещается в корневой каталог.

Поле со смещением 11 содержит расширенный блок параметров BIOS. Он состоит из обычного BPB и дополнительного расширения:

(0) 2 sect_siz Количество байтов в одном секторе диска.
(+2) 1 clustsiz Количество секторов в одном кластере.
(+3) 2 res_sect Количество зарезервированных секторов.
(+5) 1 fat_cnt Количество таблиц FAT.
(+6) 2 root_siz Максимальное количество дескрипторов файлов, содержащихся в корневом каталоге диска.
(+8) 2 tot_sect Общее количество секторов на носителе данных (в разделе DOS).
(+10) 1 media Байт-описатель среды носителя данных.
(+11) 2 fat_size Количество секторов, занимаемых одной копией FAT.
—- Расширение стандартного BPB ——
(+13) 2 sectors Количество секторов на дорожке
(+15) 2 heads Количество магнитных головок
(+17) 2 hidden_l Количество скрытых секторов для раздела, который по размеру меньше 32 мегабайтов.
(+19) 2 hidden_h Количество скрытых секторов для раздела, превышающего по размеру 32 мегабайта. (Только для DOS 4.0).
(+21) 4 tot_secs Общее количество секторов на логическом диске для раздела, превышающего по размеру 32 мегабайта.

Как обычный, так и расширенный блок параметров BIOS содержит байт-описатель среды media . Этот байт может служить для идентификации носителя данных и может содержать следующие величины, характеризующие носитель данных по количеству сторон диска и количеству секторов на дорожке:

FFh 2 стороны, 8 секторов на дорожке;
FEh 1 сторона, 8 секторов на дорожке;
FDh 2 стороны, 9 секторов на дорожке;
FCh 1 сторона, 9 секторов на дорожке;
F9h 2 стороны, 15 секторов на дорожке;
F8h жесткий диск.

Мы не будем рассматривать восьмидюймовые дискеты, которые используют значения FEh и FDh байта описателя среды, так как такие дискеты используются крайне редко.

Прежде чем мы продолжим изучение логической структуры диска, покажем, как программа может обратиться к BOOT -сектору.

DOS предоставляет программе возможность работы с так называемыми логическими номерами секторов. Это номера секторов внутри логического диска.

Вы знаете, что для адресации сектора при помощи функций BIOS необходимо указывать номер дорожки, номер головки и номер сектора на дорожке. DOS организует «сквозную» нумерацию секторов, при которой каждому сектору логического диска присваивается свой уникальный номер. Порядок нумерации выбран таким, что при последовательном увеличении номера сектора вначале увеличивается номер головки, затем номер дорожки. Это сделано для сокращения перемещений блока головок при обращении к последовательным логическим номерам секторов.

Пусть, например, у нас есть дискета с девятью секторами на дорожке. Сектор с логическим номером, равным 1, расположен на нулевой дорожке и для обращения к нему используется нулевая головка. Это самый первый сектор на дорожке, в терминах BIOS он имеет номер 1. Следующий сектор на нулевой дорожке имеет логический номер 2, последний сектор на нулевой дорожке имеет логический номер 9. Сектор с логическим номером 10 расположен также на нулевой дорожке. Это тоже самый первый сектор на дорожке, но теперь для доступа к нему используется головка с номером 1. И так далее, по мере увеличения логического номера сектора изменяются номера головок и дорожек.

Для работы с логическим диском (или дискетой) на уровне логических номеров секторов DOS предоставляет программам два прерывания — INT 25h (чтение сектора по его логическому номеру) и INT 26h (запись сектора по его логическому номеру). Вызов этих прерываний имеет различный формат для разных версий DOS. Для тех версий, которые не поддерживают размер логических дисков более 32 М (MS-DOS 3.10, 3.20, 3.30) используется следующий формат:

На входе: AL = Адрес дисковода (0 — A, 1 — B, . )
CX = Количество секторов, которые нужно прочитать
DX = Логический номер начального сектора
DS:BX = Адрес буфера для чтения
На выходе: AH = Код ошибки при неуспешном завершении операции
CF = 1, если произошла ошибка,
0, если ошибки нет

На входе: AL = Адрес дисковода (0 — A, 1 — B, . )
CX = Количество секторов, которые нужно записать
DX = Логический номер начального сектора
DS:BX = Адрес буфера, сожержащего записываемые данные
На выходе: AH = Код ошибки при неуспешном завершении операции
CF = 1, если произошла ошибка,
0, если ошибки нет

Для версий DOS MS-DOS 4.0 и COMPAQ DOS 3.31 используется другой способ задания номера логического сектора. Так как шестнадцати разрядов регистра недостаточно для адресации диска размером более 32М, то при работе с расширенным разделом диска (т.е. с разделом диска, занимающим более 32 мегабайтов) при вызове этих прерываний регистры используются по-другому.

Регистр CX содержит FFFFh — признак того, что работа будет производится с логическим диском, имеющим размер более 32 мегабайтов.

Регистры DS:BX содержат адрес управляющего блока:

(0) 4 Начальный номер логического сектора
(+4) 2 Количество секторов для чтения/записи
(+6) 4 FAR-адрес буфера для передачи данных

Так как для задания начального номера логического сектора в этом управляющем блоке отводится 4 байта, то снимается 32-мегабайтное ограничение на размер логического диска.

Очень важное замечание, касающееся только что рассмотренных прерываний DOS. Эти прерывания оставляют в стеке одно слово — старое значение регистра флагов. Поэтому после вызова прерывания должна следовать, например, такая команда:

Содержимое BOOT -сектора может быть использовано для определения общего количества секторов на логическом диске (например, в программах проверки читаемости секторов диска), для работы с таблицей размещения файлов FAT , о которой мы будем говорить ниже, для определения других характеристик логического диска.

Для работы с загрузочной записью мы подготовили структуры, описывающие расширенный блок параметров BIOS EBPB и собственно загрузочную запись BOOT :

Поле серийного номера диска разбито на две компоненты — volser_lo и volser_hi . Это сделано для облегчения представления серийного номера в виде, аналогичном используемому командой DIR операционной системы MS-DOS 4.0.

Для чтения загрузочной записи логического диска вы можете использовать следующую функцию:

Эта функция используется в следующей программе, показывающей содержимое загрузочной записи для указанного логического диска:

Приведенная выше программа использует функции _fmalloc() и _ffree() соответственно для заказа и освобождения массива памяти. В отличие от широко известных функций malloc() и free() , эти функции используют FAR -указатели на полученную и отдаваемую области памяти.

Сразу после загрузочного сектора на логическом диске находятся сектора, содержащие таблицу размещения файлов FAT (File Allocation Table). В отечественной литературе иногда можно встретить аббревиатуру ТРФ, однако мы будем пользоваться общепринятым сокращением — FAT .

Для того, чтобы назначение этой таблицы стало более понятным, вспомним, как организовано хранение информации на различных носителях данных.

Магнитные ленты. Этот вид носителей информации использовался еще в самых первых ЭВМ. В современных компьютерах магнитные ленты используются для разгрузки магнитных дисков.

При использовании магнитных лент информация записывается в виде файлов с последовательным доступом. Последовательный доступ означает, что для чтения какого-либо файла требуется вначале прочитать все предыдущие файлы. При записи информация может добавляться в конец ленты, после той информации, которая была записана в последний раз.

Если вы попытаетесь перезаписать файл, то это может привести к потере всех файлов, расположенных на магнитной ленте после перезаписываемого.

Доступ к информации, записанной на магнитном диске, может выполняться либо последовательным, либо прямым методом доступа. Использование прямого метода доступа позволяет позиционировать головки сразу на тот файл, который вам нужен (или на нужную запись файла). Например, вы можете задать номер сектора на оперделенной дорожке и номер головки.

Но метод доступа — это еще не все. Важное значение имеет способ распределения места на диске для файлов. От правильного выбора способа распределения зависит эффективность работы программ.

Операционная система ОС ЕС для ЭВМ ряда ЕС позволяет задать начальное количество цилиндров диска для размещения набора данных и размер области диска, которая может быть использована для этого набора дополнительно. Если при записи в файл все распределенное для файла место на диске окажется исчерпанным, программа завершится аварийно, даже если на диске еще есть свободные цилиндры.

Операционные системы, подобные DOS, UNIX, OS/2 используют дисковое пространство другим способом.

В этих операционных системах при создании файла для него не задается начальное распределение памяти в дорожках или секторах. По мере того, как файл увеличивается в размерах, операционная система распределяет этому файлу сектора из числа свободных, не используемых другими файлами. При этом файл располагается не обязательно в смежных областях диска, он может быть разбросан по разным дорожкам и секторам.

Очевидно, что в этом случае операционная система должна вести учет используемых участков диска. Для каждого файла она должна хранить где-то информацию о том, какому файлу какие участки диска распределены.

В операционной системе MS-DOS для хранения этой информации используется таблица размещения файлов.

Весь диск разбивается операционной системой на участки одинакового размера, называемые кластерами. Кластер может содержать несколько секторов. Для каждого кластера FAT имеет свою индивидуальную ячейку, в которой хранится информация об использовании данного кластера. Другими словами, таблица размещения файлов — это массив, содержащий информацию о кластерах. Размер этого массива определяется общим количеством кластеров на логическом диске. (Именно кластеров, а не секторов!).

Что же хранится в таблице размещения файлов?

Все свободные кластеры помечены в ней нулями. Если файл занимает несколько кластеров, то эти кластеры связаны в список. Для связанных в список кластеров элементы таблицы FAT содержат номера следующих используемых данным файлом кластеров. Конец списка отмечен в таблице специальным значением. Номер первого кластера, распределенного файлу, хранится в элементе каталога, описывающего данный файл.

Утилиты операционной системы и некоторые специальные утилиты проверяют диск на предмет наличия дефектных областей. Кластеры, которые находятся в этих дефектных областях, отмечаются в FAT как плохие и не используются операционной системой.

Итак, FAT — массив информации об использовании кластеров диска, содержит односвязные списки кластеров, распределенных файлам. Номера начальных кластеров файлов хранятся в каталогах, о которых мы будем говорит в разделе «Файлы и каталоги». Прежде чем углубляться в тонкости таблицы размещения файлов, приведем рисунок, иллюстрирующий сказанное выше.

На этом рисунке показаны фрагменты корневого каталога диска С: и элементы FAT для файлов autoexec.bat и config.sys . Реально эти файлы не используют столько кластеров. Из рисунка видно, что в каталоге для файлов указаны номера первых кластеров (соответственно 11 и 27). Таблица FAT в одиннадцатой ячейке содержит число 12 — номер следующего кластера, распределенного файлу autoexec.bat . Ячейка с номером 12 содержит число 13, и так далее. Последняя ячейка, соответствующая последнему кластеру распределенному этому файлу, содержит специальное значение — FF . В этом примере все кластеры файлов расположены подряд, но это может быть и не так.

Существуют два формата FAT — 12-битовый и 16-битовый. Эти форматы используют, соответственно, 12 и 16 битов для хранения информации об одном кластере диска.

12-битовый формат удобен для дискет с небольшим количеством секторов — вся таблица размещения файлов помещается целиком в одном секторе. Если размер диска такой, что для представления всех секторов двенадцати разрядов недостаточно, можно увеличить размер кластера, например до восьми секторов. Однако большой размер кластера приводит к неэффективному использованию дискового пространства. Это происходит из-за того, что минимальный выделяемый файлу элемент — кластер — имеет слишком большой размер. Даже для файла, имеющего длину 1 байт выделяется целиком кластер. Значит, если размер кластера составляет 8 секторов, то для хранения одного байта будет использовано 4 килобайта дисковой памяти.

При использовании FAT 16-битового формата операционная система может работать с диском, который имеет размер более 32 мегабайт. DOS версии 4.0 при использовании 16-битового формата FAT и кластеров размером 4 сектора может работать с разделами, по размеру достигающими 134 мегабайтов.

Как программа может определить формат FAT?

Для DOS версии 3.0 16-битовый формат используется, если размер диска превышает 4086 кластеров. Это число получилось исходя из того, что в 12 разрядах может быть представлено максимальное число 4096, кроме того, значения, большие 0ff6 , зарезервированы.

Для DOS версии 3.2 16-битовый формат FAT используется в том случае, когда размер диска превышает 20790 секторов (именно секторов, а не кластеров). Фактически это означает, что 16-битовый формат используется только для дисков, имеющих размер более 10 мегабайтов.

Сектор загрузочной записи ( BOOT -сектор) диска, отформатированного в DOS версии 4.0 в поле со смещением 36h содержит восьмибайтовую строку, идентифицирующую формат FAT . Она имеет вид «FAT12 » или «FAT16 «. Вы можете использовать это поле для определения формата FAT . В структуре BOOT , описанной в файле sysp.h, это поле называетcя fat_format .

Если разделы на жестком диске создавались утилитой DOS FDISK , формат FAT можно определить, анализируя содержимое поля sys главной загрузочной записи (Master Boot Record). Если это поле содержит значение 1, используется 12-битовый формат, если 4 — 16-битовый. Однако диск, подготовленный программами диск-менеджеров, может иметь нестандартный для DOS формат таблицы разделов диска (Partition Table), и поле sys может содержать другие величины, отличные от 1 и 4.

Опишем подробно формат FAT.

Первый байт FAT называется «Описатель среды» (Media Descriptor) или байт ID идентификации FAT . Он имеет такое же значение, как и байт-описатель среды, находящийся в BOOT -секторе логического диска.

Следующие 5 байтов для 12-битового формата или 7 байтов для 16-битового формат всегда содержат значение 0ffh .

Остальная часть FAT состоит из 12-битовых или 16-битовых ячеек, каждая ячейка соответствует одному кластеру диска. Эти ячейки могут содержать следующие значения:

FAT12 FAT16 Что означает
000h 0000h Свободный кластер
ff0h — ff6h fff0h — fff6h Зарезервированный кластер
ff7h fff7h Плохой кластер
ff8h — fffh fff8h — ffffh Последний кластер в списке
002h — fefh 0002h — ffefh Номер следующего кластера в списке

Непосредственный доступ к FAT может потребоваться вам для организации сканирования каталогов для поиска нужных файлов, для чтения каталогов как файлов, для организации защиты информации от несанкционированного копирования. Общая схема использования FAT такая:

  • Читаем FAT целиком в память. Обычно FAT располагается сразу после BOOT -сектора (логический сектор с номером 1). Для точного определения начального сектора FAT следует прочитать в память BOOT -сектор и проанализировать содержимое блока параметров BIOS. В поле ressecs записано количество зарезервированных секторов, которые располагаются перед FAT . Поле fatsize содержит размер FAT в секторах. Кроме того, следует учитывать, что на диске может находиться несколько копий FAT . Операционная система использует только первую копию, остальные нужны для утилит восстановления содержимого диска, таких как CHKDSK . Количество копий FAT находится в поле fatcnt BOOT -сектора.
  • Затем необходимо узнать номер первого кластера файла, для которого необходимо определить его расположение на диске.
  • Используем номер первого кластера как индекс в FAT для извлечения номера следующего кластера.
  • Повторяем предыдущую процедуру до тех пор, пока извлеченное из FAT значение не будет соответствовать концу файла.

Процедура извлечения номера кластера из FAT зависит от формата таблицы размещения файлов.

16-битовую FAT можно представить как массив 16-битовых чисел. Для определения номера следующего кластера вам надо просто извлечь 16-битовое значение из FAT , использовав в качестве индекса номер предыдущего кластера.

Для 12-битовой FAT процедура значительно сложнее. Необходимо выполнить следующие действия:

  • Умножить номер начального кластера на 3.
  • Разделить результат на 2 (так как каждый элемент таблицы имеет длину 1.5 байта).
  • Прочитать 16-битовое слово из FAT , используя в качестве смещения значение, полученное после деления на 2.
  • Если номер начального кластера четный, на выбранное из FAT слово надо наложить маску 0fffh , оставив младшие 12 битов. Если номер начального кластера нечетный, выбранное из FAT значение необходимо сдвинуть вправо на 4 бита, оставив старшие 12 битов.
  • Полученный результат — номер следующего кластера в цепочке, значение 0fffh соответствует концу цепочки кластеров.

Используя описанные выше методики чтения FAT , вы сможете для каждого файла определить цепочку занимаемых им кластеров. Для чтения файла при помощи прерывания DOS INT 25h вам будет нужно установить соответствие между номерами кластеров и номерами секторов, в которых располагаются эти кластеры. Для того чтобы это сделать, необходимо определить расположение и размер корневого каталога. Поэтому следующий раздел книги будет посвящен каталогам и файлам. Там же будут приведены примеры программ для работы с FAT .

Вы, конечно, знаете, что файловая система DOS имеет древовидную структуру. В корневом каталоге располагаются 32-байтовые элементы, которые содержат информацию о файлах и других каталогах. Для чтения корневого каталога необходимо определить его расположение и размер.

Корневой каталог находится сразу за последней копией FAT . Количество секторов, занимаемых одной копией FAT , находится в блоке параметров BIOS в BOOT -секторе в поле fatsize , количество копий FAT — в поле fatcnt блока BPB . Следовательно, перед корневым каталогом находится один BOOT -сектор и (fatcnt_*_fatsize) секторов таблицы размещения файлов FAT .

Размер корневого каталога можно определить исходя из значения поля rootsize . В этом поле при форматировании диска записывается максимальное количество файлов и каталогов, которые могут находиться в корневом каталоге. Для каждого элемента в каталоге отводится 32 байта, поэтому корневой каталог имеет длину (32_*_rootsize) байтов.

Корневой каталог занимает непрерывную область фиксированного размера. Размер корневого каталога задается при форматировании и определяет максимальное количество файлов и каталогов, которые могут быть описаны в корневом каталоге. Для определения количества секторов, занимаемых корневым каталогом, можно воспользоваться следующей формулой:

В этой формуле sectsize — размер сектора в байтах, он может быть получен из соответствующего поля BOOT -сектора.

После корневого каталога на логическом диске находится область файлов и подкаталогов корневого каталога. На рисунке изображены все области логического диска. Такую структуру имеют логические диски, расположенные в разделах жестких дисков, а также дискеты.

Область данных разбита на кластеры, причем нумерация кластеров начинается с числа 2. Кластеру с номером 2 соответствуют первые сектора области данных. Теперь мы можем привести формулу, которая позволит нам связать номер кластера с номерами секторов, занимаемых им на логическом диске:

Этой формулой мы воспользуемся для чтения корневого каталога.

Как мы уже говорили, любой каталог содержит 32-байтовые элементы — дескрипторы, описывающие файлы и другие каталоги. Приведем формат дескриптора:

Смещение Размер Содержимое
(+0) 8 Имя файла или каталога, выравненное на левую границу и дополненное пробелами.
(+8) 3 Расширение имени файла, выравненное на левую границу и дополненное пробелами.
(+11) 1 Атрибуты файла.
(+12) 10 Зарезервировано.
(+22) 2 Время создания файла или время его последней модификации.
(+24) 2 Дата создания файла или дата его последней модификации.
(+26) 2 Номер первого кластера, распределенного файлу.
(+28) 4 Размер файла в байтах.

Байт атрибутов является принадлежностью каждого файла. Биты этого байта имеют следующие значения:

Файл предназначен только для чтения, в этот файл нельзя писать и его нельзя стирать.
1 Скрытый файл, этот файл не будет появляться в списке файлов, создаваемом командой операционной системы DIR.
2 Системный файл. Этот бит обычно установлен в файлах, являющихся составной частью операционной системы.
3 Данный дескриптор описывает метку диска. Для этого дескриптора поля имени файла и расширения имени файла должны рассматриваться как одно поле длиной 11 байтов. Это поле содержит метку диска.
4 Дескриптор описывает файл, являющийся подкаталогом данного каталога.
5 Флаг архивации. Если этот бит установлен в 1, то это означает, что данный файл не был выгружен утилитой архивации (например, программой BACKUP).
6-7 Зарезервированы.

Обычно файлы имеют следующие комбинации битов в байте атрибутов:

Обычные файлы (тексты программ, загрузочные модули, пакетные файлы).
7 Только читаемые, скрытые, системные файлы. Такая комбинация битов байта атрибутов используется для файлов операционной системы IO.SYS, MSDOS.SYS.
8 Метка тома. Дескриптор метки тома может находиться только в корневом каталоге логического диска.
10h Дескриптор, описывающий каталог.
20h Обычный файл, который не был выгружен утилитами BACKUP или XCOPY.

В любом каталоге, кроме корневого, два первых дескриптора имеют специальное назначение. Первый дескриптор содержит в поле имени строку:

Этот дескриптор указывает на содержащий его каталог. Т.е. каталог имеет ссылку сам на себя.

Второй специальный дескриптор содержит в поле имени строку:

Этот дескриптор указывает на каталог более высокого уровня.

Если в поле номера первого занимаемого кластера дескриптора с именем «.. » находится нулевое значение, это означает, что данный каталог содержится в корневом каталоге.

Таким образом, в древовидной структуре каталогов имеются ссылки как в прямом, так и в обратном направлении. Эти ссылки можно использовать для проверки сохранности структуры каталогов файловой системы.

При удалении файла первый байт его имени заменяется на байт E5h (символ ‘х’ ). Все кластеры, распределенные файлу, отмечаются в FAT как свободные. Если вы только что удалили файл, его еще можно восстановить, так как в дескрипторе сохранились все поля, кроме первого байта имени файла. Но если на диск записать новые файлы, то содержимое кластеров удаленного файла будет изменено и восстановление станет невозможным.

Остановимся подробнее на полях времени и даты создания или последней модификации файла. DOS обновляет содержимое этих полей после любой операции, изменяющей содержимое файла — создания файла, перезаписи содержимого файла, добавления данных в файл или обновления содержимого файла. После обновления файла DOS устанавливает бит архивации 5 байта атрибутов в 1.

Формат поля времени показан на рисунке:

Старшие пять битов содержат значение часа модификации файла, шесть битов с номерами 5-10 содержат значение минут модификации файла, и, наконец, в младших 5 битах хранится значение секунд, деленное на 2. Для того, чтобы время обновления файла уместилось в шестнадцати битах, пришлось пойти на снижение точности времени до двух секунд.

Формат даты обновления файла напоминает формат времени:

Для того, чтобы получить значение года обновления файла, необходимо прибавить к величине, хранимой в старших семи битах, значение 1980. Поля месяца и дня каких-либо особенностей не имеют, они полностью соответствуют календарной дате.

Поле длины в дескрипторе содержит точную длину файла в байтах. Для каталогов в поле длины записано нулевое значение. Вы не можете работать с каталогом, как с обычным файлом средствами DOS. Единственный способ прочитать каталог как файл — использовать FAT для определения цепочки занимаемых каталогом кластеров и прочитать сектора, соответствующие этим кластерам при помощи прерывания DOS INT 25h.

Для удобства работы с каталогами файл sysp.h содержит следующие определения типов:

Приведем исходный текст программы, которая читает BOOT -сектор выбранного диска, определяет формат FAT , вычисляет размер и расположение FAT и корневого каталога. Затем программа читает FAT и корневой каталог в динамически получаемые буфера и выводит на экран содержимое корневого каталога.

Запустив программу два раза для диска С: и RAM-диска G: мы получили на экране следующую картину:

Заметьте, что приведенная выше программа предоставляет вам параметр, который невозможно получить с помощью команды операционной системы DIR — номер первого кластера, распределенного файлу. Операционная система MS-DOS не дает программам иной возможности определить номер первого кластера файла, чем чтение каталога по секторам.

Для исследования подкаталогов корневого каталога и для демонстрации основных приемов работы с таблицей размещения файлов FAT предназначена следующая программа. Вы можете использовать ее для исследования структуры каталогов диска.

Эта программа обращается к таблице размещения файлов при помощи функции fat() :

В качестве примера приведем результат работы программы для диска E:

Обратите внимание на выделенные элементы каталога. Это ссылки соответственно на сам каталог и на каталог более высокого уровня.

В этом разделе мы сделаем несколько замечаний, касающихся программ, формирующих логическую структуру дисков.

После низкоуровневого форматирования, формирующего адресные маркеры, маркеры данных и сектора, необходимо создать разделы диска. Операционная система MS-DOS позволяет сделать это с помощью утилиты FDISK . Версия 4.0 MS-DOS и более поздние версии не накладывают ограничений на размер разделов и логических дисков. Однако при использовании утилиты FDISK вы не сможете организовать защиту логических дисков от записи или от несанкционированного доступа.

Программы диск-менеджеров, такие как ADM и SpeedStor , в некоторой степени решают вопросы защиты от записи и несанкционированного доступа. Но появляются новые проблемы.

Диск-менеджеры используют свой собственный механизм разбиения диска на разделы, и, следовательно, логическая структура диска, подготовленного программами диск-менеджеров, отличается от стандартной для MS-DOS. Прежде всего это касается таблицы разделов диска (Partition Table), находящейся в главной загрузочной записи. Элементы таблицы разделов имеют отличный от используемого MS-DOS код системы. Этот код зависит от используемой программы диск-менеджера.

Если ваш диск подготовлен программой SpeedStor , то все элементы таблицы разделов будут заняты (MS-DOS оставляет два элемента неиспользованными). Для того, чтобы установить на этот же диск другую операционную систему (например, XENIX или OS/2) вам придется выгрузить содержимое всего диска на дискеты или стриммер (кассетный накопитель на магнитной ленте), удалить все разделы SpeedStor , создать разделы другой операционной системы, и уже затем разделы MS-DOS. Если бы диск был подготовлен утилитой FDISK , то зарезервировав заранее место для другой операционной системы, вы смогли бы без проблем использовать два оставшихся элемента таблицы разделов.

В таблице разделов диска, подготовленной программой FDISK , находится информация об используемом формате таблицы размещения файлов FAT . Вы можете пользоваться этой информацией, но только в том случае, если диск подготовлен утилитой FDISK .

Из сказанного выше следует, что если работа вашей программы не должна зависеть от того, каким способом были подготовлены разделы диска, вам не следует работать непосредственно с таблицей разделов диска. Для многих приложений, включая защиту от несанкционированного копирования, вам будет достаточно прочитать загрузочный сектор логического диска и воспользоваться той информацией, которая в нем содержится.

Илон Маск рекомендует:  Rss and atom
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL