Начальный сектор жеского диска содержит главную корневую запись, которая загружается в память и выполняется.
Последняя часть этого сектора содержит таблицу разделов - 4-элементную таблицу с 16-байтовыми элементами. Этой таблицей манипулирует программа FDISK (или эквивалентная утилита в иной операционной системе).
Во время загрузки ROM-BIOS загружает главную корневую запись и передает управление на ее код. Этот код считывает таблицу разделов, чтобы определить раздел, помеченный как активный. Затем в память считывается корректный корневой сектор и выполняется.
Таблица 1. Структура главной корневой записи и таблицы разделов
Смещение | Длина | Содержимое |
---|---|---|
000h | 446 | Корневая запись (MSB) |
1BEh | 16 | Описатель раздела 1 (см. табл.2) |
1CEh | 16 | Описатель раздела 2 |
1DEh | 16 | Описатель раздела 3 |
1EEh | 16 | Описатель раздела 4 |
1FEh | 2 | Подпись таблицы разделов (значение AA55h) |
Таблица 2. Структура описателя раздела
Смещение | Длина | Содержимое |
---|---|---|
00h | 1 | Признак активности раздела (0 - не активен, 80h - активен) |
01h | 1 | Номер поверхности диска, с которой начинается раздел |
02h | 2 | Номер цилиндра и номер сектора, с которых начинается раздел |
04h | 1 | Код раздела (см. табл.3) |
05h | 1 | Номер поверхности диска, на которой заканчивается раздел |
06h | 2 | Номер цилиндра и номер сектора, на которых заканчивается раздел |
08h | 4 | Абсолютный (логический) номер начального сектора раздела |
0Ch | 4 | Размер раздела (число секторов) |
Код раздела используется для определения наличия и положения на диске основного и расширенного разделов. После обнаружения нужного раздела его размер и координаты можно извлечь из соответствующих полей описателя. Если в поле кода раздела записан 0, то описатель считается пустым, то есть он не определяет на диске никакого раздела.
Таблица 3. Коды разделов операционных систем Microsoft
Код | Вид раздела | Размер | Тип FAT | ОС |
---|---|---|---|---|
01h | Основной | 0-15 Мбайт | FAT12 | MS-DOS 2.0 |
04h | Основной | 16-32 Мбайт | FAT16 | MS-DOS 3.0 |
05h | Расширенный | 0-2 Гбайт | - | MS-DOS 3.3 |
06h | Основной | 32 Мбайт-2 Гбайт | FAT16 | MS-DOS 4.0 |
0Bh | Основной | 512 Мбайт-2 Гбайт | FAT32 | OSR2 |
0Ch | Расширенный | 512 Мбайт-2 Тбайт | FAT32 | OSR2 |
0Eh | Основной | 32 Мбайт-2 Гбайт | FAT16 | Windows 95 |
0Fh | Расширенный | 0-2 Гбайт | - | Windows 95 |
За операционными системами других фирм зарезервированы следующие коды:
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
c | c | c | c | c | c | c | c | c | c | s | s | s | s | s | s |
CMP byte ptr sect_buf[01BEh], 80h
проверит, активен ли первый раздел, а код
MOV CX, sect_buf[01C0h]
загрузит CX для вызова INT 13h для чтения корневого сектора раздела № 1.
Применима формула:
отн_сек = (#Цил * сек_на_цил * головок) + (#Гол * сек_на_цил) + (#Сек -1)
Разделы начинаются с четного номера цилиндра, за исключением первого раздела, который может начинаться с цилиндра 0, головки 0, сектора 2 (поскольку сектор 1 занят Главной записью загрузки).
Когда корневая запись раздела получает управление, DS:SI указывает на соответствующий элемент таблицы разделов.
Таблица 4. Формат корневого сектора дискеты или раздела жесткого диска
Смещ. | Длина | Содержимое |
00h | 3 | NEAR-переход на код загрузки
| 03h | 8 | | | OEM-имя компании и версия системы
| 0Bh | 2 | SectSiz | число байтов в секторе (всегда 512) | начало BPB
| 0Dh | 1 | ClustSiz | число секторов в кластере
| 0Eh | 2 | ResSecs | число резервных секторов (секторов перед FAT #1)
| 10h | 1 | FatCnt | число таблиц FAT
| 11h | 2 | RootSiz | число 32-байтовых элементов корневого каталога (для FAT32 - 0)
| 13h | 2 | TotSecs | общее число секторов на носителе (раздел DOS)
| 15h | 1 | Media | тип носителя информации (то же, что 1-й байт FAT)
| 16h | 2 | FatSize | число секторов в одной FAT | конец BPB
| 18h | 2 | TrkSecs | число секторов на дорожке
| 1Ah | 2 | HeadCnt | | число головок
| 1Ch | 4 | HidnSec | число скрытых секторов (исп. в схемах разделения)
| 20h | 4 | TotSecs | всего секторов, если размер >32 Мб
| 24h | 1 | 128 | физич.номер диска
| 25h | 1 | | | резерв
| 26h | 1 | 29h | | признак расшир.структуры
| 27h | 4 | | ID тома(серийный номер)
| 2Bh | Bh | | метка (NO NAME)
| 36h | 8 | | ID файловой системы (FAT12)
| 3Eh | начало кода и данных загрузки
| |
Эта 10-байтовая структура известна также как "Disk Base Table". Она находится по адресу вектора прерывания INT 1Eh (4-байтовый адрес в 0:0078). Эта таблица задает некоторые важные переменные для устройств дискет. Ее инициализирует ROM-BIOS, а DOS модифицирует, чтобы улучшить производительность дискет.
Таблица 5. Формат таблицы параметров дискеты
Смещение | Длина | Содержимое |
---|---|---|
00h | 1 | Первый байт спецификации:
биты 0-3 - время загрузки головок; биты 4-7 - длительность шага головок |
01h | 1 | Второй байт спецификации:
бит 0 - флаг режима ПДП; биты 1-7 - время загрузки головок |
02h | 1 | Задержка перед отключением мотора (в "тиках" ситемных часов) |
03h | 1 | Размер сектора (байт): 0 - 128, 1 - 256, 2 - 512, 3 - 1024 |
04h | 1 | Число секторов на дорожке |
05h | 1 | Длина межсекторного промежутка для операций чтения/записи |
06h | 1 | Длина области данных |
07h | 1 | Длина межсекторного промежутка для операции форматирования |
08h | 1 | Символ-заполнитель для форматирования (обычно 0F6h, т.е. 'Ў') |
09h | 1 | Время установки головок (в миллисекундах) |
0Ah | 1 | Время запуска мотора (в 1/8 с) |
Эта 16-байтовая структура находится по адресу вектора прерывания INT 41h (4-байтовый адрес в 0:0104). Параметры для второго жесткого диска (если он есть) находятся по адресу вектора INT 46h. Эти таблицы задают некоторые важные переменные для операций с твердыми дисками.
Таблица 6. Формат таблицы жесткого диска
Смещение | Длина | Содержимое |
---|---|---|
00h | 2 | Число цилиндров |
02h | 1 | Число головок |
03h | 2 | Не используется (всегда 0) |
05h | 2 | Номер начального цилиндра предкомпенсации |
07h | 1 | Максимальная длина блока коррекции ошибок ECC |
08h | 1 | Байт контроля:
биты 0-2 - не используются (всегда 0); бит 3 - установлен, если число головок больше 8; бит 4 - не используется (всегда 0); бит 5 - установлен, если изготовитель разместил карту дефектов на цилиндре с номером "максимальный рабочий цилиндр + 1"; бит 6 - запрет повторного контроля ECC; бит 7 - запрет контроля ECC |
09h | 1 | Не используется (всегда 0) |
0Ah | 1 | Не используется (всегда 0) |
0Bh | 1 | Не используется (всегда 0) |
0Ch | 2 | Номер цилиндра зоны парковки |
0Eh | 1 | Число секторов на дорожке |
0Fh | 1 | Резерв |
Размер файла может изменяться со временем. Если допустить хранение файла только в смежных секторах, то при увеличении размера файла ОС должна полностью переписать его в другую подходящего объема (свободную) область диска. Чтобы упростить и ускорить выполнение операции добавления новых данных в файл, в современных ОС применяются таблицы распределения файлов (File Allocation Table, сокращенно FAT), которые позволяют хранить файл в виде нескольких несмежных участков.
При использовании FAT область данных логического диска разделена на участки одинакового размера - кластеры. Кластер может состоять из одного или нескольких последовательно расположенных на диске секторов. Число секторов в кластере должно быть кратным 2N и может принимать значения от 1 до 64 (размер кластера зависит от типа используемой FAT и объема логического диска).
Каждому кластеру поставлен в соответствие собственный элемент таблицы FAT. Первые два элемента FAT являются резервными - если на диске имеется K кластеров данных, то число элементов FAT будет равно K+2. Тип FAT определяется значением K:
Название типов FAT происходят от размера элемента. Так элемент FAT12 имеет размер 12 бит, FAT16 - 16 бит, FAT32 - 32 бита. Следует учитывать, что в FAT32 четыре старших двоичных разряда зарезервированы и игнорируются в процессе работы ОС (то есть значащими являются только семь младших шестнадцатеричных разрядов элемента).
FAT - это связный список, который ОС использует для отслеживания физического расположения данных на диске и для поиска свободной памяти для новых файлов.
В каталоге файлов (оглавлении) для каждого файла содержится номер начального элемента в таблице FAT, соответствующий первому кластеру в цепочке распределения файла. Соответствующий элемент FAT либо указывает конец цепочки, либо ссылается на следующий элемент, и т.д. Пример:
Эта диаграмма иллюстрирует основные концепции FAT. Из нее видно, что:
Таблица 7. Значения элементов FAT
Значение | FAT12 | FAT16 | FAT32 |
---|---|---|---|
Свободный кластер | 0 | 0 | 0 |
Зарезервированный кластер | FF0h-FF6h | FFF0h-FFF6h | FFFFFF0h-FFFFFF6h |
Дефектный кластер | FF7h | FFF7h | FFFFFF7h |
Конец цепочки распределения | FF8h-FFFh | FFF8h-FFFFh | FFFFFF8h-FFFFFFFh |
Номер кластера следующего элемента в цепочке | 002h-FEFh | 0002h-FFEFh | 0000002h-FFFFFEFh |
FAT обычно начинается с логического сектора 1 в разделе DOS (т.е. ее можно прочитать по INT 25h с DX=1). В общем случае сначала надо прочитать корневой_сектор (DX=0) и взять смещение 0Eh. Там указано, сколько корневых и резервных секторов стоят перед FAT. Используйте затем это число (обычно 1) как содержимое DX, чтобы прочитать FAT через INT 25h.
Может существовать несколько копий FAT. Обычно поддерживаются две идентичных копии. В этих случаях все копии расположены непосредственно друг за другом.
Чтобы прочитать любой элемент FAT (следуя по цепочке), сначала прочитайте в память всю FAT и получите из оглавления начальный номер кластера. Затем, в случае FAT12:
Теперь рассмотрим порядок действий при записи элемента в FAT12.
В программах, написанных на ассемблере, для выполнения умножения на 3 вместо команды MUL часто применяется алгоритм "сдвиг и сложение": исхродное число копируется, над копией числа выполняется сдвиг влево на один разряд (умножение на 2), а затем оба числа складываются (x + 2x = 3x). Вместо команды DIV используется сдвиг вправо на один разряд.
Элемент FAT содержит номер кластера, но при работе с дисками на низком уровне адресуемой единицей данных является сектор, а не кластер.
Дискета (или раздел твердого диска) структурирована следующим образом:
Каждая секция в этой структуре имеет переменную длину, и для корректного преобразования номера кластера в номер сектора необходимо знать длину каждой такой секции.
Чтобы получить номер начального сектора кластера из номера кластера ClustNum (считанный из соответствующего поля в элементе каталога или в цепи FAT ), вы можете использовать недокументированную функцию ОС 32h или прочитать корневой сектор и применить следующие формулы:
где значения переменных: RootSiz, ResSecs, FatSize, FatCnt, ClustSiz извлекаются из корневого сектора или из BPB (см. табл.4).
Установите DX=нач_сектор перед операцией чтения INT 25h или записи INT 26h.
Каталог файлов представляет собой массив 32-байтных элементов - описателей файлов. С точки зрения операционной системы все каталоги (кроме корневого каталога в системах FAT12 и FAT16) выглядят как файлы и могут содержать произвольное количество записей.
Корневой каталог (Root Directory) - это главный каталог диска, с которого начинается дерево подкаталогов. Для корневого каталога в FAT12 и FAT16 в системной области логического диска выделено специальное место фиксированного размера (16 Кбайт), рассчитанное на хранение 512 элементов. В системе FAT32 корневой каталог является файлом произвольного размера.
Таблица 8. Структура элемента каталога
Смещение | Длина | Содержимое |
---|---|---|
00h | 11 | Короткое имя файла |
0Bh | 1 | Атрибуты файла |
0Сh | 1 | *Зарезервировано под Windows NT (должно содержать 0) |
0Dh | 1 | *Поле, уточняющее время создания файла (в десятках миллисекунд). Значение поля может находиться в пределах от 0 до 199 |
0Eh | 2 | *Время создания файла |
10h | 2 | *Дата создания файла |
12h | 2 | *Дата последного обращения к файлу для записи или считывания данных |
14h | 2 | *Старшее слово номера первого кластера файла |
16h | 2 | Время выполнения последней операции записи в файл |
18h | 2 | Дата выполнения последней операции записи в файл |
1Ah | 2 | Младшее слово номера первого кластера файла |
1Ch | 4 | Размер файла в байтах (32-разрядное число) |
Знак "*" означает, что поле обрабатывается только в файловой системе FAT32. В системах FAT12 и FAT16 поле считается зарезервированным и содержит значение 0.
Короткое имя файла состоит из двух полей: 8-байтного поля, содержащего собственно имя файла, и 3-байтного поля, содержащего расширение. Если введенное пользователем имя файла короче восьми символов, то оно дополняется пробелами (код пробела - 20h), если введенное расширение короче трех символов, то оно также дополняется пробелами.
Некоторые функции DOS требуют в качестве параметра байт атрибутов файла. Разряды байта атрибутов устанавливаются в 1 в том случае, если у файла имеется соответствующее свойство:
Поле времени создания файла и поле времени выполнения последней операции записи в файл имеют следующий формат:
Час | Минута | Секунда/2 |
15 | 11 | 10 | 5 | 4 | 0 |
"Секунда/2" означает двухсекундный отсчет (допустимо значение от 0 до 29).
Поле даты создания файла, поле даты последного обращения к файлу и поле даты последней записи в файл имеют следующий формат:
Год | Месяц | День |
15 | 9 | 8 | 5 | 4 | 0 |
При создании файлов отсчет дат ведется от начала эпохи MS-DOS, т.е. от 01.01.1980. Биты 9-15 содержат номер года минус 1980 (допустимо значение от 0 до 127).
Начиная с Windows 95 файлу можно присвоить (в дополнение к короткому имени) так называемое длинное имя. Для хранения длинного имени используются пустые элементы каталога, смежные с основным элементом - описателем файла. Наличие единиц в разрядах 0-3 байта атрибутов является признаком того, что свободный элемент каталога используется для хранения участка длинного имени файла (для описателей файлов и каталогов такое сочетание невозможно). Короткое и длинное имена файла являются уникальными, т.е. не должны встречаться дважды в одном каталоге.
Длинное имя записывается не ASCII-символами, а в формате Unicode, где каждому национальному алфавиту соответствует набор кодов. Расплатой за универсальность Unicode является снижение плотности хранения информации - каждый символ занимает два байта (16-разрядное слово). В пустые элементы каталога длинное имя записывается в разрезанном на кусочки виде (см. табл.9).
Таблица 9. Структура элемента каталога, хранящего фрагмент длинного имени файла
Смещение | Длина | Содержимое |
---|---|---|
00h | 1 | Номер фрагмента |
01h | 10 | Первый участок фрагмента имени |
0Bh | 1 | Атрибуты файла |
0Ch | 1 | Байт флагов |
0Dh | 1 | Контрольная сумма короткого имени |
0Eh | 12 | Второй участок фрагмента имени |
1Ah | 2 | Номер первого кластера (должен быть равен 0) |
1Ch | 4 | Третий участок фрагмента имени |
Длинное имя записывается в каталог первым, причем фрагменты размещены в обратном порядке, начиная с последнего:
(Начало каталога) |
Последний фрагмент длинного имени |
*** |
Второй фрагмент длинного имени |
Первый фрагмент длинного имени |
Стандартный описатель файла |
*** |
(Конец каталога) |
Все каталоги, за исключением корневого, содержат в двух первых элементах вместо описателей файлов специальные ссылки. В элементе № 0 размещается указатель на сам каталог, а в поле имени находится одна точка ("."). В элементе № 1 размещается указатель на родительский каталог , а в поле имени находятся две точки (".."). Если ссылка на таблицу FAT у элемента № 1 имеет нулевое значение, то текущий каталог находится в корневом каталоге.
Блок информации диска формируется НЕДОКУМЕНТИРОВАННОЙ функцией DOS 32h.
Все сведения, содержащиеся здесь, можно получить путем чтения корневого сектора и вызова ряда других функций ОС с некоторыми вычислениями, но блок информации удобен тем, что он содержит все данные вместе. Это единственный вызов, который возвращает адрес заголовка драйвера устройства.
Таблица 10. Схема блока информации диска
Смещение | Длина | Содержимое |
---|---|---|
00h | 1 | Номер диска (0=A, 1=B и т.д.) |
01h | 1 | Номер субустройства из заголовка устройства (один драйвер может управлять несколькими дисками) |
02h | 2 | Размер сектора в байтах |
04h | 1 | Число секторов на кластер -1 (максим. сектор в кластере) |
05h | 1 | Сдвиг кластера в сектор (кластер = 2№ секторов) (секторов на кластер в степенях двойки: 2 для 4, 3 для 8) |
06h | 2 | Число резервных секторов (корневые, начало корневого огл.) (N первого сектора FAT) |
08h | 1 | Число таблиц FAT |
09h | 2 | Макс. число элементов в корневом оглавлении |
0Bh | 2 | Номер сектора для кластера №2 (1-й кластер данных) |
0Dh | 2 | Всего кластеров +2 (наивысший номер кластера) |
0Fh | 1 | Число секторов, занимаемое одной FAT |
10h | 2 | Номер сектора начала корневого оглавления |
12h | 4 | Адрес заголовка_устройства |
16h | 1 | Байт дескриптора_носителя |
17h | 1 | Флаг доступа: 0, если был доступ к устройству |
18h | 4 | Адрес следующего блока информации диска (0FFFFh, если блок - последний) |
Битовые флаги режима открытия:
Если байт атрибутов файла индицирует только чтение, он перекрывает эти флаги.
Биты прав доступа в сети и режима разделения имеют эффект только в том случае, когда установлена программа SHARE.
© Колесников Дмитрий Геннадьевич
Учебник по СайтоСтроению
-
|