Студопедия  
Главная страница | Контакты | Случайная страница

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

Boot-сектор

Поскольку дискеты не разбиваются на логические диски, MBR на них отсутствует. Структуры дискеты и логического диска одинаковы и включают в себя следующие элементы:

· Boot-сектор;

· FAT (2 копии);

· Корневой Каталог;

· область данных.

Boot-сектор является самым первым сектором логического диска (номер логического сектора - 0). Для дискеты его физический адрес - дорожка 0, головка 0, сектор 1; для логического диска на жестком диске адрес определяется полями Begin_Hd, Begin_SecTrk соответствующего элемента таблицы разделов. При загрузке системы с дискеты именно этот сектор считывается в память программой POST и выполняет дальнейшую загрузку; при загрузке с жесткого диска этот сектор считывается загрузчиком, содержащимся в MBR. Boot-сектор содержит информацию о физических параметрах диска и о размещении на нем системной информации, используемой далее системой при работе с диском, поэтому даже если дискета и несистемная, то есть, загрузка с нее не выполняется, на ней все равно имеется Boot-сектор с данными о носителе.

Формат Boot-сектора различен для версий DOS до 4.0 и от 4.0 и выше. В программном примере 2 структурой struct BootRec описан Boot-сектор для DOS 4.0 и выше.

/* Структура корневой записи DOS 4.x */

struct RootRec {

byte jmp[3]; /* Переход на загрузку */

char ident[8]; /* Идентификатор системы */

/* Расширенный Блок Параметров BIOS */

/* стандартная часть */

word SectSize; /* Размер сектора (байт) */

byte ClustSize; /* Размер кластера (сект) */

word ResSect; /* Резервных секторов */

byte FatCnt; /* Число копий FAT */

word RootSize; /* Размер корневого оглавления

(число элементов оглавления по 32 байта) */

word TotSecs; /* Общее число секторов */

byte Media; /* Тип диска (то же, что 1-й байт FAT */

word FatSize; /* Размер FAT (секторов) */

/* расширение; следующие 3 поля не входят в BPB

для DOS 3.x, но входят в загрузочную запись */

word TrkSecs; /* Секторов на дорожке */

word HeadCnt; /* Число поверхностей */

word HidnSecL; /* Число спрятанных секторов

(младшая часть) */

/* эта часть имеется только для DOS 4.x и больше */

word HidnSecH; /* (старшая часть) */

/* для диска >32 Мбайт используется вместо TotSecs */

dword LongTotSecs; /* Число секторов */

/* конец расширенного BPB */

byte Drive; /* Физический номер дисковода */

byte reserved1;

byte DOS4_flag; /* Код 41 в этом поле - признак

расширенного формата загр.записи */

dword VolNum; /* Серийный номер тома */

char VolLabel[11]; /* Метка тома */

char FatForm[8]; /* FAT12 или FAT16 */

/* Далее следуют программа и данные загрузки */

} *rt;

Первые 3 байта сектора содержат команду JMP, обеспечивающую переход на программу загрузки. Следующие 8 байт - символьный идентификатор программного средства, производившего форматирование дискеты (диска); если дискета форматировалась системной утилитой FORMAT, там записан номер версии операционной системы. Поле SectSize всегда содержит значение 512. Поле ClustSize показывает, сколько секторов содержится в одном кластере - единице распределения дисковой памяти. Поле ResSect содержит число секторов, расположенных до начала FAT, обычно это 1 - перед FAT имеется только Boot-сектор. Число копий FAT (поле FatCnt) всегда 2. Поле RootSize показывает размер Корневого Каталога, чтобы узнать число секторов в корневом каталоге надо содержимое этого поля разделить на 16. Поле TotSecs - общее число секторов на диске для диска, отформатированного в DOS 4.0 или выше, содержит 0, если число секторов больше 65535, в этом случае число секторов может быть выбрано из поля LongTotSecs. Байт Media идентифицирует тип носителя; возможны такие его значения: 0xFF - 2 стороны, 8 секторов на дорожке; 0xFE - 1 сторона, 8 секторов на дорожке; 0xFD - 2 стороны, 9 секторов на дорожке; 0xFC - 1 сторона, 9 секторов на дорожке; 0xF9 - 2 стороны, 15 секторов на дорожке; 0xF8 - жеский диск. Поле FatSize - число секторов в одной копии FAT. Поля TrkSecs, HeadCnt содержат значения, необходимые для преобразования дискового адреса по формуле 10.1. Поля HidnSecL и HidnSecH для DOS 4.0 и выше можно интерпретировать как одно поле: dword HidnSec - это количество скрытых секторов, упоминавшихся выше. Для DOS ниже 4.0 используется 2-байтное число скрытых секторов - HidnSecL, и на этом область данных Boot-сектора кончается. Поле Drive - номер дисковода, на котором диск форматировался. Поле DOS4_flag содержит код 0x29 (символ ')' - правая скобка), если диск форматировался в DOS 4.0 и выше. Серийный номер тома - случайное число, записываемое в поле VolNum при форматизации, может использоваться в дальнейшем для идентификации диска, как и метка тома (поле VolLabel). Наконец, поле FatForm содержит символьную последовательность 'FAT12' или 'FAT16', в зависимости от формата FAT. После этой системной информации в Boot-секторе записана программа начальной загрузки.

Для версий DOS более ранних, чем 4.0 блок системной информации в Boot-секторе имеет меньший размер - до поля HidnSecL включительно. Поля от SectSize по FatSize включительно образуют так называемый Блок Параметров BIOS (BPB - BIOS Parameter Block), он формируется в оперативной памяти драйвером диска и в дальнейшем используется при всех операциях с данным диском. В DOS 4.0 и выше принят Расширенный BPB - от поля SectSize до LongTotSecs включительно.

Формат Boot-сектора зависит не от версии DOS, установленной на той ПЭВМ, на которой дискета читается, а от версии на той ПЭВМ, где дискета форматировалась. Поскольку формат ранних версий полностью перекрывается форматом поздних, совместимость по носителям сохраняется.

Программа примера 2 демонстрирует чтение Boot-сектора дискеты или логического диска. Boot-сектор считывается средствами DOS как логический сектор 0. Поскольку прерывание 0x25 имеет два варианта применения - в зависимости от объема диска, программа запрашивает объем диска и по-разному готовит исходные данные для чтения сектора. Считанный сектор программа распечатывает - в зависимости от содержимого поля DOS4_flag в формате той или иной версии.

/*== ПРИМЕР 2 ==*/

/*==== Корневой (загрузочный) сектор логического диска ===*/

#include <dos.h>

#define byte unsigned char

#define word unsigned int

#define dword unsigned long

/* Структура корневой записи DOS 4.x */

struct RootRec {

byte jmp[3]; /* Переход на загрузку */

char ident[8]; /* Идентификатор системы */

/* Расширенный Блок Параметров BIOS */

/* стандартная часть */

word SectSize; /* Размер сектора (байт) */

byte ClustSize; /* Размер кластера (сект) */

word ResSect; /* Резервных секторов */

byte FatCnt; /* Число копий FAT */

word RootSize; /* Размер корневого оглавления

(число элементов оглавления по 32 байта) */

word TotSecs; /* Общее число секторов */

byte Media; /* Тип диска (то же, что 1-й байт FAT */

word FatSize; /* Размер FAT (секторов) */

/* расширение; следующие 3 поля не входят в BPB

для DOS 3.x, но входят в загрузочную запись */

word TrkSecs; /* Секторов на дорожке */

word HeadCnt; /* Число поверхностей */

word HidnSecL; /* Число спрятанных секторов

(младшая часть) */

/* эта часть имеется только для DOS 4.x и больше */

word HidnSecH; /* (старшая часть) */

/* для диска >32 Мбайт используется вместо TotSecs */

dword LongTotSecs; /* Число секторов */

/* конец расширенного BPB */

byte Drive; /* Физический номер дисковода */

byte reserved1;

byte DOS4_flag; /* Код 41 в этом поле - признак

расширенного формата загр.записи */

dword VolNum; /* Серийный номер тома */

char VolLabel[11]; /* Метка тома */

char FatForm[8]; /* FAT12 или FAT16 */

/* Далее следуют программа и данные загрузки */

} *rt;

byte buffer[512];

/* Структура параметров для INT 25 при работе с большим

диском (>32 Мбайт) */

struct{

dword first_sect; /* # логического сектора */

word count; /* число секторов */

byte *ptr; /* адрес в памяти */

} parm;

union REGS rr;

struct SREGS sr;

 

main()

{

char drive; /* идентификатор дисковода */

byte sys; /* признак объем > 32 Мбайт */

ASK1: printf("\nУкажите имя диска >");

drive=getche();

if (drive>'b') {

ASK2:printf("\nОбьем лог. диска больше 32 Мбайт? (y/n) >");

sys=getche();

switch(sys) {

case 'y': sys=1; break;

case 'n': sys=0; break;

default: goto ASK2;

}

}

else sys=0;

/* Чтение при помощи прерывания DOS 25 */

rr.h.al=drive-'a'; /* Диск */

if (!sys) {

/* диск < 32 Мбайт */

rr.x.cx=1; /* Секторов 1 */

rr.x.dx=0; /* Логический сектор 0 */

sr.ds=FP_SEG(buffer); /* Адрес буфера в ОП */

rr.x.bx=FP_OFF(buffer);

}

else {

/* диск > 32 Мбайт */

parm.first_sect=0;/* Логический сектор 0 */

parm.count=1; /* Секторов 1 */

parm.ptr=buffer; /* Адрес буфера в ОП */

sr.ds=FP_SEG(&parm); /* Адрес области параметров */

rr.x.bx=FP_OFF(&parm);

rr.x.cx=0xffff;

}

int86x(0x25,&rr,&rr,&sr);

/* Проверка ошибок чтения */

if (rr.x.cflag) {

printf("\nОшибка чтения: %x. ",rr.h.ah);

printf("Нажмите любую клавишу...\n\7"); getch();

exit();

}

rt=(struct RootRec *)buffer;

/* Вывод результатов */

clrscr();

printf("Загрузочная запись дискеты/диска %c:\n",drive-32);

printf("==================================\n\n");

printf("Команда JMP -------------------> ");

for(i=0;i<3;printf("%02x",rt->jmp[i++]));printf("H\n");

printf("Тип носителя ------------------> %02xH\n",

rt->Media);

printf("Система -----------------------> ");

for(i=0;i<8;printf("%c",rt->ident[i++]));printf("\n");

if (rt->DOS4_flag==41)

printf("==== Расширенный блок параметров BIOS ====\n");

else

printf("========== Блок параметров BIOS ==========\n");

printf("Байт в секторе ----------------> %u\n",

rt->SectSize);

printf("Секторов в кластере -----------> %u\n",

rt->ClustSize);

printf("Секторов на дорожке -----------> %u\n",

rt->TrkSecs);

printf("Число головок -----------------> %u\n",

rt->HeadCnt);

printf("Резервных секторов ------------> %u\n",

rt->ResSect);

printf("Скрытых секторов --------------> ");

if (!sys && rt->DOS4_flag==41) printf("%u\n",

rt->HidnSecL);

else printf("%lu\n",(dword)rt->HidnSecL);

printf("Всего секторов ----------------> ");

if (rt->TotSecs>0) printf("%u\n",rt->TotSecs);

else printf("%lu\n",rt->LongTotSecs);

printf("Копий FAT ---------------------> %u\n",

rt->FatCnt);

printf("Секторов в одной FAT ----------> %u\n",

rt->FatSize);

if (rt->DOS4_flag==41) {

printf("Формат FAT --------------------> ");

for(i=0;i<8;printf("%c",rt->FatForm[i++]));

printf("\n");

}

printf("Элементов в корневом каталоге -> %u\n",

rt->RootSize);

if (rt->DOS4_flag==41) {

printf("\nНомер дисковода ---------------> %xH\n",

rt->Drive);

printf("Серийный номер диска ----------> %08xH\n",

rt->VolNum);

printf("Метка тома --------------------> ");

for(i=0; i<11; printf("%c",rt->VolLabel[i++]));

printf("\n");

}

printf("\nНажмите любую клавишу...\n"); getch();

}

FAT

Следом за Boot-сектором на диске расположена FAT. С точки зрения распределения дискового пространства диск разбит на кластеры. Кластер представляет собой группу последовательно расположенных секторов. Если DOS получает запрос на выделение дискового пространства, она выделяет сразу целый кластер. Размер кластера является компромиссом между двумя противоречивыми требованиями: с точки зрения экономии дискового пространства выгоден малый размер кластера, так как для маленького файла (размером даже в один байт) выделяется целый кластер, большая часть которого не используется. Но с другой стороны, при малом размере кластера их на диске получится очень много, и управление ими усложняется. FAT представляет собой "карту" дискового пространства - массив элементов, каждый из которых соответствует одному кластеру диска. Номер элемента соответствует номеру кластера.

Поскольку область диска, содержащая системную информацию, распределена предварительно, она в FAT не отражается. Первые два элемента FAT не используются (первый байт содержит код, совпадающий с полем Media Boot-сектора), нумерация кластеров области данных диска начинается, таким образом, с 2. Размер элемента FAT может быть 12 или 16 бит (см. поле SysCode в элементе раздела жесткого диска, а также поле FatForm в Boot -секторе). Описание содержимого полей далее дается для 12-битного формата FAT, в скобках указываются значения для 16-битного формата. Значения элементов FAT от 2 до 0xFEF (0xFFEF) включительно - информационные значения. Такое значение - номер следующего кластера, распределенного данному файлу. Таким образом, FAT обеспечивает списковую структуру распределения - каждый ее элемент содержит указание на следующий элемент. Поскольку кластеры распределяются файлу по мере его заполнения, файл не обязательно занимает смежные кластеры, FAT может обеспечить связывание в цепочку разнесенных по диску кластеров. Другие значения элементов зарезервированы для системной информации. Значение 0 индицирует свободный кластер. Значения элементов от 0xFF0 до 0xFF6 (от 0xFFF0 до 0xFFF6) - резервные кластеры. Значение 0xFF7 (0xFFF7) - сбойный кластер. Значения от 0xFF8 до 0xFFF (от 0xFFF8 до 0xFFFF) - признак конца цепочки, последнего кластера файла.

Программа примера 3 считывает FAT и распечатывает поэлементно ее начальную часть. Для определения начального сектора и размера FAT программа вынуждена вначале считать в память Boot-сектор так же, как это делалось в предыдущем примере. Для диска, отформатированного в DOS 4.0 или выше программа может определить формат FAT по содержимому поля FatForm Boot-сектора, в противном случае программа запрашивает формат у оператора.

Выборка элемента 12-битной FAT ведется по следующему алгоритму: выбирается слово по смещению i*1,5 от начала FAT, где i - номер кластера; если i четное, содержимое элемента FAT составляют младшие 12 бит этого слова, в противном случае - старшие 12 бит.

Для 16-битной FAT слово по смещению i*2 содержит элемент FAT.

/*== ПРИМЕР 10.4 ==*/

/*========== Чтение Таблицы Размещения Файлов ==========*/

#include <dos.h>

#include <alloc.h>

#define byte unsigned char

#define word unsigned int

#define dword unsigned long

/* Структура корневой записи */

struct RootRec {

byte jmp[3], ident[8];

word SectSize; byte ClustSize;

word ResSect; byte FatCnt;

word RootSize, TotSecs; byte Media;

word FatSize, TrkSecs, HeadCnt, HidnSecL, HidnSecH;

dword LongTotSecs; byte Drive;

byte reserved1, DOS4_flag;

dword VolNum; char VolLabel[11], FatForm[8];

} *rt;

/* Структура параметров для INT 25 */

struct{

dword first_sect;

word count; byte *ptr;

} parm;

union REGS rr;

struct SREGS sr;

main()

{

byte *buff; /* адрес буфера в ОП */

byte sys; /* признак диска > 32 Мбайт */

char drive; /* идентификатор диска */

byte fat16; /* признак 16-битной FAT */

word ss;

int i,k,m,j;

 

ASK1:printf("\nУкажите идентификатор диска (A,B...) >");

drive=getche();

if (drive>'b') {

ASK2:printf("\nОбьем лог. диска больше 32 Мбайт? (y/n) >");

sys=getche();

switch(sys) {

case 'y': sys=1;break;

case 'n': sys=0;break;

default: goto ASK2;

}

}

else sys=0;

buff=(byte *)malloc(512);

/* Чтение boot-сектора */

rr.h.al=drive-'a'; /* Диск */

if (!sys) { rr.x.cx=1; rr.x.dx=0;

sr.ds=FP_SEG(buff); rr.x.bx=FP_OFF(buff); }

else { sr.ds=FP_SEG(&parm); rr.x.bx=FP_OFF(&parm);

parm.first_sect=0; parm.count=1; parm.ptr=buff;

rr.x.cx=0xffff; }

int86x(0x25,&rr,&rr,&sr); readerror();

rt=(struct RootRec *)buff;

/* определение формата FAT */

if (rt->DOS4_flag==41) {

/* для диска, отформатированного в DOS 4 можно

определить формат FAT из Boot-сектора */

if (!memcmp(rt->FatForm,"FAT16",5)) fat16=1;

else fat16=0;

}

else {

ASK3:printf("\nФормат FAT 12-битный? (y/n)");

fat16=getche();

switch(fat16) {

case 'y': fat16=0; break;

case 'n': fat16=1; break;

default: goto ASK3;

}

}

/* Выделение памяти под FAT */

buff=(byte *)realloc(buff,rt->FatSize*512);

if (buff==NULL) { printf("Нехватка памяти\n"); exit(); }

/* Чтение FAT */

rr.h.al=drive-'a';

if (!sys) { /* маленький диск */

rr.x.cx=rt->FatSize;

rr.x.dx=rt->ResSect;

sr.ds=FP_SEG(buff); rr.x.bx=FP_OFF(buff);

}

else { /* большой диск */

parm.first_sect=rt->ResSect;

parm.count=rt->FatSize;

parm.ptr=buff;

sr.ds=FP_SEG(&parm); rr.x.bx=FP_OFF(&parm);

rr.x.cx=0xffff;

}

int86x(0x25,&rr,&rr,&sr); readerror();

clrscr();

/* Форматная распечатка FAT */

printf(" Диск %c: FAT - %d бит\n",

drive-32,fat16*4+12);

printf(" |"); for(i=0;i<10;printf("%5d ",i++));

printf("\n____|____________________________________");

printf("________________________");

for(j=0,i=0,k=0;i<220;i++) {

if (!k) printf("\n%3d |",j);

if (!fat16) {

m=(i*3)/2; ss=*(word *)(buff+m);

if(i%2) /* нечетный элемент */ ss>>=4;

else /* четный элемент */ ss&=0x0fff;

if (ss>0x0fef) printf(" %03xH ",ss);

else printf("%5d ",ss);

}

else {

m=i*2; ss=*(word *)(buff+m);

if (ss>0xffef) printf("%04xH ",ss);

else printf("%5d ",ss);

}

if (++k>=10) { j+=10; k=0; }

}

getch(); free(buff);

}

/*==== Проверка ошибок чтения ====*/

readerror() {

if (rr.x.cflag) {

printf("\nОшибка чтения: %x. ",rr.h.ah);

printf("Нажмите любую клавишу...\n\7"); getch();

exit();

}

}




Дата добавления: 2015-04-11; просмотров: 20 | Поможем написать вашу работу | Нарушение авторских прав

1 | <== 2 ==> | 3 |


lektsii.net - Лекции.Нет - 2014-2024 год. (0.061 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав