
Előző számunkban két különböző szálon gyarapítottuk ismereteinket, mint
a DOS (INT 21h) megszakítás rutinjaival, és a fizikai lemezkezeléssel.
Ma is hasonlóan gondoltam felépíteni a cikket. A fizikai lemezműveletek
részében a főkönyvtár (drive:\) kilistázását tárgyalnánk hisz ez az egyik
legegyszerűbb művelet. A DOS file-kezelő megszakításaiból pedig a handle-s
file-kezelést kezdjük el tárgyalni.
A főkönyvtár kilistázása DOS nélkül !
Minden szükséges ismeretanyagot már az előző számban megtárgyaltunk. Vázoljuk
mi szükséges a kilistázáshoz:
-
Mindenek előtt le kell kötnöm, hogy a FIZIKAI LEMEZEK ELSŐDLEGES PARTÍCIÓJAIVAL
fogunk foglalkozni. Azért, mert a partíciós-tábla magyarázata egy későbbi
részben lesz esedékes, ahol magával a HDD és FDD közötti különbségekkel
foglalkozunk.
-
FIGYELEM a CD-n található program a fent specifikált problémára DOS, és
nem Win95 alól tökéletesen működik. Amennyiben az INT 13h-s megszakítást
átírjátok (az AH-ba rossz paramétert megadva) tönkre tehetitek az olvasott
lemezt. Ezért óvatosan kell bánni e megszakítással.
-
A programnak adott egy drive-név, pl. így: C:
Ebből a névből ha A: vagy B: akkor az INT 13h-ban drive-nak rendre
00h-t ill. 01h-t adunk meg.
Ha C: vagy D: akkor a C: biztosan (az esetek 99%-ban) az elsődleges
fizikai lemezt jelentik, tehát a drive száma 128+ 00h az-az 128. Ha két
HDD van a gépben akkor a második HDD elsődleges partíciója D: ként fog
megjelenni. Így erre a 128+ 01h az-az 129-ként hivatkozhatunk rá.
Amennyiben csak egy HDD van a gépben, s több partíció van akkor nyílván
nem 129-cel lehet hivatkozni a 2. particióra, hisz csak egy fizikai egység
van a gépben. Ekkor a D:-ot (ha az a HDD extended particiója) akkor a partíciós
tábla segítségével árhető el. De erről majd később.
-
Ellenőrizzük, hogy pl. bent van -e a lemez a drive-ban (FDD), vagy olvashato
-e ? Ha nem kilépünk.
-
Beolvassuk a boot-szektor-t. A TBootsecInforms típusú rekordba.
(Ezt a kettővel ezelőtti cikkben tárgyaltam.) Így megjelennek a rekord
mezőiben a boot-szektor által tárolt adatok. Ezek alapján számítsuk ki:
- Hányadik logikai szektoron kezdődik a FAT és milyen hosszú az szektorban
mérve,
- Hányadik logikai szektoron kezdődik a főkönyvtár bejegyzései, és
mennyi szektoron van el tárolva a főkönyvtár. (huuuu magyarban passzív
?)
- Ha már ennyire belelendültünk akkor, számoljuk ki hol kezdődnek az
adatok avagy a 2. cluster.
-
Mivel a BootInf-nek deklarált TBootsecInforms típusú rekordba olvastuk
a boot-szektort, s ebből a rekordból pontosabban ennek mezőiből állítjuk
elő a fent kívánt értékeket használjuk a with do Pascal utasítást.
Lássuk a megvalósítást:
with BootInf do
begin
FATStart:=ReservedSecs;
FATSize:=FATCount * SectorInOneFAT;
RootStart:=FATStart + FATSize;
RootSize:=(MaxRootEntries * 32) div Byte_Sector;
DataStart:=RootStart + RootSize;
MaxEntryPerClus:=(Sector_Cluster * Byte_Sector) div 32;
end;
Látjuk, hogy a FAT első szektora a lefoglalt szektorok (ReservedSecs) után
kezdődik ez általában egy. Ez az egy maga a boot-szektor. Ha ennek több
az értéke akkor valószínüleg hibásak a HDD 2. 3. ... szektorai.
A FAT olyan hosszú szektorokban mérve amennyi FAT másolat van (általában
2) és amennyi szektorból áll egy db. FAT. (E kettő szorzatából, lásd fent
a forráskódot.)
A főkönyvtár bejegyzései ott vannak tárolva, onnan kezdődik: a FAT kezdete
plussz a FAT hossza után.
A főkönyvtár szektorban mért hossza a maximális bejegyzések száma (MaxRootEntries,
ennyi file ill. könyvtár bejegyzés lehet max a főkönyvtárban) szorzva 32-vel
mivel ennyi egy bejegyzés hossza. Így meg van az össze bejegyzés byte-ban
mért hossza. Ezt el kell osztani egy szektorban tárolt byte-ok számával,
így megkapjuk mennyi szektor szükséges ahhoz, hogy eltároljuk a főkönyvtárat.
Az adatok (tehát a 2. cluster) pedig mind ezek után kezdődik.
Van pár apróság amit a DOS DIR parancs is kiír: ezek a drive-név, ill a
széria-szám (serial number). Ezek is a boot-szektorban vannak tárolva.
-
Kötet név egy 11 karakterből álló tömbben a VolumeLabel-ben. (Ill.
lehet még a főkönyvtárban a VolumeID attribútummal ellátott bejegyzés is.)
-
A széria-szám egy Longint-ben. Ennek a Longint-nek a felső ill. alsó Word-jét
kell hexában kiírni.
A fizikai lemezműveletek track ill. szektor megadása
Egy fincsi kis részhez értünk ahol muszály lesz picit elidőznünk. Vegyük
sorra az INT 13h első pár rutinját:
-
A lemez reset-elése, és a 0,0 szektorra való pozícionálás
AH = 00h
DL = a drive száma (00h A:, 01h B: A fizikai HDD száma 128+ 00h ha
első HDD, 128 + 01h ha a 2. )
INT 13h
Vissza: AH-ban a státusz. Ha 0 akkor minden sikeres volt, ha nem akkor
hiba volt. (Lásd a hiba táblázatot a PCXDRIVE.pas-ban function ConvertStatusByteToString(StatusByte:
Byte): String;-nál.)
(Egyébkent ha nincs hiba akkor a CF (carry-flag) kikapcsolt ha hiba
volt akkor meg bekapcsolt.)
-
Az előző művelet eredményének lekérdezése
AH = 01h
DL = a drive száma az előzőek szerint
INT 13h
CF kikapcsolt ha nincs hiba, ha bekapcsolt akkor hiba volt.
AH = az előző művelet (írás, olvasás) eredménye
-
Szektor beolvasása a memóriába
AH = 02h
AL = a szektorok száma amit egyszerre be akarunk olvasni (legalább
1)
CH = a cylinder (= track) számának alsó 8 bit-e
CL : CL alsó 6 bit-e (0-5. bit-ig) a szektor száma ez 1-63 lehet.
CL : CL felső két bit-e (7. és 6. bit) a cylinder felső két bit-e szám
szerint a 9. és a 8.
DH = az olvasó fej száma (0-tól van számozva)
DL = a meghajtó száma a fentiek szerint
ES:BX az a cím ahova a beolvasott adat kerüljön.
INT 13h
CF kikapcsolt ha nincs hiba, ha bekapcsolt akkor hiba volt.
AH = az olvasás művelet (írás, olvasás) eredménye (00h sikeres egyébként
hibás)
AL = a beolvasott szektorok száma. (Ha AL = az INT 13h előtt megadott
AL-lel akkor minden stimmelt.)
Első nekifutásból erre lesz csak szükségünk, de lássunk egy ábrát a szektor
olvasásánál (és késöbbiekben minden írás | ellenőrzés, stb. műveletnél
is így lesz.) a track ill. szektor megadására a CX (CH - CL) ben.
Lássuk a megvalósítást arra, hogy hogyan kerül CH-ba és CL-be a megfelelő
érték. A forráskód assembly-ben:
mov ax, Track {CylNum -> ax (ah, al)}
shl ah, 6 {xxxx xxBB -> BBxx xxxx}
mov bl, Sector {SecNum -> bl}
and bl, 0011 1111b {xxBBBB BB -> 00BB BBBB}
add ah, bl {ah -> ah felső két bit és bl alső 6 bit}
xchg al, ah {ah, al között csere}
mov cx, ax
-
A track (cylinder) számot az AX-be másoljuk. Az AH alsó két bit-jét
(tehát a track szám felső két bitjét a 9. és 8. bit-et) elcsúsztatjuk balra
6-tal. Így az AH alsó két bit-je a felső két bit lesz.
-
A BL-be másoljuk a szektor számot, majd annak felső két bit-ét a biztonság
kedvéért kinullázzuk.
-
Ehhez adjuk az AH felső két bit-ét. Így AH felső két bit-e a a cylinder
szám felsző két bit-e lesz, s AH alsó 6 bit-e pedig a szektorszám.
-
AL-ben pedig megmaradt a cylinder szám alsó 8 bit-e.
-
AL-t és AH-t megcseréljük, mivel az INT 13h így várja, s most AX-ben kapjuk
meg a kívánt formát, amit CX-be másolhatunk.
Mivel logikai szektorokról beszéltünk lássuk, hogyan kezelhetjük fizikailag
(nem INT 25h-val !) de logikai szektor szinten a lemezt.
Mindenek előtt le kell lomboznom benneteket, de az INT 13h-nak nincs
ilyen rutinja mely logikai szinten kezelné a lemezt. Csak meghajtó-fej,
track (avagy HDD-nél ezt cylinder-nek hívják, egyébként magyarul
ez a sáv), ill. szektor szinten kezelhető a lemez. Viszont mi
logikai szinten kívánjuk kezelni, hiszen a a FAT, a főkönyvtár kezdő szektora
is logikai szektorral van megadva.
Ki kell találnunk, hogyan lehet a logikai szektor számozást fej-sáv-szektorra
visszaalakítani.
Mindenek előtt két részre kell bontanunk ezen eset vizsgálatát:
A floppy egység melynek drive számozása 128 alatt van (avagy a 7. bit
nem bekapcsolt), ill. a harddisk egység melynek meghajtó száma 128 vagy
annál nagyobb (a 7. bit bekapcsolt).
Az elkülönítésre azért van szükség, mert a harddisk-eknél lehetőség
van egy lemezen több partíció (cca: egy lemezen több elkülönített rész
melyeket külön betűvel jelölünk.) kialakítására.
A több partíció ill. a harddisk szerepe miatt létezik egy particiós
tábla mely a winchester fizikailag 0 fej, 0 sáv, 1 szektorán található.
Ez a táblázat mondja meg, hogy hol kezdődik az első, pl. a C: partíció.
Általában OP-rendszer az 1 fej, 0 sáv, 1 szektorára teszi az első partíció
boot-szektorát mely magát a boot-olást végzi.
A floppy-knál ezzel ellentétben - mivel nincs partíciós tábla - a 0.
fej, 0 sáv, 1 szektorán van a boot-szektor.
Ezekre azért van szükség, mert egy logikai szektor-számból fizikai jellemzőket
(fej-sáv-szektor) kívánunk előállítani, hogy INT 13h-val kezelhessük.
Lesz egy - Pascal - rutin melybe a logikai szektor-szám mely
be, és cím szerint paraméterként adja vissza a beolvasott szektorokat (és
egyéb változókat, mely pl. az eredményességet tárolja):
function ReadLogicalSectorIntoMemory(var Buf; ADrive: Byte; StartSec: Longint; SecCount: Byte; BootInf: PBootSecInforms; var Status, ReadedSecCount: Byte): Boolean;
Lássuk, hogyan lehet a logikai szektor-számból visszaállítani a fizikait:
-
Megkapjuk a szektor számot, ha elosztjuk a StartSec-t (a logikai-szektor-számot)
az egy sávban található szektorok számával, és hozzáadunk egyet. (Persze
az osztás egészrészét vesszük.)
Sector:=Byte(((StartSec) mod BootInf^.Sector_Track)+1);
-
Megkapjuk a sáv (track - cylinder) számot, ha elosztjuk a StartSec-t
(a logikai-szektor-számot) az egy sávban található szektorok számával
és ezt még elosztjuk a fejek számával. (Persze az osztás egészrészét vesszük.)
Track:=Word(((StartSec) div BootInf^.Sector_Track) div BootInf^.Head_Number);
-
A fej számát a logikai-szektor-számból már egy picit körülményesebb kiszámolni,
mert tudjuk, hogy a boot-szektor nem egy helyen kezdődik a floppy-nál ill.
a harddisk-nél. A harddisk-nél eggyel nagyobb a fej száma a boot-szektor-nál,
így a logikai-szektorból kiszámított fej számához harddisk-nél egyet hozzá
kell adni míg a floppy-nál nem.
A kiszámítás amúgy nem ördöngős. A logiakai-szektor számot kell elosztani
az egy sáv található szektorok számával, majd ezt a maximális fejek számával.
Az így kapott maradék adja a fej számát. Ha HDD-ről van szó (az-az
a drive szám nagyobb, mint 127) akkor hozzáadunk egyet a partíciós
tábla miatt.
if ADrive > $7F
then Head:=Byte(((((StartSec) div BootInf^.Sector_Track) mod BootInf^.Head_Number))+1)
else Head:=Byte((((StartSec) div BootInf^.Sector_Track) mod BootInf^.Head_Number));
Mindenhol láthatjuk a BootInf rekordot fehasználtuk. Ez nem más,
mint a boot-szektor beolvasásakor feltöltött TBootsecInfos típusú rekord,
amit pointer-ként adunk át a rutinnak. (Mint ahogy fent a paraméter-listán
is láthatjuk.) Erre szükség van, hisz ebből nyerjük a szektor/sáv,
ill. maximális fej-számot.
Miután kiszámítottuk a fej (head), sáv (track - cylinder), szektor (sector)
értékeket, már használhatjuk az eredeti INT 13h megszakítás szektor beolvasó
rutinját, hisz minden szükséges értéket kiszámoltunk hozzá.
Láthatjuk a rutin vissza is ad értéket, név szerint ezek: a Status,
ill. ReadedSecCount. Ez nem más amit az INT 13h szektor olvasó
rutinja ad vissza rendre: AH ill. AL regiszterekben. (a művelet sikeressége,
ill. a beolvasott szektorok száma.)
A főkönyvtár szektorainak olvasása, és visszaalakítása
Most már tudjuk és ki is számítottuk, hogy a fökönyvtár a RootStart
szektortól kezdődik és a RootSize hosszú szektorban mértve.
Így a RootStart + RootSize szektoron fejeződik be.
Nincs más dolgunk mint egy ciklusban RootStart-tól RootStart
+ RootSize-ig a szektorokat beolvasni, az alábbiak szerint átalakítani
és kiírni.
Tudjuk, hogy:
-
A főkönyvtár (mint minden könyvtár) TDirectoryEntry (lásd: előző
szám) típusú bejegyzésekből áll, avagy a jobb érthetőség miatt mondhatnánk:
TDirSector = Array[0..15] of TDirectoryEntry;
-
Azt is tudjuk, hogy legtöbbször nincsen felhasználva a főkönyvtár összes
bejegyzése (FDD-nél: ált: 224, HDD-nél: 512). A DOS a főkönytárat addig
listázása ki amíg a következő bejegyzés első karaktere (az-az a filenév
első betűje) nem #0 (az-az 0 ASCII).
-
Persze megjegyezném, ha a file első karaktere #32 a space karakter alatt
van (#0-#31), a file neve nem listázódik ki (nem írja ki a DIR), ugyanakkor
folytatódik a következő file nevének kiírása. (Ezt a #32 alatti név "nem
kiírást" használja ki DOS kompatibilitás gyanánt a Win95 hosszú file-név
rendszere.)
Nos két ciklusból áll a kilistázás. Egy a fent megnevezett RootStart-tól
RootStart + RootSize-ig. Ill. egy ebben lévő 0 - 15-ig tartó
belső ciklus mely az egy szektorban lévő könyvtárbejegyzéseket írja ki
darabonként. Az összes ciklusból akkor lehet kilépni amikor a következő
könyvtárbejegyzés első karaktere #0 lenne.
A ciklus felépítéséhez szükséges még pár apróság:
-
Az előző számban tárgyaltuk, hogy a könyvtár-bejegyzéseket a TDirectoryEntry
tipusú rekordban tárolhatjuk. Ennek van Time és Date mezője mely az utolsó
módosítás idejét tartalmazza. Ezek Word-ben vannak tárolva, visszaalakításukat
már előző számunk elején tárgyaltuk.
-
El kell döntenünk, hogy minden file-t ki akarunk -e listázni, vagy csak
az archive ill. a read-only attributumu file-okat. Lehessen megadni programunknak
egy kapcsolóval, hogy a hidden - system file-okat is ki lehessen iratni.
Legyez ez a kapcsoló a /hrs.
-
Kell írni egy rutint mely a beolvasott szektorból az x. könyvtárbejegyzésnek
megfelelő byte-okat átmásolja a TDirectoryEntry rekordba. Ezt a rutint
használja a 0-15-ig belső ciklus mely a szektorból elkezdi kiírni a 0.
bejegyzést, az elsőt, ... s végül a 15.-et úgy, hogy a rutin másolja a
szektroból a dir-entry rekorda az adatokat. E rekordból az adatokat pedig
szépen magunk írjuk ki a képernyőre.
Valósítsuk meg ezt a szektroból dir-entry rekordba másoló rutint:
-
A kiszámítás egyszerű. Azt kell kiszámolni a szektor hányadik byte-tól
(milyen offszettől) kell elkezdeni a másolást. A másolás hossz értelem
szerüen megegyezik a TDirectoryEntry byte-ban mért hosszával.
Az offszetet úgy kapjuk meg, hogy a TDirectoryEntry hosszát összeszorozzuk
az index számával. Pl.:
A 0 indexű bejegyzés a 0 * 32 = az-az 0-dik byte-on kezdődik.
Az 1-ő az 1*32 = 32. byte-on kezdődik. (ugyanis a 0. bejegyzés 0 -
31 byte-ig tartott.) És így tovább ...
-
Lássuk az assemby rutint mely ezt megoldja: (Nem a leggyorsabb rutint
mutatom be, inkább azt amelyik érthetőbb. (így nem használtam a rep movsb-et.)):
procedure CopyBufToDirEntry(var Buf; Index: Byte; var _Aentry: TDirectoryEntry); Assembler;
const SizeOfAEntry: Word = SizeOf(TDirectoryEntry); {megadja egy bejegyzés hosszát}
asm
push es
push ds
push di
push si
push bp
les di, [Buf]
lds si, [_AEntry]
mov cx, SizeOfAEntry
xor ah, ah
mov al, Index
mul cl
mov bx, ax
xor bp, bp
@Loop:
mov al, Byte Ptr es:[di+bx]
mov Byte Ptr ds:[si+bp], al
inc bx
inc bp
cmp bp, cx
jb @Loop
pop bp
pop si
pop di
pop ds
pop es
end;
MUL-lal összeszorozza az indexet és a rekord hosszát, ez lesz az offszet
melytől 32 byte-on (a rekord hosszán át) az _AEntry-be másolja a
byte-okat.
Lássuk a két ciklust mely megvalosítja a fenti rutinok segítségével
a főkönyvtár kilistázását. Sematikus ábra:
AllFileSize:=0; AllFileNumber:=0; AllDIRNumber:=0;
for i:=RootStart to RootStart+RootSize do
begin
if BreakAll then Break; {kiugrás a belső után a külső ciklusból is !}
ReadLogicalSectorIntoMemory(Sector, Drv, i, 1, @BootInf, Status, Readed);
{Ez olvassa be a főkönyvtár szektorait ...}
if Status <> 0 then {ha nem sikerült beolvasni a szektort akkor kilépés !!!}
begin
System.WriteLn('Error: ', ConvertStatusByteToString(GetStatusOfLastDriveOperation(Drv)));
System.WriteLn;
System.WriteLn('Exitting ...');
Halt($FF);
end;
for OneEntry:=0 to 15 do {ez a belső ciklus mely egy szektor bejegyzéseit dolgozza fel}
begin
CopyBufToDirEntry(Sector, OneEntry, AEntry); {Ez másolja a szektorból az AEntry-be az
OneEntry-edik indexű bejegyzést}
if AEntry.FileName[1] = #0 then begin BreakAll:=True; Break; end;
{vége, nincs több file kilépés a belső ciklusból ! Ugrás a külsőre !}
with AEntry do
if Not ( ((Attribute and VolumeID) = VolumeID) or
((Attribute and Hidden) = Hidden) or
((Attribute and SysFile) = SysFile) )
then if Not (FileName[1] in[#229, #0..#32]) then {ha nem hidden vagy systemfile}
begin
TTUtil.WriteLn(FileName+ ' '+Extension+' '+
ConvertAttrByteToAttrStr(Attribute)+' '+FillToSizeA(MSeeable(FileSize), 11)+
' '+ConvertTimeAndDateToString(Time, Date));
{rendre kiírjuk a file nevet és kiterjesztést, attribútumot, file-hoszt,
dátumot, időt}
AllFileSize:=AllFileSize+FileSize;
if (Attribute and Directory) = Directory
then Inc(AllDIRNumber)
else Inc(AllFileNumber);
{ezen utolsó 4 sor pedig a file-ok számát, az összes file
hosszát ill. a könyvtárak számát adja meg.}
end;
end;
end;
Nos a fökönyvtár kilistázása kész is lenne. Ezzel cikkünknek a lemez fizikai
kezelésével foglalkozó része végetért, ezek után DOS file-kezelő rutinjait
tárgyaljuk ahogy előző számunk végén megígértem.
A DOS file-kezelő rutinjai II
Előző számunkban nagyjából végigvettük az FCB-s file-kezelést. Ma a handle-lel
történő file-kezelést feszegetnénk.
De mielőtt fejest ugranánk a mélybe, hogy mindenki számára érthető
legyen mondjuk el mi az a file-handle.
Nos ez típusát tekintve egy Word szám. A file műveletre való megnyitásakor
meg kell adni a nevet egy ASCIIZ karakter-láncban, esetleg az attribútumot,
meg még ki tudja ... Nos ugye az FCB-nél az egész FCB rekordot el kellett
tárolni ha hivatkozni akartunk a már megnyitott file-ra. És mi tagadás
kissé körülményes volt az FCB-s file kezelés a mai ellustult puhány programozóknak.
Így a DOS a UNIX-tól átvette a hande orientált file-kezelést mely egyszerűbb,
és már könyvtárstruktúrát is kezel. Szóval file megnyitásakor vagy első
létrehozásakor kapunk ha az sikeres volt (ha sikerült megynitni, ill. létrehozni)
akkor kapunk egy word számot mellyel a későbbi műveletek során (írás |
olvasás) hivatkozhatunk a file-ra. Nem kell ezek után se nevet, se path-t
megadni csak a handle számot és már tudja is a DOS melyik file-ra gondoltunk.
(Ezt ő belsőleg tárolja, hogy melyik handle-höz melyik file tartozik.)
Azonban vannak előre lekötött handle számok amiket már a DOS hozzárendelt
bizonyos egységekhez a könnyebb kezelés végett. Ezek:
0 |
Standard Input Device (alapértelmezett bemeneti egység,
általában a billentyűzet) |
1 |
Standard Output Device (alapértelmezett kimeneti egység,
általában a képernyő) |
2 |
Standard Error Device (alapértelmezett hiba-kiíró egység,
CON - => képernyő) |
3 |
Standard AUX Device (alapértelmezett AUX egység, az első
COM port = COM1) |
4 |
Standard Printer (alapértelmezett printer port, LPT1) |
Ezeket az egységeket nem kell megnyitni, ezekre rögtön közvetlenül
írhatunk - vagy olvashatunk róla. (Amelyikről amit lehet. Nyilván a printer-port-ról
nem fogunk betűket beolvasni. (Nem a bi-dirrekciós printer-ekről van szó.))
Volt még egy dolog amit lehet, hogy érdemes tisztázni. Igaz régen már
beszéltünk róla.
A DOS a karakter-láncot (String) nem úgy tárolja ahogy a Pascal. Nem
fixen 256 byte hosszon ahol az első byte jelenti a szöveg hosszát. (Ord(S[0])
= a szöveg hossza, S[1], S[2], ... maga a szöveg). Szóval nem a
DOS nem így tárolja, hanem van maga a szöveg, pl: 'itt ez egy karakterlánc'#0
. És amint láthatjuk a végén egy ASCII nulla karakter. Nincsen sehol letárolva,
hogy milyen hosszú a szöveg, hanem a szöveg végét egy ASCII 0 - vagy
Pascal-osan egy #0 - karakter jelzi.
Most pedig kezdjük el a handle tipusú file-kezelést:
-
MkDIR - Make Directory - könyvtár létrehozása
AH = 39h
DS:DX : A létrehozandó könyvtár neve útvonallal együtt.
INT 21h (A megszakítást ezek után nem írom ki, egyértelmünek tekintem
!)
Ret: Ha CF kikapcsolt akkor minden sikeresen történt.
Ha a CF bekapcsolt állapotban van akkor a hiba kódja az AX-ben van.
Lássunk egy példát a könyvtár létrehozására. A Pascal megvalósítás:
var
S, O : Word;
DirPath: String;
Error : Word;
BEGIN
Error:=0;
DirPath:='C:\!TOROLD.LE!'#0; {Töröld le ez csak egy próba volt !}
S:=Seg(DirPath); O:=Ofs(DirPath)+1; {Növeljük eggyel mert nincs szükség}
asm { a hosszra az ASCIIZ-hez. }
push ds
mov dx, S
mov ds, dx
mov dx, O
mov ax, 3900h
int 21h
jnc @NoHiba {Ha CF felkapcsolt, akkor Error változóba a hiba}
mov Error, ax
@NoHiba:
pop ds
end;
if Error <> 0 then WriteLn('Nem sikerült a könyvtárat létrehozni !');
END.
-
RmDIR - Remove Directory - könyvtár törlése
AH = 3Ah
DS:DX : A törlendő könyvtár neve útvonallal együtt.
Ret: Ha CF kikapcsolt akkor minden sikeresen történt.
Ha a CF bekapcsolt állapotban van akkor a hiba kódja az AX-ben van.
-
ChDIR - Change Directory (Set DOS default DIR) - könyvtárváltás
AH = 3Bh
DS:DX : A létrehozandó könyvtár neve útvonallal együtt.
Ret: Ha CF kikapcsolt akkor a könyvtárváltás sikeresen megtörtént.
Ha a CF bekapcsolt állapotban van akkor a hiba kódja az AX-ben van.
-
CreatFile (Creat file handle) - file létrehozása (ill. ha létezik felülírása)
AH = 3Ch
DS:DX : A létrehozandó file meghajtója, útvonala, és neve
CX a file attribútuma
Ret: Ha CF bekapcsolt akkor nem sikerült létrehozni a file-t,
és AX-ben a hiba kódja,
ha CF kikapcsolt akkor AX-ben található a létrehozott file handle-je.
-
OpenFile - Létező file megnyitása
AH = 3Dh
AL = open mode (megnyitási mód)
0 - megnyitás csak olvasásra
1 - megnyitás csak írásra
2 - megnyitás írásra / olvasásra
(share jogokról nem beszélünk)
DS:DX : A megnyitandó létező file meghajtója, útvonala, és neve
Ret: Ha CF bekapcsolt akkor nem sikerült megnyitni a file-t,
és AX-ben a hiba kódja,
ha CF kikapcsolt akkor AX-ben található a megnyitott file handle-je.
-
CloseFile - Megnyitott file lezárása, az általa használt hanlde felszabadítása
AH = 3Eh
BX : file-handle (A megnyitott file handle-je.)
Ret: Ha CF bekapcsolt akkor nem sikerült lezárni a file-t, és
AX-ben a hiba kódja,
ha CF kikapcsolt akkor sikerült lezárni a file-t, a régi file-handle-t
a DOS felszabadította.
Most kicsit rövidebb lett a DOS file-kezelő részének leírása, mert a fizikai
lemezkezelésnél most nem csak elméletet, hanem egy programot is tárgyalnunk
kellett. Következő számunkban folytatjuk a DOS-os file-kezelést, és a fizikai
részben valószínüleg már a FAT felépítését, és a linkeléseket vesszük.
Amennyiben a mai cikk kissé tömör lenne - bár szerintem érthető - (és
második elolvasás után is homályos) eMail-ezz.
Bérczi László
