home *** CD-ROM | disk | FTP | other *** search
- (*---------------------------------------------------------------------------*)
- (* MAKEMAP.INC (v2.0) *)
- (* Anfertigung eines Belegungsplanes des PC-Hauptspeichers (MS-DOS/Turbo) *)
- (* (c) 1987 Karsten Gieselmann & PASCAL International *)
- (*---------------------------------------------------------------------------*)
- Type ProgName = String[8]; (* "reiner" Programmname (o. Pfad u. Ext.) *)
- Entry = ^ProgEntry; (* Eintrag fuer ein Programm *)
- ProgEntry = Record
- Segment :Integer; (* Lade-Segment *)
- Name :ProgName; (* Name des Programms *)
- Segs :Integer; (* Anzahl der Segmente *)
- Paragraphs :Integer; (* belegter Speicher *)
- Last, (* Zeiger auf letzten Eintrag *)
- Next :Entry; (* Zeiger auf naechsten Eintrag *)
- End;
- Var FreeBlocks :Integer; (* Groesse der nicht belegten Bloecke in Paragr. *)
-
- (* Vergleichsfunktion "a < b" fuer CARDINAL-Zahlen (0..$FFFF): *)
- Function Lower (a,b :Integer) :Boolean;
- Begin
- Inline ($31/$C0/ (* XOR AX,AX ; *)
- $8B/$5E/$06/ (* MOV BX,[BP+06] ;a holen *)
- $3B/$5E/$04/ (* CMP BX,[BP+04] ;Vergleich: a < b ? *)
- $73/$01/ (* JNC *+1 ;nein: dann Abbruch *)
- $40/ (* INC AX ;sonst Bedingung erfuellt *)
- $88/$46/$08) (* MOV [BP+08],AL ;Ergebnis auf Stapel *)
- End;
-
- (* Diese Prozedur erstellt eine nach Segmenten geordnete Liste aller im
- Speicher befindlichen residenten Programme. Der durch unbenutzte Bloecke
- freie Speicher wird in der globalen Variablen "FreeBlocks" mitgezaehlt
- (Angabe in Paragraphen). Der Uebergabe-Parameter "FirstProgPtr" enthaelt
- einen Zeiger auf den ersten Listeneintrag. *)
- Procedure MakeMemoryMap (Var FirstProgPtr :Entry);
- Type MCB_Ptr = ^MCB_Type;
- MCB_Type = Record (* Aufbau eines Memory Control Blocks *)
- ID :Char;
- PSPSeg, Diff :Integer;
- End;
- Var MCB :MCB_Type;
- CurrentMCB :MCB_Ptr;
- FirstProg, ProgPtr :Entry; (* Listenkopf und Arbeitszeiger *)
-
-
- (* liefert einen Zeiger auf den ersten Memory Control Block: *)
- Function First_MCB :MCB_Ptr;
- Var Regs :Record AX,BX,CX,DX,BP,DI,SI,DS,ES,Flags :Integer End;
- Begin
- Regs.AX := $5200; MsDos (Regs); (* undokumentierte Funktion 52h *)
- With Regs do First_MCB := Ptr (MemW[ES:BX-2], 0);
- End;
-
- (* durchsucht die nach Segmenten aufsteigend sortierte Programm-Liste
- und liefert die Einfuege-Position. Befindet sich bereits ein Eintrag
- in der Liste, bei welchem das Segment mit "PSPSeg" uebereinstimmt, so
- wird ein Zeiger auf diesen Eintrag uebergeben: *)
- Procedure GetProgPos (PSPSeg :Integer; Var ProgPtr :Entry);
- Begin
- ProgPtr := FirstProg;
- While (ProgPtr^.Next <> Nil) and Lower (ProgPtr^.Segment, PSPSeg) do
- ProgPtr := ProgPtr^.Next;
- If ProgPtr <> FirstProg then
- If Lower (PSPSeg, ProgPtr^.Segment) then ProgPtr := ProgPtr^.Last
- End;
-
- (* erzeugt ein neues Listenelement und fuegt es hinter "ProgPtr" ein: *)
- Procedure InsertNewProg (Var ProgPtr :Entry);
- Var NewProg :Entry;
- Begin
- New (NewProg); NewProg^.Next := ProgPtr^.Next;
- NewProg^.Last := ProgPtr; ProgPtr^.Next := NewProg;
- If NewProg^.Next <> Nil then NewProg^.Next^.Last := NewProg;
- ProgPtr := NewProg
- End;
-
- (* holt das Environment-Segment aus dem PSP (Offset 2Ch) und schaut
- dort nach dem vom DOS (erst ab Version 3.0!) abgelegten Dateinamen.
- Bei erfolgreicher Suche werden Pfad und Extension abgeschnitten und
- der reine Programmname uebergeben: *)
- Function GetProgName (PSPSeg :Integer) :ProgName;
- Var Name :String[255];
- EnvSeg,EnvOfs :Integer; (* Segment, Offset des Environments *)
- p :Byte;
- Begin
- EnvSeg := MemW [MCB.PSPSeg:$2C]; EnvOfs := 0; Name := '';
- While (MemW[EnvSeg:EnvOfs] <> $0000) do (* bis Ende des Env.-Strings *)
- EnvOfs := succ (EnvOfs);
- If MemW[EnvSeg:EnvOfs+2] = $0001 then begin (* Datein. ist eingetragen *)
- EnvOfs := EnvOfs + 4; (* EnvOfs auf Dateinamen *)
- While Mem[EnvSeg:EnvOfs] <> $00 do begin (* bis zum Ende des Namens *)
- Name := Name + chr(Mem[EnvSeg:EnvOfs]); EnvOfs := succ (EnvOfs)
- End;
- Repeat (* Pfadnamen abspalten *)
- p := Pos ('\', Name); Delete (Name, 1, p);
- until p = 0;
- End;
- p := pred (Pos('.',Name));
- GetProgName := Copy (Name,1,p); (* Extension abspalten *)
- End;
-
- Begin (* MakeMemoryMap *)
- New (FirstProg); (* Programm-Liste anlegen *)
- FirstProg^.Next := Nil; FirstProg^.Last := Nil; FreeBlocks := 0;
- CurrentMCB := First_MCB; (* Zeiger auf ersten MCB holen *)
- Repeat
- MCB := CurrentMCB^;
- With MCB do (* belegt und nicht vom DOS benutzt: *)
- If Lower ($0070,PSPSeg) then begin
- GetProgPos (PSPSeg, ProgPtr);
- If (ProgPtr <> FirstProg) and (ProgPtr^.Segment = PSPSeg) then
- With ProgPtr^ do Begin
- Segs := succ (Segs); Paragraphs := Paragraphs + Diff;
- If Name <> 'DOS' THEN Name := GetProgName (PSPSeg);
- End
- else begin (* neuen Eintrag erzeugen *)
- InsertNewProg (ProgPtr);
- With ProgPtr^ do Begin
- Segment := PSPSeg; Segs := 1; Paragraphs := Diff;
- If ProgPtr = FirstProg^.Next then (* Eintrag ist DOS! *)
- Name := 'DOS'
- else Name := '???'
- End
- End;
- End
- else
- If PSPSeg = $0000 then (* unbenutzer Speicherblock *)
- FreeBlocks := FreeBlocks + Diff;
- CurrentMCB := Ptr(Seg(CurrentMCB^)+succ(MCB.Diff),0); (* naechster MCB *)
- until MCB.ID = 'Z';
- FirstProgPtr := FirstProg^.Next
- End;
- (*---------------------------------------------------------------------------*)
- (* MAKEMAP.INC (v2.0) *)