» Главная
eXcode.ru » Статьи » Assembler
» Новости
» Опросы
» Файлы
» Журнал



Пользователей: 0
Гостей: 15





Читаем FAT12




[Человек не машина, и он хиреет, если лишается
возможности самоопределения и свободы высказывать
собственные суждения…]

Альберт Эйнштейн.

Предисловие.
Это статья не является полным руководством по FAT12, а даёт только начальные знания, навыки и умения для реализации работы с FAT12.

Начнём…
А начнём мы с того, что узнаем, какие данные нужно записать в загрузочный сектор (если он, конечно, есть) дискеты:

Смещение Размер, байт Описание
+3h 8 Аббревиатура и номер версии ОС
+Bh 2 Число байт на сектор (512)
+Dh 1 Число секторов на кластер
+Eh 2 Число резервных секторов в резервной области раздела
+10h 1 Число копий FAT в разделе (2)
+11h 2 Количество 32-байтных дескрипторов файлов в корневом каталоге
+13h 2 Общее число секторов в разделе
+15h 1 Тип носителя информации (для современных дискет F0h)
+16h 2 Количество секторов, занимаемых одной копией FAT
+18h 2 Число секторов на дорожке
+1Ah 2 Число головок
+1Ch 4 Число скрытых секторов перед началом раздела (для дискет 0)
+20h 4 0 (используется FAT32)
+24h 1 Номер дисковода (для дискет - от 0 до 3)
+25h 1 0 (для Windows NT)
+26h 1 Признак расширенной загрузочной записи (29h)
+27h 4 Номер логического диска (создается при форматировании)
+2Bh 11 Метка диска (текстовая строка)
+36h 8 Аббревиатура типа файловой системы
+3Eh Начало загрузочного кода

Загрузчик загружается по физическому адресу 07C00h размером 512 байт. Причём первые 3 байта программы придётся потратить на переход непосредственно к коду загрузчика ОС.

Реализовать это можно следующим образом:


.model tiny
.code
.286
org 100h
Start:

jmp BeginJMP
org 07C00h
BeginJMP:
jmp Begin
gnOEM db "DATA " ; Аббревиатура и номер версии ОС
gnSectSize dw 512 ; Число байт на сектор
gnClustSize db 1 ; Число секторов на кластер
gnRessect dw 1 ; Число резервных секторов
gnFatCnt db 2 ; Число копий FAT
gnRootSize dw 224 ; Размер корневой директории
gnTotalSect dw 2880 ; Общее число секторов
gnMedia db 0F0h ; Тип носителя информации
gnFatSize dw 9 ; Количество секторов, занимаемых FAT
gnTrackSect dw 18 ; Число секторов на дорожку
gnHeadCnt dw 2 ; Число головок
gnHidenSect dd 0 ; Число скрытых секторов
gnHugeSect dd 0 ; Используется FAT32
gnBootDrv db 0 ; Номер дисковода
gnReserv db 0 ; Зарезервировано
gnBootSign db 29h ; Признак расширенной загрузочной записи
gnVolID dd 0 ; Номер логического диска
gnVoLabel db "BASE " ; Метка диска
gnFSType db "FAT12 " ; Аббревиатура типа файловой системы

Begin:

; Загрузчик ОС

Конечно это не самый идеальный вариант, т.к. приходится вырезать почти 07D00h байт от начала. Но главный плюс такого подхода – это простота. Я думаю, вам не составит труда смастерить утилиту для записи загрузочного сектора на дискету. Двигаемся дальше…

Структура FAT.
Первый байт таблицы FAT называется описателем устройства или FAT ID. Следующие пять байтов содержат 0FFh. Следующие байты состоят из 12 битных записей, которые описывают один кластер на диске. Для этих записей используются следующие значения:

Значение Описание
000h Свободный кластер.
FF0h - FF6h Зарезервированный кластер.
002h - FEFh Номер следующего кластера в цепочке
FF7h Плохой кластер.
FF8h-FFFh Последний кластер в цепочке.

Следует учесть, что FAT находится в 1-ом кластере устройства, а корень в 19-ом, прошу не путать эти два понятия.
Элементы оглавления.
Что бы работать с файлами, нужно знать, где они хранятся, сколько байт занимают и т.д. Сейчас мы рассмотрим типичный элемент оглавления файла для FAT12:

Смещение Длина, байт Содержимое
+0 8 Имя файла (дополненное справа пробелами)
+8 3 Расширение файла (дополненное справа пробелами)
+0Bh 1 Атрибут файла:
• 01h – Только чтение
• 02h – Скрытый
• 04h – Системный
• 08h – Метка тома
• 10h – Директория
• 20h – Архив
+0Ch 10 Зарезервировано
+16h 2 Время создания или модификации в формате filetime
+18h 2 Дата создания или модификации в формате filetime
+1Ah 2 Номер начального кластера данных
+1Ch 4 Размер

Особое внимание нужно обратить на время и дату создания. Т.к. время и дата у нас в своём формате, имеет смысл описать алгоритм извлечения нормальных значений даты и времени:
Считываем слово из элемента оглавления со смещением +16h. Поместим его в регистр AX. Для секундных единиц следует учесть, что 1 сек = 2 единицам.

Секунды
(0-30) Минуты
(0-59) Часы
(0-23)
And AX, 001Fh
Imul AX, 2
AX = секунды And AX, 07E0h
Shr AX, 5
AX = минуты And AX, 0F800h
Shr AX, 11
AX = часы

Для даты считываем слово из элемента оглавления со смещением +18h. Поместим его в регистр AX. После операций маскирования и сдвигов прибавьте к году 1980 (07BCh).

День
(0-31) Месяц
(1-31) Год
(0-119)
And AX, 001Fh
AX = день And AX, 01E0h
Shr AX, 5
AX = месяц And AX, 0FC00h
Shr AX, 9
Add AX, 07BCh
AX = год

Вот и всё что вам нужно знать об элементе оглавления файла. Но осталось самое главное, без чего мы не сможем работать с файлами.… Это, конечно же, работа с секторами и кластерами…

Сектора и кластеры.
И так дорогой друг, мы с тобой подошли к самому интересному в нашей работе. Если бы всё было так просто…. Взял, считал начальный кластер данных, а в конце кластера был бы записан следующий номер кластера и т.д. Но нет, мелкософт оказался умнее и предложил неплохую систему поиска и чтения кластеров - нахождение абсолютного сектора. Воспользуемся следующими обозначениями:
N – кластер.
Hidden - количество "скрытых" секторов (0)
Reserved - количество резервных секторов (1)
FATsize – размер одной копии FAT (9 секторов)
FATCount – количество FAT’ов (2)
RootSize - максимально возможное количество файловых записей в корневом каталоге (224)
SectPerClust – количество секторов на кластер (512)

Теперь для вычисления абсолютного сектора для кластера с номером N нам нужно будет воспользоваться формулами:

Temp = Hidden + Reserved
FATSect = FATCount * FATsize
RootData = (RootSize*32 + (SectPerClust-1)) / SectPerClust
SectOffset = (N -2)* SectPerClust
AbsSect = Temp + FATSect + RootData + SectOffset

Абсолютный номер первого сектора для кластера с номером N это и есть AbsSect. Теперь мы свободно можем использовать номер этого сектора для работы с прерыванием INT 13h, нужно только рассчитать головку и дорожку.
Для чтения кластера в определённую область памяти можно воспользоваться вот такой процедурой:

push di
push es
; Начало расчета сектора/дорожки/головки
push cs
pop ds
mov cx,[gnTrackSect] ; Количество секторов на дорожку
mov si,dx
; tmp=(Sector/TrackSectors);
mov ax,si
xor dx,dx
div cx
mov di,ax
; Sec=Sector-(tmp*TrackSectors)+1;
mov ax,di
imul cx
mov dx,si
sub dx,ax
inc dx
mov [AbsSectNum],dx
; Head=tmp & 1;
mov ax,di
and ax,1
mov [AbsHeadNum],ax
; Trk=(Sector-(Head*TrackSectors)-(Sec-1))/(TrackSectors*2);
imul cx
push ax
mov ax,si
pop dx
sub ax,dx
mov dx,[AbsSectNum]
dec dx
sub ax,dx
mov dx,cx
shl dx,1
push ax
push dx
xor dx,dx
pop bx
pop ax
div bx ; AX = AbsTrackNum
; Конец расчетов
mov cx,ax
mov al,cl
shr cx,2
and cl,0C0h
mov ch,al
and cx,0FFC0h
mov ax,[AbsSectNum]
or cl,al
pop es
pop bx ; ES:BX = Куда считывать
mov dx,[AbsHeadNum]
mov dh,dl ; Номер головки
mov dl,00h ; Номер диска 0 = A
xor dl,dl
mov al,1 ; Количество считываемых секторов
mov ah,2 ; Номер функции
int 13h

Эта процедура взята из системы Gluk OS. Т.к. система была, что называется Open Source, то думаю, ничего противозаконного в публикации её здесь нет. Здесь и далее мы будем пользоваться именно этой процедурой. На самом деле вся дальнейшая работа по чтению FAT строится именно на этой процедуре, поэтому удостоверьтесь, что вы написали её правильно.
Это конечно замечательно, что мы можем читать первый кластер файла, но что делать, если файл больше 512 байт?
Ответ прост, обратимся к докам мелкософта. А там сказано, что для того, чтобы прочесть значение любой записи FAT (значение будет равно следующей записи в
цепочке), необходимо сначала прочесть всю таблицу FAT в память, а затем получить номер первого кластера файла. После того как мы получили первый кластер файла нам нужно совершить кое-какие действия для получения следующей записи в
цепочке:
• Умножить номер кластера на 3
• Разделить результат на 2 (каждое значение 12 бит = 1,5 байта, а результат 3 / 2 = 1,5)
• Считать слово (WORD) из полученного адреса (как смещение от начала FAT)
• Если кластер с четным номером, то наложить маску 0FFFh (сохранить нижние 12 бит)
Если кластер нечетный, то сдвинуть значение на 4 бита вправо (сохранить верхние 12 бит)
• Результатом будет номер следующего кластера в цепочке (если 0FFFh, то это последний)

Замечательно! Вот и ответ на наш вопрос. Осталось только это реализовать:

Start_read_next:
push dx
push di
push es
add dx,31 ;Преобразуем в номер сектора
Call ReadSect ;Чтение сектора
pop es
pop di
pop dx
;Получить следующий сектор после DX
push di
mov di,offset Mem_FAT
mov ax,dx
mov bx,ax
mov cx,3
mul cx
shr ax,1
add di,ax
mov dx,word ptr es:[di]
and bx,1
je gns01 ;Если номер кластера четный
shr dx,4
jmp gns02
gns01:
and dx,0FFFh
gns02:
pop di
cmp dx,0FFFh
je End_Begin ;FFF - последний кластер
add di,512
jmp Start_read_next
End_Begin:

Осталась самая малость – написать программу для чтения FAT и рута за одно. Идём далее…

Читаем FAT.
Вот, наконец, программа для чтения FAT и рута с диска A: в определённые области памяти. Собирается в TASM 5.0 как обычный COM файл. С компоновкой и сборкой у вас не должно возникнуть проблем.

.model tiny
.code
.386p
org 100h
start:
mov ax,0003h
int 10h
call ReadRootDir
call ReadFAT
ret

; Чтение сектора (DX=номер сектора)
; ES:DI – Адрес для приёма данных

ReadSect proc
push di
push es
; Начало расчета сектора/дорожки/головки
push cs
pop ds
mov cx,[gnTrackSect]
mov si,dx
; tmp=(Sector/TrackSectors);
mov ax,si
xor dx,dx
div cx
mov di,ax
; Sec=Sector-(tmp*TrackSectors)+1;
mov ax,di
imul cx
mov dx,si
sub dx,ax
inc dx
mov [AbsSectNum],dx
; Head=tmp & 1;
mov ax,di
and ax,1
mov [AbsHeadNum],ax
; Trk=(Sector-(Head*TrackSectors)-(Sec-1))/(TrackSectors*2);
imul cx
push ax
mov ax,si
pop dx
sub ax,dx
mov dx,[AbsSectNum]
dec dx
sub ax,dx
mov dx,cx
shl dx,1
push ax
push dx
xor dx,dx
pop bx
pop ax
div bx ; AX = AbsTrackNum
; Конец расчетов
mov cx,ax
mov al,cl
shr cx,2
and cl,0C0h
mov ch,al
and cx,0FFC0h
mov ax,[AbsSectNum]
or cl,al
pop es
pop bx ; ES:BX = Куда считывать
mov dx,[AbsHeadNum]
mov dh,dl ; Номер головки
mov dl,0 ; Номер диска 0 = A
mov al,1 ; Количество считываемых секторов
mov ah,2 ; Номер функции
int 13h
ret
ReadSect endp

ReadRootDir proc
;Чтение корневого каталога в оперативную память
pusha
mov dx,19 ;Начальный сектор ROOT′a
mov di,offset RootDir
Cont_Read_Root:
push dx
push di
push es
Call ReadSect ;Чтение сектора
pop es
pop di
pop dx
add di,512
inc dx
cmp dx,33
jne Cont_Read_Root
popa
ret
ReadRootDir endp


ReadFAT proc
;Чтение таблицы размещения файлов в оперативную память
pusha
mov dx,1
mov di,offset Mem_FAT
Cont_Read_Fat:
push dx
push di
push es
Call ReadSect
pop es
pop di
pop dx
add di,512
inc dx
cmp dx,10
jne Cont_Read_Fat
popa
ret
ReadFAT endp

AbsSectNum dw 0
AbsHeadNum dw 0
gnTrackSect dw 18 ; Число секторов на дорожку
Mem_FAT db 9*512 dup(?)
RootDir db 15*512 dup (?)
end start


Вот вы и познакомились с основами работы в FAT12. Надеюсь, что вам эта статья хоть чуть-чуть, но помогла. Т.к. человеку свойственно ошибаться, то шлите все ругательства, просьбы, и замечания на мыло: Exs42@yandex.ru. Отдельное и большое спасибо: Xbyte и Mirzman за кодерскую помощь! Спасибо за внимание, всем удачи!
К началу статьи





Добавил: Exs42Дата публикации: 2006-11-16 00:24:10
Рейтинг статьи:4.00 [Голосов 4]Кол-во просмотров: 22028

Комментарии читателей

Всего комментариев: 6

2016-09-07 15:13:05
whiteprofitbupt
Большинство людей, начинающих, какие только узнали, что в Webе возможно по-настоящему заработать без инвестиций и обмана, наступают на одни и те же грабли - они сразу хватаются за трудоемкие и требующие тренировки виды деятельности. Как следствие, почти все они терпят невезуху, что и служит фактором большинства гневных сообщений на тему "заработок в интернете - стопроцентное мошенство и выдумка".
Как по-настоящему иметь заработок в Онлайне новому без инвестиций и обмана
В данной публикации будет идти речь о самых элементарных методах извлечения доходов в интернете, какие сможет освоить даже начинающий. Они не принесут таких денег, как, предположим, создание личного вебсайта или разработка приложений, но и требования предъявляют к пользователю куда более скромные. Итак, давайте начнем.

все находится <a href=http://whiteprofit.ru/wordpress/kak-ispravit-v-wordpress-ne-mogu-sozdat-direktoriyu-uploads.htm>таким</a>

2016-08-30 17:19:30
mykomp2Pet
На этом web-сайте вы узнаете много важной информации о компьютерах, их использованию. Каким способом лучше настроить нетбук? С чего предпринимать установку виндовс? Как инсталировать драйвера? Как, например, подбирать нетбук или определенные его компоненты? Каким способом вернуться данные, в случае, если полетел виндовс? И многое другое.

Кроме того намечаются не очень большие видеоуроки о настройках и сервисном обслуживанию компьютера.

Отслеживайте за добавлением новых статей на блог и вы значительно увеличите свое знание о компьютерах.



Все находится <a href=http://mykomp2.ru/2012/04/chto-delat-esli-igra-ne-zapuskaetsa-s-obraza/>на сайте</a> - и вы узнаете что такое компьютер? Каким образом с ним работать? Как его настраивать? И очень многое другое…

2016-08-26 14:02:06
astrapromopt
Разработка, раскрутка в поисковых системах и сео оптимизация web-сайтов. Сопровождение блогов, выручка в интернет, внутренняя оптимизация, партнерские программы. Сео, смо, вконтакт, wordpress, dle и другие CM у нас <a href=http://astrapromo.com/articles/obrabotka-video/obrabotka-video-pri-pomoshhi-mencoder.html>блог</a>

2016-08-20 13:34:20
langspbRak
Наш общеобразовательный центр предоставляет курсы английского разговорного языка для всех желающих в Санкт-Петербурге. Работу со студентами осуществляют как профессиональные русскоязычные преподаватели по английскому, так и носители, хорошо владеющие разговорным языком, именно поэтому на курсах для начинающих стремительно расширите лексический запас. Вы освоите правила грамматики и обучитесь свободно общаться в любой обстановке посещая наши <a href=https://lang-spb.ru/kursy-english.html>курсы английского языка санкт петербург</a>.

Условия обучения

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



<a href=https://lang-spb.ru/kursy-english.html>курсы английского языка в спб</a>

2013-04-04 10:06:03
андрей
ага

2009-09-30 00:08:42
ERR
В статье ошибка


RootData = (RootSize*32 + (BytesPerClust-1)) / BytesPerClust
SectOffset = (N -2)* SectPerClust
AbsSect = Temp + FATSect + RootData + SectOffset

SectPerClust = 1
BytesPerClust = 512
Ваше имя: *
Текст записи: *
Имя:

Пароль:



Регистрация

Вы программируйте ради
денег
15% (31)
славы
4% (8)
удовольствия
33% (68)
знаний
20% (40)
просто так
5% (10)
все вместе
23% (47)

Проголосовало: 204
Я тебя инстальнул - я тебя и убью!
Рейтинг: 7.6/10 (5)
Посмотреть все анекдоты