TURBO PASCAL

Новости

Программы   

Turbo Pascal 

Игры

Документация   

Странности

FAQ

Ссылки

Форум

Гостевая книга

Рассылка

Благодарности

Об авторе

 

 

МОДУЛЬ FJMSK ДЛЯ РАБОТЫ С ДИСКОМ НА ФИЗИЧЕСКОМ УРОВНЕ

Описание модуля см. п.3.3.

/..-»—=..=»==,===^ OHIT F_Disk; ^=-===~-====-^

{

+—————————————————————————————————————+

I Модуль содержит подпрограммы для гибкой работы с дисками. I I Во всех подпрограммах параметр DISK относится к логическим I I дискам: 0=А, 1=В, 2=С, 3=0 и т.д. Параметр SEC - относи- I I тельный номер сектора: О •s загрузочный сектор, далее по I

секторам до конца дорожки, по головкам, по цилиндрам. 1 +---__--_------_------__-------------------------------------+

;

INTERFACE type

{Информация из ВРВ загрузочного сектора:}

ВРВ_Туре = record

SectSiz : Word; {Количество байт в секторе}

ClustSiz: Byte; {Количество секторов в кластере.

ResSecs : Word; {Количество секторов перед FAT}

FatCnt : Byte; (Количество FAT}

RootSiz : Word; (Количество элементов корневого каталога}

TotSecs : Word; {Количество секторов на диске}

Media : Byte; {Дескриптор носителя}

FatSize : Word {Количество секторов в FAT}

end; {BPB_Type}

(Дополнительная информация из загрузочного сектора:} Add_BPB_Type = record

TrkSecs : Word; {Количество секторов на дорожке

для разделов меньше 32 Мбайт или 0}

HeadCnt : Word; (Количество головок}

HidnSecLo: Word; (Количестве спрятанных секторов для разделов меньше 32 Мбайт}

HidnSecHi: Word; (Вместе в HidnSecLo дает количество

спрятанных секторов для разделов больше 32 Мбайт}

LargSectors: Longint; (Общее количество секторов для

разделов больше 32 Мбайт} end; {Add_BPB_Type} {Элемент дискового каталога:} Dir_Type ° record caae Byte of 1: (

Name : arxay [1..8] of Char; (Имя файла или каталога)

Ext : array [1..3] of Char; {Расширение}

FAttr : Byte; (Атрибуты файла}

Reserv: arxay [1..10] of Byte; {Резервное поле}

Time : Word; {Время создания}

Date : Word; {Дата создания}

FirstC: Word; (Номер первого кластера}

Size : Longint {Размер файла в байтах});

2:(NameExt: array [1..11] of Char) end; (Dir_Type}

(Описатель логического раздела} PartType = record

Act: Boolean; (Флаг активности раздела}

BegHead: Byte; (Головка начала раздела}

BegSC : Word; (Сектор/цилиндр начала}

SysCode: Byte; {Системный код}

EndHead: Byte; (Головка конца раздела}

EndSC : Word; (Сектор/цилиндр конца}

RelSect: Longint; (Относительный сектор начала}

FoolSiz: Longint (Объем в секторах} end; {PartType} (Загрузочный сектор диска} PBoot = "TBoot;

TBoot = record case Byte of 0: (

a : array [1..11] of Byte;

BPB: BPB Type;

Add: Add_BPB_Type;

с : array [1..+$1BE-(SizeOf(BPB_Type)+SizeOf(Add_BPB_Type)+11)] of Byte;

Par: array [1..4] of PartType);

1: (b: array [1..512] of Byte) and;

(Описатель диска по структуре lOCTtf !OCTL_Type = xecord

BuildBPB Boolean; (Строить BPB}

TypeDrv Byte; (Тип диска}

Attrib Word; (Атрибуты диска}

Cylindrs Word; (Число цилиндров}

Media Byte; (Тип носителя}

BPB BPB_Type;

Add Add_BPB_Type;

Reserv array [1..10] of Byte;

end;

{Описатель диска! TDisk = record

Number Byte; {Номер диска 0°Л,...}

TypeD Byte; {Тип диска}

AttrD Word; {Атрибуты диске}

Cyls Word; (Число цилиндров на диске)

Media Byte; (Дескриптор носителя)

SectSize Word; (Количество байт в секторе}

TracltSiz Word; {Количество секторов на дорожка}

TotSecs LongInt; {Полная длина в секторах}

Heads Byte; {Количество головок}

Tracks Word; {Число цилиндров на носителе)

ClusSize Byte; (Количество секторов в кластере}

MaxClus Word; {Максимальный номер кластера}

FATLock Word; {Номер 1-го сектора FAT}

FATCnt Byte; {Количество FAT}

FATSize Word; {Длина FAT в секторах}

FAT16: Boolean; {Признак 16-битового элемента FAT}

RootLock Word; {Начало корневого каталога)

RootSize Word; {Количество элементов каталога}

DataLock Word; {Начальный сектор данных) end;

{Список описателей диска} PListDisk = "TListDisk;

TListDisk - record

Disklnfo: TDisk;

NextDisk: PListDisk end;

var

Disk_Error : Boolean; (Флаг ошибки} Disk Status: Word; {Код ошибки} conat

Disks: PListDisk = ШЬ; {Начало списка описателей диска)

function ChangeDiskettefDisk: Byte): Boolean;

{Возвращает TRUE, если изменялось положение запора на указанном приводе гибкого диска)

Procedure FreeListDisk(var List: PListDisk);

{Удаляет список описателей дисков}

Procedure GetAbsSector(Disk,Head: Byte; CSec: Word; var Buf);

{Читает абсолютный дисковый сектор с помощью прерывания $13}

Function GetCluster(Disk: Byte;Sector: Word): Word;

{Возвращает номер кластера по заданному номеру сектора}

Function GetDefaultDrv: Byte;

/Возвращает номер диска по умолчанию)

Procedure GetDirItem(FileName: String; var Item: Dir_Type) ;

^Возвращает элемент справочника для указанного файла)

Procedure GetDirSector(Path: String; var Disk: Byte; var Dirs,DirSize: Word),

{Возвращает адрес сектора, в котором содержится начало нужного каталога, или 0, если каталог не найден. Вход:

PATH - полное имя каталога С', если каталог текущий). Выход:

DISK - номер диска;

DIPS - номер первого сектора каталога или 0;

DIRSIZE - размер каталога (в элементах DIR ТУРЕ).}

Procedure GetDiskInfo(Disk: Byte; var Diskl-nfo: TDisk);

{Возвращает информацию о диске DISK}

Function GetDiskNumber(с: Char): Byte;

{Преобразует юля диска A...Z s номер О...26'. Если указано недействительное имя,возвращает 255}

Function GetFATItem(Dislc: Byte; Item: Word); Word;

{Возвращает содержимое указанного элемента FAT}

Procedure GetIOCTLInfo(Disk: Byte; var l6: юеть_Туре);

{Получить информацию об устройстве согласно общему вызову IOCTL)

Procedure GetListDisk(var List: PLtstDisk);

(Формирует список описателей дисков}

Procedure GetMasterBoot(var But);

/'Возвращает в переменной Buf главный загрузочный сектор}

Function GetMaxDrv: Byte;

{Возвращает количество логических дисков}

Function GetSectorfDisk: Byte;Cluster: Word): Word;

(Преобразует номер кластера в номер сектора}

Function PackCylSec(Cyl,Sec: Word): Word;

(Упаковывает цилиндр и сектор в одно слово для прерывания ?13}

Procedure ReadSector(Disk: Byte; Sec: Longint; NSec: Word; var Buf);

{Читает сектор (секторы) на указанном диске}

Procedure SetAbsSector(Disk,Head: Byte; CSec: Word; var Buf);

{Записывает абсолютный дисковый сектор с помощью прерывания $13}

Procedure SetDefaultDrv(Disk: Byte);

{Устанавливает диск по умолчанию}

Procedure SetFATItemtDiSk: Byte;Cluster,Item: Word);

{Устанавливает содержимое ITEM в элемент CLUSTER таблицы FAT}

Procedure SetMasterBoot(var Buf);

{Записывает в главный загрузочный сектор сеДержимое Buf}

Procedure UnPackCylSec(CSec: Word; var Cyl,Sec: Word);

(Декодирует цилиндр и сектор для прерывания $13}

Procedure WnteSector(Disk: Byte; Sec: Longint; NSec: Word; var Buf);

{Записывает сектор (секторы) на указанный диск}

IMPLEMENTATION

Oses DOS;

var

Reg: registers;

Procedure Output;

(Формирует значения Dislc_Status и Disk_Ercoc)

begin

with Reg do begin

Disk_Error := Flags and FCarry =1;

Disk_Status:= ax end

end; {Output} /——————————————;

Function ChangeDiskette(Disk: Byte): Boolean;

{Возвращает TRUE, если изменялось положение запора на указанном приводе гибкого диска) begin

with Reg do begin

АН := $16;

DL := Disit;

Intr($13, Reg) ;

Output;

ChangeDiskette := Disk_Error and (AH=6) end end; {ChangeDiskett} ^————————————————/

Procedure FreeListDisklvar List: PListDisk);

{Удаляет список дисковых описателей} var

Р: PListDisk;

begin

while List <> Nib do begin

P :a List^.NextDisk;

Dispose(List) ;

List := P end end; {FreeListDisk} ^——.————————————;

Procedure GetAbsSector(Disk,Head: Byte; CSec: Word; var Buf);

{Читает абсолютный дисковый сектор с поыоп^ыо прерывания $13} begin

with Reg do begin

ah :»= 2; {Операция чтения) dl := Disk; {Номер привода} dh := Head; {Номер головки} ex := CSec; {Цилиндр/сектор} a.1 :« 1; (Читать один сектор} es := seg(Buf);

bx := of s (Buf) ;

Intr($13,Reg) ;

Output end end; /GetAbsSector^ ^——————————————;

Function GetCluster(Disk: Byte; Sector: Word): Word;

{Возвращает номер кластера по заданному номеру сектора} var

DI: TDisk;

begin

GetDiskInfo(Disk,DI) ;

if not Disic Error then with DI do

Тексты программ 3)9

if (Sector-DataLock >= 0) and (TotSecs-Sector >= 0) then GetCluster := {Нормальное обращение/

(Sector-DataLock) div ClusSize+2 else

GetCluster := 0 (Неверный номер сектора} else

GetCluster := 0 {Неверный номер диска} end; {GetCluster} ^——————————————/

Function GetDefaultDrv: Byte;

{Возвращает номер диска по умолчанию} begin

with Reg do begin

АН :- $19;

MSDOS(Reg) ;

GetDefaultDrv := AL end end; {GetDefaultDrv) ^——————————„————;

Procedure GetDirItem(FileName: String; var Item: Dir_Type);

{Возвращает элемент справочника для указанного файла} var

Dir: array [1..16] of Dir_Type; {Буфер на 1 сектор каталога}

Path : DirStr; {Маршрут поиска}

NameF: NameStr; {Имя файла}

Ext : ExtStr; {Расширение файла}

Disk : Byte; {Номер диска}

Dies : Word; /Номер сектора}

DirSize: Word; {Размер каталога}

Find: Boolean; {Флаг поиска}

j : Integer; {Номер элемента каталога} {————} Procedure Findltem;

(Ищет нужный элемент в секторах каталога} var

k,i: Integer;

т: array [1..11] of Char; {Массив имени}

Clus: Word; (Номер кластера}

DI: TDisk;

begin

GetDiskInfo(Disk,DI); {Получаем длину кластера}

ReadSector(Disk,Dirs,!,Dir); {Читаем первый сектор}

k := 0; {Количество просмотренных элементов}

j := 1; {Текущий элемент каталога} {Готовим имя и расширение для поиска}

FillChar(m,ll, ' ');

Move(NameF[1],т[1],Length(NameF)) ;

if exto'' then

Move(Ext[2],т[9],Length(ext)-l);

Find := False;

{Цикл поиска}

repeat

if Dir[j] .Nametl^tO than

exit; {Обнаружен конец списка} if (Dir[j].FAttr and $18) = 0 then

begin {Проверяем очередное имя а каталоге} Find := True;

i := 1;

While Find and (i<=ll) do

begin

Find := m[i]=Dir[j].NameExtti];

inc(i) end;

end;

if not Find then inc(j);

if j = 17 then begin

inc (k, 16) ;

if k >= DirSize then

exit; {Дошли до конца каталога} j := 1; {Продолжаем с 1-го элемента

следующего сектора}

if (k div 16) mod DI.ClusSize°0 then if succ(Dirs)<DI.DataLock then

inc(Dirs) (Корневой каталог} else

begin {Конец кластера} {Новый кластер} Clus :=- GetFATItem(Disk,GetCluster(Disk,Dirs));

{Новый сектор} Dirs := GetSector(Disk,Clus) end

else {Очередной сектор - в кластере/ inc(Dirs);

ReadSector(Dislt,Dirs, 1, Dir) end until Find end; {Find.Item} {————} begin (GetDicItem} (Готовим имя файла) FileName := FExpand(FileName);

FSplit(FileName, Path, NameF, Ext);

{Искать каталог} GetDirSector(Path,Disk,Dirs,DirSize);

Find := DirsoO; {Dirs'=0 - ошибка в маршруте} if Find then

Findltem; {Ищем нужный элемент} if Find then begin

(Переносим элемент каталога в Item} Move(Dir[j],Item,SizeOf(Dir_Type)) ;

{Сбросить ошибку} Disk Error := False end else

begin {Файл не найден} Disk_Error := True;

Disk_Status := $FFFF end end; tGetDirItem} ^———————————————;

Procedure GetDirSector(Path: String; var Disk: Byte; var Dirs,DirSize: Word);

(Возвращает адрес сектора, в котором содержится начало нужного каталога, или 0, если каталог не найден. Вход:

PATH - полное имя каталога ('', если каталог - текущий

DISK - номер диска;

DIRS - номер первого сектора каталога или О/ DIRSIZE - размер каталога (в элементах DIR_TYPE).} var

i,j,k Integer; {Вспомогательные переменные 1 Find Boolean; {Признак поиска) m array [1..11] of Char; {Массив имени каталога} s String; {Вспомогательная переменная} DI TDisk; {Информация о диске} Dir array [1..16] of Dir_Type; {Сектор каталога} Clus Word; {Текущий кластер каталога} label err;

begin

{Начальный этап: готовим путь к каталогу и диск} if Path = '' then {Если каталог текущий,}

GetDir(0,Path); {дополняем маршрутом поиска} if Path[2] о ':' then {Если нет диска,}

Disk := GetDefaultDrv {берем текущий} else

begin {Иначе проверяем имя диска} Disk :» GetDiskNumber(Path[l]);

if Disk-255 then

begin {Недействительное имя диска} Err: {Точка выхода при неудачном поиске}

Dirs := 0; {Нет сектора} Disk_Error :" True; {Флаг ошибки} Disk_Status :- $FFFF; {Статус fFFFF} exit end;

Delete(Path,1,2) {Удаляет имя диска из пути} end;

{Готовим цикл поиска]

if Path[l]='\' then {Удаляем символы \}

Delete(Path,I,1); /в начале} if Path[Length(Path)] = '\' then

Delete(Path,Length(Path),1); {и конце маршрута} GetDiskInfo(Disk,DI) ;

with DI do begin

Dirs := RootLock; {Сектор с каталогом} DirSize :" RootSize {Длина каталога} end;

ReadSector(Disk,Dirs,1,Dir); {Читаем корневой каталог} Clus := GetCluster(Disk,Dirs); {Кластер начала каталога} {Цикл поиска по каталогам}

Find :- Path"''; {Path-'' - конец маршрута} while not Find do begin

{Получаем в S первое имя до символа \} s := Path;

if pos('\',Path) <> 0 then

s[0] :-chr(post'\',Path)-1);

{Удаляем выделенное имя из маршрута) Delete(Path,I,Length(s)) ;

if Path[l]»'\' then

Delete (Path,1,1); '.Удаляем разделитель \} {Говим массив имени} FillChar(m,ll, ' '):

move(s[1],m,ord(s[0]));

(Просмотр очередного каталога}

k := 0; {Количество просмотренных элементов каталога) j :° 1; (Текущий элемент в Die} repeat (Цикл поиска в каталоге} if Dir[j],Name[l]=#0 then {Если имя}

Goto Err; {начинается с 0 - это конец каталога} if Dir(j].FAttr=Directory then begin

Find := True;

i :» 1;

while Find and (i<=ll) do

begin {Проверяем иыя] Find := m[i]=Dir[j] .NameExt[i];

inc(i) end end;

if not Find •then inc(j);

if j = 17 then

begin {Исчерпан сектор каталога} j :« 1; {Продолжаем с J--I'O элемента

следующего сектора} inc(k,16); (k - сколько элементов просмотрели} if k >= DirSize then

goto err; (Дошли до конца каталога} if (k div 16) mod DI.ClusSize=0 then

begin {Исчерпан кластер - ищем следующий} {Получаем новый кластер} Clus := GetFATItem(Disk,Clus);

{Можно не проверять на конец цепочки, т.к. каталог еще не исчерпан} {Получаем новый сектор/ Dirs := GetSector(Disk,Clus) end else (Очередной сектор -}

inc(Dirs); текущем кластере} ReadSector(Disk,Dirs,l,Dir);

end until Find;

{Наден каталог для очередного имени в маршруте}

Clus := Dir[j].FirstC; {Кластер начала} Dirs := GetSector(Disk,Clus); {Сектор} ReadSector(Disk,Dirs,l,Dir);

Find := Path = '' {Продолжаем поиск,

если не исчерпан путь} end {while not Find} end; {GetDlrSector} ^————————————————/

Procedure ReadWriteSector(Disk: Byte;

Sec: LongInt; NSec: Word; var Buf; Op: Byte); forward;

Procedure GetDiskInfo(Disk: Byte; var Disklnfo: TDisk);

{Возвращает информацию о диске DISK} var

Boot: TBoot;

I!. : IOCTL_Type;

p: PListDisk;

label

Get;

begin

Disk_Error := False;

if (Disk<2) or (Disks=NIL) then

goto Get; {He искать в списке, если дискета или нет списка} {Ищем в списке описателей} р := Disks;

while (р".Disklnfo.NumberODisk) and (p^.NextDiskoNIb) do

p := p^.NextDisk; (Если не тот номер диска} if p'\.DiskInfo.Number=Disk then

begin (Найден нужный элемент - выход} Disklnfo := p^DiskInfo;

exit end;

(Формируем описатель диска с помощью вызова IOCTL} Get:

IO.Build.BPB := True; (Требуем построить ВРВ} GetIOCTLInfo(Disk,10); (Получаем информацию} If Disk_Error then exit;

with Disklnfo, 10 do {Формируем описатель, begin

Number a= Disk;

TypeD == TypeDrv;

AttrD - Attrib;

Cyls = Cylindrs;

Media - BPB.Media;

SectSize - BPB.SectSiz;

TrackSiz = Add.TrkSecs;

TotSecs ч BPB.TotSecs;

if TotSecs=0 then

begin (Диск большой емкости}

ReadWriteSector(Number,0,1,Boot,2); (Читаем загрузочный сектор} TotSecs :•" Boot.Add.LargSectors;

end;

Heads = Add.HeadCnt;

Tracks = (TotSecs+pred(TrackSiz)) div (TrackSiz*Heads);

ClusSize = BPB.ClustSiz;

FATLock - BPB.ResSecs;

FATCnt = BPB.PatCnt;

FATSize - BPB.FatSize;

RootLock = FATLock+FATCnt*FATSize;

RootSize » BPB.RootSiz;

DataLock = RootLock+(RootSize*SizeO?(Dir_Type)) div SectSize;

MaxClus = (TotSecs-DataLock) div ClusSize+2,-fAT16 - (MaxCius > 4086) and (TotSecs > 20790) end end; (GetDiskInfof /———————.———————/

Function GetDiskNumber(c: Char): Byte;

(Преобразует имя диска A...Z в номер О...26. Если указано недействительное имя, возвращает 255} var

DrvNumber: Byte;

begin

ifOpCase(c) in ['A'..'2'] then

DrvNumber :« ord(UpCase(c))-ord('A')

else

DrvNumber := ^55;

if DrvNumber > GetHaxDrv then

DrvNumber := 255;

GetDiskNumber := DrvNumber;

end; {GetDiskNumber} /——_-——_————-.———;

Function GetFATItem(Disk: Byte;Item: Word): Word;

fBosBpastae'r содержимое указанного элемента FAT} var

DI : TDisk;

k,j,n: Integers-Fat : record case Byte of 0: (w: array [0..255] of Word);

1: (b: array [0..512*3-1] of Byte);

end;

begin

GetDiskInfo(Disk,DI) ;

if not Dislc_Error then with DI do begin

if (Item > MaxClus) or (Item < 2) then

Item := $FFFF {Задан ошибочный номер кластера) else begin

if FAT 16 then begin

k := Item div 256; {Нужный сектор FAT} j := Item mod 256; {Смещение в секторе} n := 1 {Количество читаемых секторов) end else begin

k :° Item div 1024; {Нужная тройка секторов FAT} j :~ (3*Item) аЪх 1-)t*1536; {Смещение в секторе} п := 3 {Количеетво читаемых секторов/ end;

{Чихаем 1 или 3 сектора FAT} ReadSector (Disk, FATLock+lc*n, n, Fat) ;

it not Disk_Error then begin

if FAT 16 then

Item :» Fat.wtj] else begin

n := Item; {Старое значение Item для проверки четности} Item := Fat.b[j]+Fat.b[j+l] shi 8;

if odd(n) than

Item :~ Item shr 4 else

Item :" Item and $FFF;

if Item > $FF6 then

Item :-- $FOOO+Item end;

GetFatItem := Item end end end end; {GetFATItemf /———————————————;

procedure GetIOCTLInfo(Disk: Byte; var 10: IOCTL__Type);

{Получает информацию об устройстве согласно общему вызову IOCTL}

begin

with Reg do begin

ah :•" $44; {Функция 44}

al := $OD; (Общий вызов lOCTLf

cl := $60; {Дать параметры устройства}

ch := $8; (Устройство - диск)

Ы :- Di.sk+1; {Диск 1=А,..)

bh := 0;

ds := seg(IO) ;

dx := of s(IO) ;

MSDOS(Reg);

Output end

end; {GetIOCTLInfo)

{—.— —_———_-_————/

Procedure GetListDisk(var List: PListDisk);

{Формирует список дисковых описателей} var

Disk: Byte;

DI : TDisk;

P,PP: PListDisk;

begin

Disk := 2; {Начать с диска С:} List MIL;

repeat

GetDiskInfo(Disk,DI);

if not Disk_Error then begin New(P) ;

if List=MII. then

List := P else

PP^.NextDisk := P;

with P" do begin

DiskInfo := DI;

NextDisk := HXL;

inc(Disk) ;

PP := P end end until Disk_Error;

Disk_Error := False end; {GetListDiskf ^—————————————;

Procedure GetMasterBoot(var But) ;

(Возвращает в переменной Buf главный загрузочный сектор} begin

GetAbsSector($80,0,l,Buf) end; {GetMasterBoot} {— ———————— ————

Function GetMaxDrv: Byte;

{Возвращает количество логических дисков) consfc

Мах: Byte =0;

->egin

if Max=0 then with Reg do begin

ah := $19;

MSDOS(Reg) ;

ah :=• $OE;

dl := al;

MSDOS(Reg) ;

Max := al end;

GetMaxDrv := Max end; {GetMaxDrv} /———————————.——-J;

function GetSector(Disk: Byte; Cluster: Word): Word;

{Преобразует номер кластера в номер сектора} var

DI: TDisk;

begin

GetDiskInfo(Disk,DI) ;

if not Disk Error then with DI do begin

Disk_Error := (Cluster > MaxClus) or (Cluster < 2);

if not Disk_Error then

GetSector := (Cluster-2)*ClusSize +DataLock end;

if Disk_Error then

GetSector := $FFFF end; {GetSector} ^————————————————;

Function PackCylSec(Cyl,Sec: Word): Word;

{Упаковывает цилиндр и сектор в одно слово для прерывания $13}

begin

PackCylSec := Sec+(Cyl and $300) shr 2+(Cyl shi 8) end; {CodeCylSec} ^————————————————;

Procedure ReadWriteSector(Disk: Byte;

Sec: Longint; NSec: Word; var Buf; Op: Byte);

(Читает или записывает сектор (секторы):

Op = 0 - читать; 1 - записать (малый диск)

= 2 - читать; 3 - записать (большой диск)} type

TBufO "2 record

StartSec: Longint;

Sees: Word;

AdrBuf: Pointer end;

var

BufO: TBufO-S: Word;

0: Word;

begin

if Op>l taen with BufO do begin

{Готовим ссылочную стр'^туру для большого диска} AdrBuf := Ptr(Seg(Buf) ,0?s (Buf) ) ;

StartSec := Sec;

Sees := NSec;

S := Seg(BufO) ;

0 := Ofs(BufO) ;

asm

mov CX,$FFFF nio"v й.Ь f ^ly

shr ИХ,1 mov AL, Disit push DS push BP mov BX,0 mov DS,S jc @1 int 25H jmp @2 @1: int 26H @2: pop DX pop BP pop DS mov BX,1 jc @3 mov BX,0 xor AX,AX @3: mov Disk Error,BL

mov Disk Status,AX end end

else (Обращение к диску малой емкости} aSm

mov DX, Word Ptr Sec {DX := Sec/ mov CX,NSec {CX := NSec} push DS {Сохраняем DS - он будет испорчен} push BP {Сохраняем BPi ids BX,Buf {DS:BX - адрес буфера} mov AL,Op {AL := Op} shr AX,1 {Переносим младший бит Op в CF{ mov AL,Disk {ALDisk) jc @Write {Перейти, если младший бит ОроО} int 25H {Читаем данные} jmp @Go {Обойти запись} eWRITE:

int 26H (Записываем данные} SGO:

pop DX {Извлекаем флаги из стека) pop BP {Восстанавливаем BP} pop DS {Восстанавливаем DS} mov BX,1 {BX := True} jc @Exit {Перейти, если была ошибка} mov BX,0 {BX :~ False} xor AX, AX {Обнуляем код ошибки} QEXIT:

mov Disk_Error,BL {Флаг ошибки взять из BX} mov Disk Status,AX {Код ошибки вять из АХ} end

end; {ReadKriteSector} ^——-.—„——.——————/

Procedure ReadSectoriDisk: Byte; Sec: Longint; NSec: Word; var Buf);

{Читает сектор (секторы) на указанном диске) v^x

Dl: TDisk;

begin

GetDiskInfo(Disk,DI) ;

if Dl.TotSecs > $FFFF then {Диск большой емкости?} ReadWriteSector(Dislt,Sec,Nsec,Buf,2) {-Да: операция 2}

else

ReadWriteSector(Disk,Sec,Nsec,Buf,0) {-Нет: операция 0}

end; {ReadSector} /-———————————————/

Procedure SetAbsSector(Disk,Head: Byte; CSec: Word; var Buf);

{Записывает абсолютный дисковый сектор с помощью прерывания $13} begin

with Reg do begin

ah := 3; (Операция записи} dl :° Disk; (Номер привода} dh := Head; (Номер головки} ex := CSec; {Цилиндр/сектор} al := 1; (Читаем один сектор} es := seg(Buf) ;

bx :- ofs(Buf) ;

Intr($13,Reg);

Output end end; /SetAbsSector/ ^———————————————;

Procedure SetDefaultDrvfDisk: Byte);

(Устанавливает диск по умолчанию} begin

if Disk <= GetMaxDrv then with Reg do begin

AH :=» $E;

DL := Disk;

MSDOS(Reg)

end end;

_———————————————;

Procedure SetFATItemfDisk: Byte;Cluster,Item: Word) ;

(Устанавливает содержимое ITEM в элемент CLUSTER таблицы FAT} var

DI : TDisk;

k,j,n: Integer;

Fat: record case Byte of 0: (w: array [0..255] of Word);

1: (b: array (0..512*3-1] of Byte) ;

end;

begin

GetDiskInfo(Disk,DI) ;

if not Disk_Error then with DI do begin

if (Cluster <= MaxClus) and (Cluster >=• 2) then begin

if FAT16 then

begin

k := Cluster div 256; (Нужный сектор FAT}

j := Cluster mod 256; (Смещение в секторе}

n :» 1 end else begin

k := Cluster div 1024; {Нужная тройка секторов FAT}

j := (3*Clu3ter) shr 1-k*1536;

n :° 3 end;

ReadSector (Disk, FATLoc]<+k*n,n,Fat) ;

if not Disk_Error then begin

if FAT 16 then

Fat.w[j] := Item else begin

if odd(Cluster) then

Item :- Item ehl 4 +Fat.b[j] and $F else

Item := Item+(Fat.b[j+l] and$FO) shi 12;

Fat.b[j] := Lo(Item) ;

Fat.b[j+l] Hi(Item) end;

if not FAT16 then

begin {Проверяем "хвост" FAT} k := k*n; {k - смещение сектора} while k+n > FatSize do dec(n) end;

inc(FATLock,k); (FATLock - номер сектора в FAT} {Записываем изменение в FatCnt копий FAT) for k := 0 to pred(FatCnt) do

WriteSectortDisk,FATLock+k*FatSize,n,Fat) end end end end; {SetFATItem} ^——————————————;

Procedure SetMasterBoot(var Buf);

{Записывает в главный загрузочный сектор содержимое Buff begin

with Reg do begin

ah := 3; {Операция записи}

al := 1; (Кол-во секторов}

dl :- $80; {1-й жесткий диск)

dh := 0; {Головка 01

сх := 1; (1-й сектор 0-й дорожки}

es := seg(Buf) ;

bx := ofs (Buf) ;

Intr($13, Reg);

Disk_Error := (Flags and FCarry о 0);

if Disk_Error then

Disk_Status :~ ah else

Disk_Status := 0 end end; {SetMasterBoot} ^-__—————————————;

Procedure UnpackCylSec(CSec: Word; var Cyl,Sec: Word);

{Декодирует цилиндр и сектор для прерывания $13} begin

Cyl := (CSec and 192) shi 2+CSec she 8;

Sec := CSec and 63 end; {RecodeCylSec} /-——————————————;

Procedure WriteSector(Disk: Byte; Sec: Longint; NSec: Word; var Buf);

{Записывает сектор {секторы) на указанный диск) var

DI: TDisk;

begin

CctDiskInfo(Disk,DI) ;

if Dl.TotSecs > $FFFF then

ReadWriteSector(Disk,Sec,Nsec,Buf,3) else

ReadWriteSector(Disk,Sec,Nsec,Buf,1) ;

end; {ReadSectorf ! ===========; end. {Unit F_Disk} /»===»===.»=»;

 

 Оглавление

На первую страницу

Rambler's Top100 Rambler's Top100
PROext: Top 1000

(с)Все права защищены

По всем интересующим вопросам прошу писать на электронный адрес

Hosted by uCoz