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

  1. (* ------------------------------------------------------------------------- *)
  2. (*                            RELEASE.PAS (v3.1)                             *)
  3. (*                Freigeben eines MARKierten Speicherbereichs                *)
  4. (*      Copyright (c) 1988  Karsten Gieselmann  &  TOOLBOX                   *)
  5. (* ------------------------------------------------------------------------- *)
  6.  
  7. {$R-,S-,I-,V-,B-,N-}                       (* größtmögliche Geschwindigkeit! *)
  8.  
  9. PROGRAM Release;
  10.  
  11. USES Dos, ProgMap;                                        (* benötigte Units *)
  12.  
  13. CONST
  14.   OK         = 0;                            (* Rückgabe-Codes für MarkFound *)
  15.   NotFound   = 1;
  16.   ShellError = 2;
  17.  
  18. VAR
  19.   Seg        : WORD;                     (* Segment des letzten MARK-Aufrufs *)
  20.   FirstProg,
  21.   LastProg   : EntryPtr;
  22.  
  23.  
  24. FUNCTION MarkFound (VAR Segment : WORD) : BYTE;
  25.   (* sucht in der Programm-Liste den letzten MARK-Eintrag;  wird dieser ge-
  26.      funden, so enthält "Segment" das Segment dieses Eintrags. Entsprechend
  27.      dem Erfolg der Operation wird eine Kennzahl (siehe oben) zurückgegeben. *)
  28. VAR
  29.   ProgPtr : EntryPtr;
  30.  
  31. FUNCTION DosVersion : BYTE;
  32. VAR
  33.   Regs : Registers;
  34. BEGIN
  35.   WITH Regs DO BEGIN
  36.     AH := $30;
  37.     MsDos (Regs);
  38.     DosVersion := AL;                              (* "Major version number" *)
  39.   END;
  40. END;
  41.  
  42. FUNCTION MarkFound_ : BOOLEAN;
  43. TYPE
  44.   Search   = ARRAY [0..22] OF CHAR;
  45. CONST
  46.   MarkName = 'MARK';                              (* Name des MARK-Programms *)
  47.   MarkCode : Search = (#$FA,#$0E,#$07,#$33,#$C0,#$8E,#$D8,#$89,#$C6,
  48.                        #$BF,#$17,#$01,#$B9,#$00,#$02,#$F3,#$A5,#$FB,
  49.                        #$BA,#$17,#$05,#$CD,#$27);
  50. BEGIN
  51.   WITH ProgPtr^ DO
  52.     IF DosVersion >= 3 THEN
  53.       MarkFound_ := (Name = MarkName)
  54.     ELSE
  55.       MarkFound_ := (Search(Ptr(Segment,$100)^) = Search(MarkCode));
  56. END;
  57.  
  58. BEGIN
  59.   MarkFound := NotFound;
  60.   ProgPtr := LastProg;
  61.   WHILE NOT MarkFound_ AND (ProgPtr <> FirstProg) DO
  62.     WITH ProgPtr^ DO
  63.       IF Name = 'COMMAND' THEN BEGIN
  64.         MarkFound := ShellError;
  65.         Exit;
  66.       END ELSE
  67.         ProgPtr := Last;
  68.   IF ProgPtr <> FirstProg THEN BEGIN
  69.     Segment := ProgPtr^.Segment;
  70.     MarkFound := OK;
  71.   END;
  72. END;
  73.  
  74. (* ------------------------------------------------------------------------- *)
  75.  
  76. PROCEDURE RestoreIntVecTable (Seg : WORD);
  77.   (* kopiert die von MARK gesicherte Interrupt-Vektor-Tabelle wieder an ih-
  78.      ren ursprünglichen Platz am Speicheranfang bei Adresse $0000:$0000      *)
  79. BEGIN
  80.   INLINE
  81.     ($FA/                  (*  CLI                ;Interrupts verbieten      *)
  82.      $06/                  (*  PUSH    ES         ;Extrasegment sichern      *)
  83.      $1E/                  (*  PUSH    DS         ;Datensegment sichern      *)
  84.      $8B/$86/Seg/          (*  MOV     AX,Seg     ;MARK-Segment holen...     *)
  85.      $8E/$D8/              (*  MOV     DS,AX      ;...und nach DS laden      *)
  86.      $BE/$17/$01/          (*  MOV     SI,0117    ;Beginn der IntVec-Tabelle *)
  87.      $31/$C0/              (*  XOR     AX,AX      ;AX löschen, ...           *)
  88.      $8E/$C0/              (*  MOV     ES,AX      ;...als Segment nach ES... *)
  89.      $89/$C7/              (*  MOV     DI,AX      ;...und als Offset nach DI *)
  90.      $B9/$00/$02/          (*  MOV     CX,0200    ;Länge der IntVec-Tabelle  *)
  91.      $F3/                  (*  REPZ               ;Kopieren bis Tabellenende *)
  92.      $A5/                  (*  MOVSW              ;                          *)
  93.      $1F/                  (*  POP     DS         ;Datensegment wiederholen  *)
  94.      $07/                  (*  POP     ES         ;Extrasegment wiederholen  *)
  95.      $FB)                  (*  STI                ;Interrupts zulassen       *)
  96. END;
  97.  
  98. (* ------------------------------------------------------------------------- *)
  99.  
  100. PROCEDURE GetPtr (VAR LastProg : EntryPtr);
  101.   (* liefert einen Zeiger auf den letzten Eintrag der Programm-Liste *)
  102. VAR
  103.   ProgPtr : EntryPtr;
  104. BEGIN
  105.   ProgPtr := FirstProg;
  106.   WHILE ProgPtr^.Next^.Next <> NIL DO
  107.     ProgPtr := ProgPtr^.Next;
  108.   LastProg := ProgPtr;
  109. END;
  110.  
  111. (* ------------------------------------------------------------------------- *)
  112.  
  113. PROCEDURE ReleaseMemory (ProgPtr : EntryPtr);
  114.   (* gibt den durch "ProgPtr" bezeichneten Speicherbereich wieder frei *)
  115.  
  116. PROCEDURE ReleaseBlock (Segment : WORD);
  117.   (* gibt das vom DOS allokierte Segment "Segment" wieder frei *)
  118. VAR
  119.   Regs : Registers;
  120. BEGIN
  121.   WITH Regs DO BEGIN
  122.     ES := Segment;
  123.     AH := $49;                       (* DOS-Funktion "Free Allocated Memory" *)
  124.     MsDos (Regs);
  125.     IF Odd (Flags) THEN
  126.       WriteLn ('Error releasing ', ProgPtr^.Name);
  127.     END;
  128. END;
  129.  
  130. BEGIN
  131.   WITH ProgPtr^ DO BEGIN
  132.     IF Segs = 2 THEN                                (* Environment freigeben *)
  133.       ReleaseBlock (MemW[Segment:$2C]);
  134.       ReleaseBlock (Segment);
  135.   END;
  136. END;
  137.  
  138. (* ----------------------------- Hauptprogramm ----------------------------- *)
  139.  
  140. BEGIN
  141.   MakeMemoryMap (FirstProg);            (* Zeiger auf erstes  Programm holen *)
  142.   GetPtr (LastProg);                    (* Zeiger auf letztes Programm holen *)
  143.   WriteLn (^M^J'RELEASE  v3.1'^M^J);
  144.   CASE MarkFound(Seg) OF
  145.  
  146.     OK:
  147.       BEGIN
  148.         RestoreIntVecTable (Seg);      (* Interrupt-Vektoren auf alten Stand *)
  149.         REPEAT
  150.           ReleaseMemory (LastProg);                    (* Speicher freigeben *)
  151.           WITH LastProg^ DO
  152.             IF Segment <> Seg THEN              (* MARK wird nicht angezeigt *)
  153.               WriteLn (Name, ' released....');
  154.           LastProg := LastProg^.Last;                   (* nächstes Programm *)
  155.         UNTIL LastProg^.Segment < Seg;       (* bis MARK-Segment freigegeben *)
  156.       END;
  157.  
  158.     NotFound:
  159.       WriteLn ('MARK was not found!');
  160.  
  161.     ShellError:
  162.       WriteLn ('Can''t release across current DOS shell!');
  163.  
  164.   END;
  165. END.
  166.