home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turbo Toolbox
/
Turbo_Toolbox.iso
/
1988
/
02
/
mmr
/
release.pas
< prev
Wrap
Pascal/Delphi Source File
|
1987-11-11
|
6KB
|
117 lines
(*---------------------------------------------------------------------------*)
(* 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.