W poprzedniej części omawiane były uniwersalne wywołania funkcji. Oto pozostałe.
Funkcja 27h - umożliwia swobodny odczyt jednego lub wielu rekordów ze zbioru dyskowego i zapisanie ich do obszaru DTA. Rejestry DS:DX wskazują na blok FCB, w którym podana jest nazwa zbioru (przemieszczenie 01h), jej rozszerzenie (przemieszczenie 08h) oraz numer pierwszego rekordu (przemieszczenie 21h do 24h). Rejestr CX zawiera liczbę odczytywanych rekordów i musi być różny od 0. Po powrocie z wywołania funkcji rejestr AL zawiera kod błędu w takim samym formacie jak dla funkcji 14h lub 21h (odczyt sekwencyjny lub swobodny jednego rekordu), zaś CX - liczbę faktycznie przeczytanych rekordów. W przeciwieństwie do funkcji 21h, uaktualniany jest numer rekordu przy dostępie swobodnym (przemieszczenie 21h ... 24h) - przyjmowany jest numer rekordu następnego po ostatnim odczytanym. Jednocześnie uaktualniane są wskaźniki wykorzystywane przy dostępie sekwencyjnym : numer bloku (przemieszczenie 0Ch ... 0Dh) i numer rekordu w ramach bloku (przemieszczenie 20h).
Funkcja 28h - umożliwia swobodny zapis jednego lub wielu rekordów do zbioru dyskowego. Nazwa zbioru i jej rozszerzenie oraz numer pierwszego rekordu podawane są w bloku FCB, wskazywanym przez rejestry DS:DX, zaś liczba rekordów - w rejestrze CX. Umieszczenie wartości 0 w rejestrze CX sygnalizuje, że przetwarzany zbiór ma się kończyć przed wyspecyfikowanym rekordem. Umożliwia to w prosty sposób zwalnianie miejsca na dysku, gdy końcowa część zbioru przestaje być potrzebna. Po powrocie z wywołania funkcji rejestr AL zawiera kod błędu o takim samym znaczeniu, jak przy funkcji 15h lub 22h (zapis sekwencyjny lub swobodny jednego rekordu), zaś CX - faktyczną liczbę zapisanych rekordów. Uaktualniane są: numer rekordu przy dostępie swobodnym, numer bloku i numer rekordu w ramach bloku przy dostępie sekwencyjnym. Uwaga : po otwarciu zbioru (za pomocą funkcji 0Fh) w pole FCB o przemieszczeniu 0Eh i 0Fh otwieranego zbioru wpisywana jest wielkość rekordu wynosząca 128 bajtów. Wpisując w to pole inną wartość można zmieniać rozmiar rekordu. Często wpisuje się wartość 1 i wówczas przy każdym odczycie lub zapisie rekordu przesyłany jest jeden bajt. Obszar transmisji dyskowych (DTA) można zmieniać za pomocą funkcji 1Ah.
Funkcja 29h - analizuje wprowadzony z urządzenia wejściowego wiersz polecenia, poszukując specyfikacji zbiorów w postaci DRIVE:FILENAME.EXT, gdzie DRIVE jest symbolem napędu dyskowego, zaś FILENAME i EXT są nazwą zbioru i jej rozszerzeniem. Funkcja nie pozwala na podawanie ścieżki dostępu (ang. pathname). Rejestry DS:SI wskazują obszar pamięci, w którym znajduje się analizowany ciąg znaków, rejestry ES:DI - obszar pamięci, w którym w razie znalezienia zbioru system tworzy nie otwarty blok FCB. Bity 0 ... 3 rejestru AL określają sposób analizowania ciągu znaków :
- Bit 0 równy 1 - sprawia, że pomijane są początkowe separatory (tabulacja, spacja, plus i przecinek), bit 0 równy 0 oznacza, że specyfikacja pliku rozpoczyna się bezpośrednio pod adresem DS:SI;
- Bit 1 równy 1 - sprawia, że bajt zawierający numer napędu (przemieszczenie 00h) będzie zmieniony tylko wówczas, gdy numer napędu został podany w specyfikacji zbioru. Dzięki temu blok FCB może mieć wpisany przez programistę własny domyślny numer napędu, inny niż systemowy;
- Bit 2 równy 1 - sprawia, że blok FCB jest zmieniany tylko w razie podania prawidłowo skonstruowanej nazwy zbioru. Dzięki temu w programach można używać domyślnych nazw zbiorów, które mogą być zastąpione innymi bezpośrednio podanymi nazwami;
- Bit 3 równy 1 - sprawia, że blok FCB jest zmieniany tylko w razie podania prawidłowo skonstruowanego rozszerzenia nazwy zbioru. Symbol wieloznaczny "*" zastępowany jest wynikającą z kontekstu liczbą symboli wieloznacznych "?". Po powrocie z wywołania funkcji zawartość rejestru AL świadczy o wyniku analizy :
- AL = 00h - oznacza znalezienie jednoznacznie określonego zbioru;
- AL = 01h - oznacza znalezienie zbioru określonego za pomocą nazwy wieloznacznej;
- AL = FFh - świadczy, że nie znaleziono zbioru o podanej nazwie lub źle go wy specyfikowano;
Wartość rejestrów DS:DI (praktycznie tylko rejestr SI) jest zmieniana w ten sposób, że wskazuje na pierwszy bajt za przeanalizowanym ciągiem znaków. Umożliwia to ewentualne bezpośrednie przejście do analizy kolejnej specyfikacji zbioru.
Funkcja 2Fh - przekazuje w rejestrach ES:BX adres aktualnego obszaru transmisji dyskowych (DTA). Została ona wprowadzona dopiero w wersji 2.0 MS-DOS, jednak dla użytkowników funkcji rozszerzonych nie ma większego znaczenia (gdyż nie odwołują się oni do DTA).
Organizacja logiczna dysków
Większą część dysku zajmują dane zapisane w zbiorach niezbędny jest jednak pewien obszar na informacje organizujące dane w spójną całość. Dysk podzielony jest logicznie na kilka pól, a liczba sektorów w każdym z pól zależy od formatu dyskietki (tab. 1). Istnieją też inne, nie opisane w tabeli formaty (w szczególności formaty dla dysków sztywnych). Można je stosować po przyłączeniu odpowiedniego programu sterującego (ang. device driver).
Informacja wchodząca w skład zbioru dyskowego umieszczana jest w polu danych poszczególnych sektorów. Dla zredukowania rozmiarów tablicy, w której rejestrowane są informacje o położeniu kolejnych fragmentów zbioru postanowiono stworzyć grupy sektorów czyli tzw. jednostki alokacji (ang. cluster). Klaster* może się składać z jednego lub z kilku sektorów - zależy to od formatu dysku (tab. 2). Zbiór nie może więc zajmować na dysku mniej miejsca niż zajmuje jednostka alokacji.
| Tabela 1. Liczba sektorów w poszczególnych polach dla standardowych formatów dyskietek | |||||||||
| Średnica Dyskietki | 5.25'' | 8'' | |||||||
| Gęstość zapisu | podwójna | poczwórna | pojedyncza | pojedyncza | podwójna | ||||
| Pola zarezerwowane | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 4 | 1 |
| Pierwsza kopia FAT | 1 | 2 | 1 | 2 | 5 | 7 | 6 | 6 | 2 |
| Druga kopia FAT | 1 | 2 | 1 | 2 | 5 | 7 | 6 | 6 | 2 |
| Katalog główny | 4 | 4 | 7 | 7 | 7 | 14 | 17 | 17 | 6 |
| Pole zbiorów | 313 | 351 | 630 | 708 | 1422 | 2371 | 1972 | 1969 | 605 |
--- * --- * ---
| Tabela 2. Parametry standardowych formatów dyskietek | |||||||||
| Średnica Dyskietki | 5.25'' | 8'' | |||||||
| Gęstość zapisu | podwójna | poczwórna | pojedyncza | pojedyncza | podwójna | ||||
| Liczba sektorów na ścieżce | 8 | 9 | 8 | 9 | 9 | 15 | 26 | 26 | 8 |
| Liczba bajtów w sektorze | 512 | 512 | 512 | 512 | 512 | 512 | 128 | 128 | 1024 |
| Liczba stron | 1 | 1 | 2 | 2 | 2 | 2 | 1 | 1 | 2 |
| Liczba ścieżek na stronie | 40 | 40 | 40 | 40 | 80 | 80 | 77 | 77 | 77 |
| Liczba sektorów w jednostce alokacji | 1 | 1 | 2 | 2 | 2 | 1 | 4 | 4 | 1 |
FAT - tablica alokacji zbiorów
Informacja o klastrach składających się na poszczególnezbiory (lub jeszcze nie zapisanych jest w FAT (ang. file allocation table - tablica alokacji zbiorów). Dla większego bezpieczeństwa danych na dyskietce przechowuje się co najmniej dwie identyczne tablice alokacji.
Tabela 3. Znaczenie wartości zapisywanych w FAT
Zawartość
pozycji w Status klastra w polu dysku przeznaczonym dla zbiorów
Fat
000 Klaster nie jest zapisany
FF7 Klaster zawiera uszkodzony sektor
FF8h ... FFFh Ostatni klaster w zbiorze dyskowym
XXX Każda inna wartość jest numerem pozycji FAT
odpowiadającej następnemu klastrowi zbioru
--- * --- * ---
Tabela 4. Możliwe funkcje pozycji katalogu dyskowego
Kody dla 2 pocz. Funkcja pozycji katalogu
bajtów (HEX)
2E2E Kody te (znak kropli w kodzie ASCII)oznaczają
odwołanie do katalogu nadrzędnego. W tym wypadku
bajty o przemieszczeniu 1Ah...1Bh względem
początku danej pozycji katalogu zawierają numer
pozycji w FAT odpowiadającej pierwszemu klastrowi
zawierającemu katalog nadrzędny (000 jeśli jest
to katalog główny).
2E20 Kropka i spacja oznaczają odwołanie do bieżącego
katalogu (czyli zawierającego te pozycję).
bajty 1Ah...1Bh wskazują na pierwszą grupę
sektorów zawierających ten katalog.
00xx Dana pozycja nie była jeszcze nigdy używana
E5xx Pozycja była używana, ale zbiór został
skasowany.
inny kod Pierwszy znak nazwy. Pozycja jest odwołaniem
(znak ASCII) do zbioru (który w szczególności może być
katalogiem podrzędnym) albo zawiera etykietę
nośnika (tylko w przypadku katalogu głównego).
Do dalszego rozróżnienia (plik czy etykieta
nośnika) służy atrybut pliku (bajt o
przemieszczeniu 0Bh).
Pole tablicyFAT podzielone jest na szereg 12-bitowych pozycji, numerowanych od 0. Dwie początkowe pozycje (0 i 1), zajmują w sumie 24bity, czyli 3 bajty. Pierwszy bajt to tzw. deskryptor formatu nośnika (tab. 2), umożliwiający identyfikacje formatu stosowanej dyskietku, dwa dalsze - są równe FFh.
Pozostałe 12-bitowe pozycje FAT odpowiadają poszczególnym jednostkom alokacji dla pola przeznaczonego na zbiory : pozycja 2 - pierwszemu klastrowi, pozycja 3 - drugiemu itd. 12-bitową zawartość kazdej pozycji można wyrazić za pomocą trzech cyfr szesnastkowych. Jesli dany klaster w polu zbiorów nie jest zapisany, to odpowiadająca mu pozycja FAT ma wartość 000. Po zapisaniu klastra odpowiadająca mu pozycja w FAT zmienia wartość (tab. 3).
Wartości zapisywane w kolejnych lokacjach FAT umożliwiają nie tylko rozróżnienie, które klastry są zajęte, a które wolne, lecz także pozwalają na odnalezienie kolejnych grup składających się w zbiór. W każdym katalogu wśród informacji opisujących dany zbiór znajduje się m.in. numer pozycji w FAT. odpowiadającej pierwszemu klastrowi zbioru. Pozycja ta zawiera numer pozycji opisującej następny klaster zbiory lub wartość FF8h...FFFh, gdy jest to ostatni klaster (tab.3). Dla zbiorów składających się z wielu klastrów powstaje struktura listowa, zaczynająca się w skorowidzu i przebiegająca przez pozycje FAT odpowiadające kolejnym klastrom należącym do zbioru.
Organizacja katalogów
Katalog główny nie jest zbiorem dyskowym, lecz zajmuje określone miejsce na dysku i ma stałą długość, zależną od formatu dysku (tab.1). Katalogi podrzędne są zbiorami i mają podobną budowę jak katalog główny, ale ich długość nie jest ograniczona. gdyż (w przeciwieństwie do katalogu głównego) mogą zajmować wiele klastrów. Katalog główny składa się więc z określonej liczby pozycji (tab.2). Natomiast w katalogu podrzędnym liczba pozycji jest ograniczona tylko przez pojemność nośnika. O rodzaju informacji zawartej w danej pozycji katalogu decyduje jej pierwszy (i ewentualnie drugi) bajt (tab.4). Opis poszczególnych pól występujących w każdej pozycji katalogu przedstawiono w tabeli 5.
Wyszukiwanie sektorów należących do zbioru dyskowego
Przez odczytanie deskryptora nośnika można określić format dysku. Jest to konieczne przed rozpoczęciem wyszukiwania sektorów logicznych należących do danego zbioru. Deskryptor nośnika jest pierwszym bajtem w FAT, czyli pierwszym bajtem za obszarem zarezerwowanym (na dyskietkach 5,25'' pierwszym bajtem sektora 1). Można go odczytać posługując się programem DEBUG lub za pomocą funkcji systemowych 1Bh lub 1Ch.
Znając format dysku i jego parametry (tab. 1 i 2), można określić numery numery sektorów zawierających tablicę FAT oraz numer pierwszego sektora pola przeznaczonego dla zbiorów. Teraz, z pozycji katalogu opisującej dany zbiór, można odczytać numer pozycji FAT odpowiadającej pierwszej grupie sektorów składających się na zbiór. Następnie trzeba zlokalizować pozycje w FAT, odpowiadające kolejnym klastrom zbioru. Należy w tym celu wykonać czynności :
- numer zapisany w bieżącej pozycji tablicy FAT pomnożyć przez 1.5 (każda pozycja ma 12 bitów, czyli zajmuje półtora bajta);
- część całkowita wyniku jest przemieszczeniem w tablicy FAT określającym położenie 2-bajtowego słowa zawierającego informację o następnej grupie sektorów;
- jeśli bieżąca pozycja w FAT ma numer nieparzysty, należy wziąć 12 mniej znaczących bitów wyszukiwanego słowa; w przeciwnym wypadku 12 bardziej znaczących bitów;
- jeśli otrzymana w ten sposób liczba jest równa FF8h...FFFh, zbiór nie ma więcej klastrów. W przeciwnym razie liczba ta jest numerem pozycji w FAT odpowiadającej następnej grupie sektorów zbioru.
Aby na podstawie numeru pozycji w FAT określić numery logiczne sektorów wchodzących w skład klastra, należy :
- odjąć 2 od numeru pozycji FAT (bo pozycja w FAT odpowiadająca pierwszemu klastrowi ma numer równy 2);
- pomnożyć wynik przez liczbę sektorów składającą się w danym formacie na grupę;
- dodać do wyniku numer sektora, od którego rozpoczyna się obszar przeznaczony na zapis zbiorów.
Uzyskuje się w ten sposób numer pierwszego z sektorów wchodzących w skład danego klastra.
UWAGA : Jeśli format dysku nie jest znany, to :
- funkcje 1Bh i 1Ch pozwalają odczytać deskryptor nośnika i położenie początku FAT;
- funkcja 36h pozwala określić długość FAT (zawartość rejestru DX pomnożona przez 1.5);
- początek pola przeznaczonego dla zbiorów można znaleźć zapisując na czysty dysk znany zbiór i sprawdzając gdzie został zapisany.
*) - Dokładne tłumaczenie angielskiego słowa cluster (grono lub kiść) nie nadaje się do wykorzystania w polskich tekstach. Inne słowa, takie jak zlepek, porcja lub grupa nie są oczywistymi odpowiednikami tzn. nie każdy zorientuje się, że chodzi o "cluster". Podobny problem mieli też fizycy zajmujący się astronomią i ... wprowadzili do swojego języka spolszczenie klaster.
Opr. wg mc 2/1986 i Norton P. "Programer's Guide to the IBM PC".
Zbigniew Pojmański, MikroKlan, listopad-grudzień 1987r.