Главная » Ассемблер, Железо » Размещение информации на логических дисках

0

Операционная система выбирает способ организации хранения информации на носителе в зависимости от его типа и объема, а также пожеланий пользователя. Гибкие диски для АТ-совместимых компьютеров всегда организованы в виде одного логического диска со структурой FAT12. Жесткий диск может содержать один или несколько разделов, предназначенных для одной или нескольких различных операционных систем, а разделы в свою очередь могут состоять из одного или нескольких логических дисков. Логический диск (том) файловой системы типа FAT состоит из четырех основных областей (рис. 6.1), расположенных в следующем порядке:

•           резервная область;

•           область таблиц размещения файлов (FAT1 и

•           область корневого каталога (не существует в FAT32);

•           область файлов и каталогов.

Рис. 6.1. Организация данных на логических дисках

В первом секторе логического диска с системой FAT располагаются загрузочный сектор и блок параметров BIOS. В документации Microsoft они обозначаются как Boot Sector (BS) и BIOS Parameter Block (BPB) соответственно. Начальный участок данного блока для всех типов FAT идентичен; описание этого участка приведено в табл. 6.30.

Таблица 6.30. Начальный участок загрузочного сектора


Наименование

Смещение

Размер,

Описание

элемента

 

байт

 

BSJmpBoot

OOh

3

Инструкция перехода (jmp) на загрузочный код

BS_OEMName

03h

8

Текстовая строка с аббревиатурой фирмы-изготовителя и номером версии операционной системы

BPB_BytsPerSec

OBh

2

Число байтов в секторе (всегда 512)

BPB_SecPerClus

ODh

1

Число секторов в кластере

BPB_RsvdSecCnt

OEh

2

Число резервных секторов в резервной области раздела, начиная с первого сектора раздела

BPBNumFATs

10h

1

Число таблиц (копий) FAT в разделе (всегда равно 2)

BPBRootEntCnt

11h

2

Для FAT12 и FAT16 — количество 32-байтных дескрипторов файлов в корневом каталоге (при использовании FAT16 равно 512); для FAT32 это поле имеет значение 0

BPB_TotSec16

13h

2

Общее число секторов в разделе (если данное поле имеет значение 0, то число секторов задается полем BPB_TotSec32)

BPB_Media

15h

1

Тип носителя информации (см. табл. 6.33)

BPB_FATSz16

16h

2

Для FAT12 и FAT16 — количество секторов, занимаемых одной копией FAT; для FAT32 поле имеет значение 0

BPB_SecPerTrk

18h

2

Число секторов на дорожке (для прерывания 13h)

BPB_NumHeads

1Ah

2

Число головок (для прерывания 13h)

BPB_HiddSec

1Ch

4

Число скрытых секторов, предшествующих разделу, содержащему данный том. Значение равно 0 для носителей, не подлежащих разбиению на разделы

Таблица 6.30 (продолжение)

 

Наименование элемента

Смещение

Размер, байт

Описание

 

BPB_TotSec32

20h

4

Общее число секторов в разделе (поле используется вместо BPB_TotSec16, если в разделе свыше 65 535 секторов; в противном случае поле содержит значение 0)

 

Информацию, приведенную в табл. 6.30, нужно дополнить следующими замечаниями.

•      Поле безусловного перехода BS jmpBoot может иметь два формата, соответствующих двум разным типам инструкций перехода процессора х86. Первый вариант начинается с кода EBh, второй — с кода E9h.

•      Поле BS_OEMName, вообще говоря, может содержать любое значение, однако современные операционные системы Microsoft заносят в него код MSWIN4 1.

•      Поле BPB_SecPerCl us задает число секторов в кластере и может содержать значения, равные 2N: 1, 2,4, 8, 16,32, 64.

•      Поле BPB_RsvdSecCnt задает количество секторов резервной области. Для FAT 12 и FAT 16 данное поле всегда имеет значение 1, а для FAT32 — обычно значение 32.

•      Поля BPB_TotSecl6 и BPB_TotSec32 задают число секторов в разделе, причем это число заносится только в одно из указанных полей, а второе должно содержать значение 0. Если в разделе не более 65 535 секторов, то используется поле BPB_TotSecl6, иначе — поле BPB_TotSec32.

•      Поле BPB_Media описывает тип установленного в дисковод носителя информации. Перечень допустимых кодов носителей приведен в табл. 6.33.

Различия в структуре загрузочных секторов для разных типов FAT начинаются со смещения 24h. Для FAT12 и FAT16 структура имеет вид, показанный в табл. 6.31, а для FAT32 — в табл. 6.32. Рассмотрим отдельные поля более подробно.

•      Поле BS_Fi 1 SysType содержит аббревиатуру файловой системы (FAT12, FAT16 или FAT32), но не должно использоваться для идентификации ее типа.

• Бит 7 поля BPB_ExtFl ags содержит признак активности FAT: если он равен нулю, то в процессе работы изменения отражаются во всех FAT, а в противном случае активной является только одна копия, номер которой записан в битах 0-3 поля BPB_ExtFl ags (счет номеров ведется с 0). Остальные разряды поля BPB_ExtFl ags зарезервированы.

Таблица 6.31. Структура загрузочного сектора для FAT12 и FAT16, начиная со смещения 24h

Наименование

Смещение

Размер,

Описание

элемента

 

байт

 

BS_DrvNum

24h

1

Номер дисковода для прерывания 13h (для дисководов гибких дисков — от 0 до 3; для жестких дисков счет номеров ведется с 80h)

BS_Resen/ed1

25h

1

Зарезервировано для Windows NT, имеет значение 0

BS_BootSig

26h

1

Признак расширенной загрузочной записи (29h). Показывает, что следующие три поля присутствуют

BS_VollD

27h

4

Номер логического диска (формируется при форматировании как комбинация времени и даты создания)

BS_VolLab

2Bh

11

Метка диска (текстовая строка)

BS_FilSysType

36h

8

Текстовая строка с аббревиатурой типа файловой системы

 

Таблица 6.32. Структура загрузочного сектора для FAT32, начиная со смещения 24h

Наименование

Смещение

Размер,

Описание

элемента

 

байт

 

BPB FATSZ32

24h

4

Количество секторов, занимаемых

 

 

 

одной копией FAT

BPB_Ext Flags

28h

2

Номер активной FAT

BPB FSVer

2Ah

2

Номер версии FAT32: старший

 

 

 

байт — номер версии, младший —

 

 

 

номер ревизии. В настоящее

 

 

 

время используется значение 0:0

Таблица 6.32 (продолжение)

Наименование

Смещение

Размер,

Описание

элемента

 

байт

 

BPB_RootClus

2Ch

4

Номер кластера для первого кластера корневого каталога (обычно имеет значение 2)

BPBFSInfo

30h

2

Номер сектора структуры FSINFO в резервной области логического диска (обычно 1)

BPB_BkBootSec

32h

2

Номер сектора (в резервной области логического диска), используемого для хранения резервной копии загрузочного сектора (обычно 6)

BPB_Reserved

34h

12

Область, зарезервированная для дальнейших расширений (должна содержать нули)

BS_DrvNum

40h

1

Номер дисковода для прерывания 13h (для дисководов гибких дисков — от 0 до 3; для жестких дисков счет номеров ведется с 80h)

BS_Reserved1

41h

1

Зарезервировано для Windows NT, имеет значение 0

BS_BootSig

42h

1

Признак расширенной загрузочной записи (29h). Показывает, что следующие три поля присутствуют

BS_VollD

43h

4

Номер логического диска (формируется при форматировании как комбинация времени и даты создания)

BS_VolLab

47h

11

Метка диска (текстовая строка)

BS_FilSysType "

52h

8

Текстовая строка с аббревиатурой типа файловой системы

 

Таблица 6.33. Типы носителей информации


Код типа

Тип носителя информации

 

FOh

Гибкий диск, 2 стороны, 18 секторов на дорожке

 

F8h

Жесткий диск

 

F9h

Гибкий диск, 2 стороны, 15 секторов на дорожке

 

FCh

Гибкий диск, 1 сторона, 9 секторов на дорожке

 

Код типа

Тип носителя информации

FDh

Гибкий диск, 2 стороны, 9 секторов на дорожке

Feh

Гибкий диск, 1 сторона, 8 секторов на дорожке

FFh

Гибкий диск, 2 стороны, 8 секторов на дорожке

Кроме перечисленных в табл. 6.30-6.32 полей, нулевой сектор логического диска должен содержать в байте со смещением lFEh код 55h, а в следующем байте (со смещением IFFh) — код AAh. Указанные два байта являются сигнатурой — признаком загрузочного сектора логического диска.

Таким образом, загрузочный сектор выполняет две важные функции: описывает структуру данных на диске, а также позволяет осуществить загрузку операционной системы (если она установлена на диске, и диск является активным). В случае возникновения ошибки в момент записи информации в загрузочный сектор (например, из- за внезапного выключения электропитания) может быть утрачена вся информация на логическом диске, поэтому в системе FAT32 сектор 6 резервной области используется для хранения копии загрузочного сектора (Backup Boot Sector).

Поскольку размер таблицы FAT на логическом диске с организацией FAT32 может быть очень велик, для ускорения выполнения операций с FAT была введена структура FSInfo, размещаемая в секторе 1 резервной области. Эта структура содержит информацию о количестве свободных кластеров на диске и о номере первого свободного кластера в таблице FAT. Формат структуры описан в табл. 6.34.

Таблица 6.34. Структура сектора FSInfo и резервного загрузочного сектора FAT32

Наименование

Смещение

Размер,

Описание

элемента

 

байт

 

FSI_LeadSig

000h

4

Значение 41615252h — сигнатура, которая служит признаком того, что данный сектор содержит структуру FSInfo

FSI_Reserved1

004h

480

Поле зарезервировано для дальнейших расширений (все байты должны быть заполнены нулями)

FSI_StrucSig

1E4h

4

Значение 61417272h (сигнатура)

Таблица 6.34 (продолжение)

Наименование

Смещение

Размер,

Описание

элемента

 

 

 

FSI_Free_Count

1E8h

4

Содержит текущее число свободных кластеров на диске. Если в поле записано значение OFFFFFFFFh, то количество свободных кластеров неизвестно (его нужно вычислять)

FSI_Nxt_Free

1ECh

4

Содержит номер кластера, с которого дисковый драйвер должен начинать поиск свободных кластеров. Если в поле записано значение OFFFFFFFFh, то поиск свободных кластеров нужно начинать с кластера № 2

FSI_ Reserved2

1F0h

12

Поле зарезервировано для дальнейших расширений (все байты должны быть заполнены нулями)

FSI_TrailSig

1FCh

4

Значение AA550000h — сигнатура, которая служит признаком конца структуры FSInfo

Хотя относительные номера секторов структур Backup Boot Sector и FSInfo являются константами, значения этих констант зачем-то хранятся в полях BPB_BkBootSec и BPB_FSInfo загрузочного сектора. Чтобы прочесть значение некоторого элемента любой структуры данных, нужно вначале получить доступ к самой структуре (то есть определить ее местоположение на диске), а затем прочитать с диска в буфер оперативной памяти либо всю структуру, либо только тот сектор, в котором находится интересующий нас элемент. Местоположение основных структур данных на физическом диске, то есть абсолютные номера начальных секторов, можно вычислить по следующим формулам:

BSJjtartSect = LDi skStartSect FSInfo_StartSect = BSStartSect + BPB_FSInfo FATlStartSect = BS_StartSect + BPB_RsvdSecCnt FAT2_StartSect = FATl_StartSect + BPB_FATSz ROi r_StartSect = FATl_StartSect + BPB FATSz X BPB_NumFATs Oata_StartSect – RDir StartSect + (32 X BPB_RootEntCnt)/512

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

•     BS_StartSect — номер загрузочного сектора логического диска;

•     LDisk_StartSect — номер начального сектора диска;

•     FATl_Sta rtSect — номер начального сектора первой FAT;

•     BPB_RsvdSecCnt — число секторов в резервной области (32 для системы FAT32 и 1 для остальных систем);

•     FAT2_StartSect — номер начального сектора второй FAT;

•     BPB_FATSz – размер одной копии FAT (BPB_FATSz32 для FAT32 и BPB_FATSzl6 для остальных систем);

•     BPB_NumFATs — число копий FAT на диске;

•     RDi r_Sta rtSect — номер начального сектора корневого каталога;

•     Data_StartSect — номер начального сектора области данных;

•     BPB RootEntCnt — число записей в корневом каталоге (0 для FAT32 и 512 для остальных систем).

В листинге 6.6 приведена программа ShowFDDSector, позволяющая при помощи функций BIOS осуществлять последовательный просмотр секторов гибкого диска в ASCII-кодах. Перед тем как начать просмотр, программа просит пользователя установить гибкий диск в дисковод А:, считывает загрузочный сектор и извлекает из него информацию о формате гибкого диска (то есть о количестве рабочих поверхностей диска и числе секторов на дорожке). Пролистыва- ние секторов осуществляется при помощи клавиш i и Т; для выхода из программы нужно нажать клавишу Esc. Для считывания секторов используется вспомогательная процедура ReadFDDSector.

Листинг 6.6. Просмотр секторов гибкого диска на дисководе А: при помощи функций BIOS

IDEAL

Р386

LOCALS

MODEL MEDIUM

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

Include "listl_03.inc"

; Подключить файл макросов

Include "listl_04.inc"

Листинг 6.6(продолжение) DATASEG

; Текстовые сообщения

TxtO

DB LIGHTCYAN,0,7."ПРИМЕР ИСПОЛЬЗОВАНИЯ ФУНКЦИЙ "

DB "BIOS ДЛЯ ЧТЕНИЯ ИНФОРМАЦИИ С ДИСКЕТЫ",О

DB LIGHTGREEN.12.24

DB "Установите дискету в дисковод А:",О

DB YELLOW,24,29,"Нажмите любую клавишу",О Txtl

DB LIGHTCYAN,0.10,"Просмотр секторов "

DB "гибкого диска, находящегося в дисководе А:",0

DB LIGHTGREEN,2,14,"Диск имеет поверхность(и),"

DB " секторов на дорожке",0

DB LIGHTCYAN.17,8."Управляющие клавиши:".О

DB YELLOW.24,27."Нажмите управляющую клавишу".0 Txt2

DB 19,8,"Стрелка вниз • следующий сектор;",0

DB 20.В,"Стрелка вверх – предыдущий сектор:",0

DB 21.8,"Esc – выход.",0 Txt3

DB LIGHTGREEN.5,8

DB "Дорожка N Головка N Сектор N ",0 TErr

DB 12,27,"Ошибка считывания сектора",0

: Адрес считываемого сектора в режиме CHS

Cylinder

DB ? ;номер цилиндра

HeadDB ? ;номер головки

Sector

DB ? ;номер сектора

: Предельные значения координат

MaxCylinder

DB 79 :? максимальный номер цилиндра

MaxHead

DB 1 :? максимальный номер головки

MaxSector

DB 18 ;? максимальный номер сектора

; Область памяти для хранения прочитанного сектора

SectorDataBuffer

DB 512 DUP (?)

ENDS

SEGMENT sseg para stack ‘STACK’

DB 400h DUP(?)

ENDS CODESEG

;* Основной модуль программы *

. ********************* AAA А"А AAA-

PROC ShowFDDSector

mov AX.DGROUP

mov DS.AX

mov [CS: MainDataSeg],AX

; Установить текстовый режим и очистить экран

mov АХ.З int 10h

; Скрыть курсор – убрать за нижнюю границу экрана

mov [ScreenStri ng],25

mov [ScreenColumn],0 call SetCursorPosition

; Вывести на экран сообщение "Вставьте дискету" MShowColorText 3,TxtO

; Ожидать нажатия клавиши call GetChar

; Прочитать BOOT-сектор дискеты

mov [Cylinder],О

mov [Head],О

mov [Sector],1 cal1 ReadFDDSector

; Определить и запомнить параметры дискеты

mov AL,[SectorDataBuffer+18h]

mov [MaxSector],AL

mov AL.[SectorDataBuffer+lAh] dec AL

mov [MaxHeadLAL

; Очистить экран

call ClearScreen

; Вывести текстовые сообщения MShowColorText 4,Txtl

; Установить зеленый цвет и черный фон

mov [TextColorAndBackground],LIGHTGREEN

; Отобразить параметры установленной дискеты

mov AH,[MaxHead]

inc АН

MShowDecByte 2.25,АН MShowDecByte 2,43.[MaxSector]

; Вывести описание управляющих клавиш MShowText 3,Txt2

; ЦИКЛ ПО СЕКТОРАМ

mov AX,0B800h

mov ES,AX

@@ReadSector:

MShowColorString Txt3 MShowDecByte 5,18,[Cylinder] MShowDecByte 5.31,[Head] MShowDecByte 5,44,[Sector]

; Прочитать сектор

cal1 ReadFDDSector

; Отобразить на экран содержимое считанного сектора : в ASCII-кодах

@@ShowSector:

; Установить начало окна отображения сектора

mov DI,7*160+8*2

mov SI,offset SectorDataBuffer

; Задать для символов светло-голубой

Листинг 6.6 (продолжение)

; цвет и синий фон

mov АН, LIGHTCYAN+B LUE*16

mov DX.8 :счетчик строк

@@OutNextString:

mov СХ.64 ;счетчик символов в строке

@@OutNextChar: lodsb stosw

loop

@@OutNextChar

add DI,16*2 dec DX

jnz

@@OutNextString

@@GetConmand:

; Ожидаен ввода следующей команды cal1 GetChar cmp AL.O

je

@@TestCommandByte

cal1 Beep

jmp short @PGetCommand

@@TestCommandByte:

cmp AH.B Esc ;коианда "Выход"?

; Выполнить команду "Выход"

je

@@End (PPTestDn:

сшр АН,B_DN jne

@@Testl)p

; Выполнить команду "Стрелка вниз"

mov AL.[Sector] cmp AL,[MaxSector] jae

@@IncHead

; Увеличить на 1 номер сектора

inc [Sector] jmp

@@ReadSector

@@IncHead:

mov AL.[Head] cmp AL,[MaxHead] jae

@@IncCy1inder

; Увеличить на 1 номер головки,

; установить сектор 1

inc [Head]

mov [Sector],l jmp

@@ReadSector POIncCylinder:

mov AL, [Cyl i rider] cmp AL.[MaxCyli rider]

jae

@@CommandError

; Увеличить на 1 номер цилиндра, установить

; головку 0, сектор 1

inc [Cylinder]

mov [Head],О

mov [Sector],1 jmp

@@ReadSector

@@TestUp:

cmp AH.BUP jne

@@CommandError

; Выполнить команду "Стрелка вверх" cmp [Sector],1 jbe

@@DecHead

; Уменьшить на 1 номер сектора dec [Sector] jmp

@@ReadSector

@@DecHead:

mov AL,[Head] cmp AL.O

je

@@DecCylinder : Уменьшить на 1 номер головки, установить : максимальный нонер сектора dec [Head]

mov AL,[MaxSector]

mov [Sector],AL jmp

@@ReadSector

@@DecCylinder:

mov AL.[Cylinder] cmp AL.O

je

@@CommandError

; Уменьшить на 1 номер цилиндра, установить : максимальные номера головки и сектора dec [Cylinder]

mov AL,[MaxHead]

mov [Head],AL

mov AL,[MaxSector]

mov [Sector],AL jmp

@@ReadSector

@@CommandError:

cal1 Beep

jmp

@@GetCommand

@@End:

; Переустановить текстовый режим

mov ах.З int lOh : Выход в 00S

mov AH,4Ch int 21h ENDP ShowFDDSector

IT

Листинг 6.6 (продолжение)

• Affile A AA’AA’ArArilcArAA^A А’А А АгАгАгАгАгАгАгАг А ААгА^гАг^А tAAtA1 A AAA А А А’А ‘Дг’Дг

;*ПРОЧИТАТЬ СЕКТОР ГИБКОГО ДИСКА*

;* Параметры передаются через глобальные*

;* переменные:*

;* Cylinder – номер цилиндра (от 0 до 79):*

;* Head – номер головки (0 или 1);*

;* Sector – номер сектора (от 1 до 1В).*

;* Считанный сектор записывается в основной*

;* сегмент данных по адресу SectorDataBuffer.*

. ***irk****rk-k***-kirk*irk*-k* А А * к к* » А-* А А А А А * А****

PROC ReadFDDSector NEAR pushad push ES

mov AX.DS

mov ES.AX

mov SI.3 :счетчик повторений

@@Repeat:

mov BX,offset SectorDataBuffer

mov AH.2 подфункция "Прочесть сектор"

mov AL.l :прочесть 1 сектор

mov CH,[Cyli nder]

mov CL,[Sector]

mov DH,[Head]

mov DL,0 -.читать диск "A;"

int 13h

jne POEnd

: Ошибка считывания, инициализировать систему

mov АН,0 подфункция "Инициализировать"

mov DL.0 :диск "А:" int 13h dec SI jnz

@@Repeat

; Аварийный выход – ошибка при чтении файла

MFatalError TErr : Нормальное завершение процедуры

@@End: pop ES popad ret

ENDP ReadFDDSector ENDS

; Подключить процедуры вывода данных на экран

Include "listl_02.inc"

: Подключить процедуры перевода чисел в десятичный код

Include "list2_05.inc"

END

ПРИМЕЧАНИЕ

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

Источник: Кулаков В. К90 Программирование на аппаратном уровне: специальный справочник (+дискета). 2-е издание. — СПб.: Питер, 2003. — 847 е.: ил.

По теме:

  • Комментарии