home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1988 / 02 / mmr / makemap.inc < prev    next >
Encoding:
Text File  |  1994-04-11  |  6.9 KB  |  134 lines

  1. (*---------------------------------------------------------------------------*)
  2. (*                           MAKEMAP.INC  (v2.0)                             *)
  3. (*  Anfertigung eines Belegungsplanes des PC-Hauptspeichers (MS-DOS/Turbo)   *)
  4. (*            (c) 1987  Karsten Gieselmann  &  PASCAL International          *)
  5. (*---------------------------------------------------------------------------*)
  6. Type ProgName = String[8];        (* "reiner" Programmname (o. Pfad u. Ext.) *)
  7.      Entry  = ^ProgEntry;                       (* Eintrag fuer ein Programm *)
  8.      ProgEntry = Record
  9.                     Segment    :Integer;                     (* Lade-Segment *)
  10.                     Name       :ProgName;              (* Name des Programms *)
  11.                     Segs       :Integer;              (* Anzahl der Segmente *)
  12.                     Paragraphs :Integer;                (* belegter Speicher *)
  13.                     Last,                      (* Zeiger auf letzten Eintrag *)
  14.                     Next       :Entry;       (* Zeiger auf naechsten Eintrag *)
  15.                  End;
  16. Var  FreeBlocks :Integer;   (* Groesse der nicht belegten Bloecke in Paragr. *)
  17.  
  18. (*       Vergleichsfunktion "a < b" fuer CARDINAL-Zahlen (0..$FFFF):         *)
  19. Function Lower (a,b :Integer) :Boolean;
  20. Begin
  21.    Inline ($31/$C0/        (*  XOR    AX,AX       ;                          *)
  22.            $8B/$5E/$06/    (*  MOV    BX,[BP+06]  ;a holen                   *)
  23.            $3B/$5E/$04/    (*  CMP    BX,[BP+04]  ;Vergleich:  a < b ?       *)
  24.            $73/$01/        (*  JNC    *+1         ;nein:  dann Abbruch       *)
  25.            $40/            (*  INC    AX          ;sonst Bedingung erfuellt  *)
  26.            $88/$46/$08)    (*  MOV    [BP+08],AL  ;Ergebnis auf Stapel       *)
  27. End;
  28.  
  29. (* Diese Prozedur erstellt eine nach Segmenten geordnete Liste aller im
  30.    Speicher befindlichen residenten Programme. Der durch unbenutzte Bloecke
  31.    freie Speicher wird in der globalen  Variablen  "FreeBlocks" mitgezaehlt
  32.    (Angabe in Paragraphen). Der Uebergabe-Parameter "FirstProgPtr" enthaelt
  33.    einen Zeiger auf den ersten Listeneintrag.                                *)
  34. Procedure MakeMemoryMap (Var FirstProgPtr :Entry);
  35.    Type MCB_Ptr  = ^MCB_Type;
  36.         MCB_Type = Record              (* Aufbau eines Memory Control Blocks *)
  37.                       ID           :Char;
  38.                       PSPSeg, Diff :Integer;
  39.                    End;
  40.    Var  MCB                :MCB_Type;
  41.         CurrentMCB         :MCB_Ptr;
  42.         FirstProg, ProgPtr :Entry;           (* Listenkopf und Arbeitszeiger *)
  43.  
  44.  
  45.    (*        liefert einen Zeiger auf den ersten Memory Control Block:       *)
  46.    Function First_MCB :MCB_Ptr;
  47.       Var Regs :Record  AX,BX,CX,DX,BP,DI,SI,DS,ES,Flags :Integer  End;
  48.    Begin
  49.       Regs.AX := $5200;  MsDos (Regs);       (* undokumentierte Funktion 52h *)
  50.       With Regs do  First_MCB := Ptr (MemW[ES:BX-2], 0);
  51.    End;
  52.  
  53.    (* durchsucht die nach Segmenten  aufsteigend sortierte  Programm-Liste
  54.       und liefert die Einfuege-Position. Befindet sich bereits ein Eintrag
  55.       in der Liste, bei welchem das Segment mit "PSPSeg" uebereinstimmt, so
  56.       wird ein Zeiger auf diesen Eintrag uebergeben:                         *)
  57.    Procedure GetProgPos (PSPSeg :Integer; Var ProgPtr :Entry);
  58.    Begin
  59.       ProgPtr := FirstProg;
  60.       While (ProgPtr^.Next <> Nil) and Lower (ProgPtr^.Segment, PSPSeg) do
  61.          ProgPtr := ProgPtr^.Next;
  62.       If ProgPtr <> FirstProg then
  63.          If Lower (PSPSeg, ProgPtr^.Segment) then  ProgPtr := ProgPtr^.Last
  64.    End;
  65.  
  66.    (*   erzeugt ein neues Listenelement und fuegt es hinter "ProgPtr" ein:   *)
  67.    Procedure InsertNewProg (Var ProgPtr :Entry);
  68.       Var NewProg :Entry;
  69.    Begin
  70.       New (NewProg);                NewProg^.Next := ProgPtr^.Next;
  71.       NewProg^.Last := ProgPtr;     ProgPtr^.Next := NewProg;
  72.       If NewProg^.Next <> Nil then  NewProg^.Next^.Last := NewProg;
  73.       ProgPtr := NewProg
  74.    End;
  75.  
  76.    (* holt das  Environment-Segment aus dem  PSP (Offset 2Ch) und  schaut
  77.       dort nach dem vom DOS (erst ab Version 3.0!) abgelegten Dateinamen.
  78.       Bei erfolgreicher Suche werden Pfad und Extension abgeschnitten und
  79.       der reine Programmname uebergeben:                                     *)
  80.    Function GetProgName (PSPSeg :Integer) :ProgName;
  81.       Var Name          :String[255];
  82.           EnvSeg,EnvOfs :Integer;        (* Segment, Offset des Environments *)
  83.           p             :Byte;
  84.    Begin
  85.       EnvSeg := MemW [MCB.PSPSeg:$2C];  EnvOfs := 0;  Name := '';
  86.       While (MemW[EnvSeg:EnvOfs] <> $0000) do   (* bis Ende des Env.-Strings *)
  87.          EnvOfs := succ (EnvOfs);
  88.       If MemW[EnvSeg:EnvOfs+2] = $0001 then begin (* Datein. ist eingetragen *)
  89.          EnvOfs := EnvOfs + 4;                      (* EnvOfs auf Dateinamen *)
  90.          While Mem[EnvSeg:EnvOfs] <> $00 do begin (* bis zum Ende des Namens *)
  91.             Name := Name + chr(Mem[EnvSeg:EnvOfs]);  EnvOfs := succ (EnvOfs)
  92.          End;
  93.          Repeat                                       (* Pfadnamen abspalten *)
  94.             p := Pos ('\', Name);  Delete (Name, 1, p);
  95.          until p = 0;
  96.       End;
  97.       p := pred (Pos('.',Name));
  98.       GetProgName := Copy (Name,1,p);                 (* Extension abspalten *)
  99.    End;
  100.  
  101. Begin (* MakeMemoryMap *)
  102.    New (FirstProg);                                (* Programm-Liste anlegen *)
  103.    FirstProg^.Next := Nil;   FirstProg^.Last := Nil;   FreeBlocks := 0;
  104.    CurrentMCB := First_MCB;                   (* Zeiger auf ersten MCB holen *)
  105.    Repeat
  106.       MCB := CurrentMCB^;
  107.       With MCB do                       (* belegt und nicht vom DOS benutzt: *)
  108.          If Lower ($0070,PSPSeg) then begin
  109.             GetProgPos (PSPSeg, ProgPtr);
  110.             If (ProgPtr <> FirstProg) and (ProgPtr^.Segment = PSPSeg) then
  111.                With ProgPtr^ do Begin
  112.                   Segs := succ (Segs);   Paragraphs := Paragraphs + Diff;
  113.                   If Name <> 'DOS' THEN Name := GetProgName (PSPSeg);
  114.                End
  115.             else begin                             (* neuen Eintrag erzeugen *)
  116.                InsertNewProg (ProgPtr);
  117.                With ProgPtr^ do Begin
  118.                   Segment := PSPSeg;   Segs := 1;   Paragraphs := Diff;
  119.                   If ProgPtr = FirstProg^.Next then      (* Eintrag ist DOS! *)
  120.                      Name := 'DOS'
  121.                   else  Name := '???'
  122.                End
  123.             End;
  124.          End
  125.          else
  126.             If PSPSeg = $0000 then               (* unbenutzer Speicherblock *)
  127.                FreeBlocks := FreeBlocks + Diff;
  128.       CurrentMCB := Ptr(Seg(CurrentMCB^)+succ(MCB.Diff),0); (* naechster MCB *)
  129.    until MCB.ID = 'Z';
  130.    FirstProgPtr := FirstProg^.Next
  131. End;
  132. (*---------------------------------------------------------------------------*)
  133. (*                           MAKEMAP.INC  (v2.0)                             *)
  134.