home *** CD-ROM | disk | FTP | other *** search
- (*---------------------------------------------------------------------------*)
- (* RELEASE.PAS (v2.0) *)
- (* Freigeben eines mit MARK gekennzeichneten Speicherbereichs (MS-DOS/Turbo) *)
- (* (c) 1987 Karsten Gieselmann & PASCAL International *)
- (*---------------------------------------------------------------------------*)
- PROGRAM ReleaseProgram (Output);
- {$I MAKEMAP.INC} (* einbinden der die Liste liefernden Routine *)
- Var Seg :Integer; (* Segment des letzten MARK-Aufrufs *)
- FirstProg, LastProg :Entry;
-
- (* sucht in der Programm-Liste den letzten MARK-Eintrag; wird dieser ge-
- funden, so enthaelt "Segment" das Segment dieses Eintrags, anderenfalls
- ist die Uebergabe-Variable gleich Null: *)
- Procedure FindMarker (Var Segment :Integer);
- Var ProgPtr :Entry;
-
- Function DVersion :Integer; (* DOS-Version ermitteln *)
- Var Regs :Record
- AX,BX,CX,DX,BP,DI,SI,DS,ES,Flags :Integer
- End;
- Begin
- Regs.AX := $3000; MsDos (Regs); (* Funktion 30h *)
- DVersion := Lo (Regs.AX) (* "Hauptversionsnummer" *)
- End; (* "Hi (Regs.AX)" ergibt Unterversionsnummer *)
-
- Function MarkFound :Boolean;
- Const MarkName = 'MARK'; (* Name des MARK-Programms *)
- MarkCode : Array [0..22] of Byte =
- ($FA,$0E,$07,$33,$C0,$8E,$D8,$89,$C6,$BF,$17,$01,
- $B9,$00,$02,$F3,$A5,$FB,$BA,$17,$05,$CD,$27);
- Var found :Boolean; i :Integer;
- Begin
- If DVersion >= 3 then found := (ProgPtr^.Name = MarkName)
- else begin (* DOS-Version kleiner 3.0 *)
- found := true;
- For i := 0 to 22 do
- found := found and (Mem[ProgPtr^.Segment:$100+i] = MarkCode[i]);
- End;
- MarkFound := found
- End;
-
- Begin (* FindMarker *)
- ProgPtr := LastProg;
- While not MarkFound and (ProgPtr <> FirstProg) do ProgPtr := ProgPtr^.Last;
- If ProgPtr <> FirstProg then Segment := ProgPtr^.Segment
- else Segment := $0000 (* MARK nicht gefunden! *)
- End;
-
- (* kopiert die von MARK gesicherte Interrupt-Vektor-Tabelle wieder an ih-
- ren ursprünglichen Platz am Speicheranfang bei Adresse $0000:$0000 *)
- Procedure RestoreIntVecTable (Seg :Integer);
- Begin
- Inline ($FA/ (* CLI ;Interrupts verbieten *)
- $06/ (* PUSH ES ;Extrasegment sichern *)
- $1E/ (* PUSH DS ;Datensegment sichern *)
- $8B/$86/Seg/ (* MOV AX,Segm ;MARK-Segment holen... *)
- $8E/$D8/ (* MOV DS,AX ;...und nach DS laden *)
- $BE/$17/$01/ (* MOV SI,0117 ;Beginn der IntVec-Tabelle *)
- $31/$C0/ (* XOR AX,AX ;AX loeschen, ... *)
- $8E/$C0/ (* MOV ES,AX ;...als Segment nach ES... *)
- $89/$C7/ (* MOV DI,AX ;...und als Offset nach DI *)
- $B9/$00/$02/ (* MOV CX,0200 ;Laenge der IntVec-Tabelle *)
- $F3/ (* REPZ ;Kopieren bis Tabellenende *)
- $A5/ (* MOVSW ; *)
- $1F/ (* POP DS ;Datensegment wiederholen *)
- $07/ (* POP ES ;Extrasegment wiederholen *)
- $FB) (* STI ;Interrupts zulassen *)
- End;
-
- (* liefert einen Zeiger auf den letzten Eintrag der Programm-Liste: *)
- Procedure GetPtr (Var LastProg :Entry);
- Var ProgPtr :Entry;
- Begin
- ProgPtr := FirstProg;
- While ProgPtr^.Next^.Next <> Nil do ProgPtr := ProgPtr^.Next;
- LastProg := ProgPtr
- End;
-
- (* gibt den durch "ProgPtr" bezeichneten Speicherbereich wieder frei: *)
- Procedure Release (ProgPtr :Entry);
- VAR error: Boolean;
- (* gibt das vom DOS allokierte Segment "Segment" wieder frei: *)
- (* (PASCAL 4/87, 'Externe Kommandos in Turbo Pascal', S.72 ff) *)
- Function MFree (Block_Segment :Integer) :Integer;
- Var Regs :Record
- AX,BX,CX,DX,BP,DI,SI,DS,ES,Flags :Integer
- End;
- Begin (* DOS-Funktion "Free Allocated Memory" *)
- Regs.ES := Block_Segment; Regs.AX := $4900; MsDos (Regs);
- If odd (Regs.Flags) then MFree := Lo (Regs.AX) Else MFree := 0;
- End;
-
- Begin (* Release *)
- error := false; Write ('Freigabe von ',ProgPtr^.Name);
- If ProgPtr^.Segs = 2 then (* Environment freigeben *)
- error := MFree (MemW[ProgPtr^.Segment:$2C]) <> 0;
- error := error or (MFree (ProgPtr^.Segment) <> 0);
- If error THEN Write (' Achtung: Fehler bei Freigabe');
- Writeln;
- End;
-
- Begin (* Release_Prog *)
- Lowvideo; WriteLn; Write ('RELEASE v2.0');
- Writeln (' (c) 1987 Karsten Gieselmann & PASCAL Int.'); Writeln;
- MakeMemoryMap (FirstProg); (* Zeiger auf 1. Programm holen *)
- GetPtr (LastProg); (* Zeiger auf letztes Programm holen *)
- FindMarker (Seg);
- If Seg <> 0 then begin (* ist MARK ueberhaupt vorhanden? *)
- RestoreIntVecTable (Seg); (* Interrupt-Vektoren wieder auf alten Stand *)
- Repeat
- Release (LastProg); (* Speicher freigeben *)
- LastProg := LastProg^.Last; (* naechstes Programm *)
- until Lower (LastProg^.Segment, Seg) (* bis MARK-Segment freigegeben *)
- End
- else WriteLn ('Fehler: kein MARK gefunden!')
- End.