TURBO PASCAL |
Новости
|
МОДУЛЬ 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 {AL :« Disk) 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} /»===»===.»=»; |
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |