home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1988 / 10_11 / mmr / progmap.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-07-19  |  6.3 KB  |  179 lines

  1. (* ------------------------------------------------------------------------- *)
  2. (*                          PROGMAP.PAS (v3.1)                               *)
  3. (*            Anlegen eines Belegungsplanes des PC-Hauptspeichers            *)
  4. (*      Copyright (c) 1988  Karsten Gieselmann  &  TOOLBOX                   *)
  5. (* ------------------------------------------------------------------------- *)
  6.  
  7. {$R-,S-,I-,V-,B-,N-}                       (* größtmögliche Geschwindigkeit! *)
  8.  
  9. UNIT ProgMap;
  10.  
  11. INTERFACE USES Dos;                                       (* benötigte Units *)
  12.  
  13. TYPE
  14.   ProgName  = STRING[8];     (* "reiner" Programmname (ohne Pfad und Suffix) *)
  15.  
  16.   EntryPtr  = ^ProgEntry;                        (* Eintrag für ein Programm *)
  17.   ProgEntry = RECORD
  18.                 Segment    : WORD;                           (* Lade-Segment *)
  19.                 Name       : ProgName;                 (* Name des Programms *)
  20.                 Segs       : BYTE;                    (* Anzahl der Segmente *)
  21.                 Paragraphs : WORD;                      (* belegter Speicher *)
  22.                 Last,                          (* Zeiger auf letzten Eintrag *)
  23.                 Next       : EntryPtr;        (* Zeiger auf nächsten Eintrag *)
  24.               END;
  25.  
  26. VAR
  27.   UnUsed : WORD;           (* Größe der nicht belegten Blöcke in Paragraphen *)
  28.  
  29.  
  30. PROCEDURE MakeMemoryMap (VAR FirstProgPtr : EntryPtr);
  31.   (* Diese Routine  erstellt eine nach Segmenten aufsteigend geordnete Liste
  32.      aller im Hauptspeicher befindlichen residenten Programme. Der durch un-
  33.      benutzte Blöcke  belegte Speicher wird in der globalen Variablen UnUsed
  34.      mitgezählt (Angabe in Paragraphen). Der Zugriff auf die von MakeMemory-
  35.      Map erstellte Liste erfolgt Über den VAR-Parameter FirstProgPtr, dieser
  36.      enthält einen Zeiger auf den ersten Listeneintrag.                      *)
  37.  
  38.  
  39. IMPLEMENTATION
  40.  
  41.  
  42. PROCEDURE MakeMemoryMap (VAR FirstProgPtr : EntryPtr);
  43.  
  44. TYPE
  45.   MCB_Ptr  = ^MCB_Type;
  46.   MCB_Type = RECORD                    (* Aufbau eines Memory Control Blocks *)
  47.                ID          : CHAR;
  48.                PSPSeg,Diff : WORD;
  49.              END;
  50.  
  51. VAR
  52.   MCB        : MCB_Type;
  53.   CurrentMCB : MCB_Ptr;
  54.   FirstProg,                                                   (* Listenkopf *)
  55.   ProgPtr    : EntryPtr;                                    (* Arbeitszeiger *)
  56.  
  57.  
  58. FUNCTION First_MCB : MCB_Ptr;
  59.   (* liefert einen Zeiger auf den ersten Memory Control Block *)
  60. VAR
  61.   Regs : Registers;
  62. BEGIN
  63.   WITH Regs DO BEGIN
  64.     AH := $52;                               (* undokumentierte Funktion 52h *)
  65.     MsDos (Regs);
  66.     First_MCB := Ptr (MemW[ES:BX-2], 0);
  67.   END
  68. END;
  69.  
  70.  
  71. PROCEDURE GetProgPos (PSPSeg : WORD; VAR ProgPtr : EntryPtr);
  72.   (* durchsucht die nach Segmenten  aufsteigend sortierte  Programm-Liste
  73.      und liefert die Einfüge-Position;  befindet sich bereits ein Eintrag
  74.      in der Liste, bei welchem das Segment mit "PSPSeg" übereinstimmt, so
  75.      wird ein Zeiger auf diesen Eintrag übergeben                         *)
  76. BEGIN
  77.   ProgPtr := FirstProg;
  78.   WHILE (ProgPtr^.Next <> NIL) AND (ProgPtr^.Segment < PSPSeg) DO
  79.     ProgPtr := ProgPtr^.Next;
  80.   IF ProgPtr <> FirstProg THEN
  81.     IF PSPSeg < ProgPtr^.Segment THEN
  82.       ProgPtr := ProgPtr^.Last
  83. END;
  84.  
  85.  
  86. PROCEDURE InsertNewProg (VAR ProgPtr : EntryPtr);
  87.   (* erzeugt ein neues Listenelement und fügt es hinter "ProgPtr" ein *)
  88. VAR
  89.   NewProg : EntryPtr;
  90. BEGIN
  91.   New (NewProg);
  92.   NewProg^.Next := ProgPtr^.Next;
  93.   NewProg^.Last := ProgPtr;
  94.   ProgPtr^.Next := NewProg;
  95.   IF NewProg^.Next <> NIL THEN
  96.     NewProg^.Next^.Last := NewProg;
  97.   ProgPtr := NewProg
  98. END;
  99.  
  100.  
  101. FUNCTION GetProgName (PSPSeg : WORD) : ProgName;
  102.   (* holt das  Environment-Segment aus dem  PSP (Offset 2Ch) und  schaut
  103.      dort nach dem vom DOS (erst ab Version 3.0!) abgelegten Dateinamen;
  104.      bei erfolgreicher Suche werden Pfad und Extension abgeschnitten und
  105.      der reine Programmname übergeben                                     *)
  106.  
  107. VAR
  108.   Name          : STRING;
  109.   EnvSeg,EnvOfs : WORD;                  (* Segment, Offset des Environments *)
  110.   p             : BYTE;
  111.  
  112. BEGIN
  113.   EnvSeg := MemW [MCB.PSPSeg:$002C];
  114.   EnvOfs := 0;
  115.   Name := '';
  116.   WHILE MemW[EnvSeg:EnvOfs] <> $0000 DO         (* bis Ende des Env.-Strings *)
  117.     Inc(EnvOfs);
  118.   IF MemW[EnvSeg:EnvOfs+2] = $0001 THEN BEGIN   (* Dateiname ist eingetragen *)
  119.     Inc(EnvOfs,4);                                  (* EnvOfs auf Dateinamen *)
  120.     WHILE Mem[EnvSeg:EnvOfs] <> $00 DO BEGIN      (* bis zum Ende des Namens *)
  121.       Name := Name + Chr(Mem[EnvSeg:EnvOfs]);
  122.       Inc (EnvOfs)
  123.     END;
  124.     REPEAT                                            (* Pfadnamen abspalten *)
  125.       p := Pos ('\', Name);
  126.       Delete (Name, 1, p);
  127.     UNTIL p=0;
  128.   END;
  129.   p := Pred (Pos ('.', Name));
  130.  GetProgName := Copy (Name, 1, p);                    (* Extension abspalten *)
  131. END;
  132.  
  133.  
  134. BEGIN
  135.   New (FirstProg);                                 (* Programm-Liste anlegen *)
  136.   WITH FirstProg^ DO BEGIN
  137.     Segment := 0;
  138.     Next := NIL;
  139.     Last := NIL;
  140.   END;
  141.   UnUsed := 0;
  142.   CurrentMCB := First_MCB;                    (* Zeiger auf ersten MCB holen *)
  143.   REPEAT
  144.     MCB := CurrentMCB^;
  145.     WITH MCB DO
  146.       IF PSPSeg > $0070 THEN BEGIN      (* belegt und nicht vom DOS benutzt? *)
  147.         GetProgPos (PSPSeg, ProgPtr);
  148.         IF (ProgPtr <> FirstProg) AND (ProgPtr^.Segment = PSPSeg) THEN
  149.           WITH ProgPtr^ DO BEGIN
  150.             Inc(Segs);
  151.             IF Name <> 'DOS' THEN
  152.               Name := GetProgName (PSPSeg);
  153.             Inc (Paragraphs, Diff);
  154.           END
  155.         ELSE                                       (* neuen Eintrag erzeugen *)
  156.           BEGIN
  157.             InsertNewProg (ProgPtr);
  158.             WITH ProgPtr^ DO BEGIN
  159.               Segment := PSPSeg;
  160.               Segs := 1;
  161.               Paragraphs := Diff;
  162.               IF ProgPtr = FirstProg^.Next THEN          (* Eintrag ist DOS! *)
  163.                 Name := 'DOS'
  164.               ELSE
  165.                 Name := '???'
  166.             END
  167.           END
  168.         END
  169.       ELSE
  170.         IF PSPSeg = $0000 THEN                   (* unbenutzer Speicherblock *)
  171.           Inc (UnUsed, Diff);
  172.     CurrentMCB := Ptr (Seg(CurrentMCB^)+MCB.Diff+1,0);       (* nächster MCB *)
  173.   UNTIL MCB.ID = 'Z';
  174.   FirstProgPtr := FirstProg^.Next;
  175. END;
  176.  
  177.  
  178. END.
  179.