home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* UTIL.PAS *)
- (* (c) Jörn Eichler & DMV-Verlag *)
- (* ------------------------------------------------------ *)
- UNIT Util;
-
- INTERFACE
-
- TYPE
- PtrRec = RECORD (* Bildet einen Zeiger im Speicher *)
- Ofs : Word; (* nach, so daß auf seine Bestand- *)
- Seg : Word; (* teile zugegriffen werden kann. *)
- END;
-
- pFloat = ^tFloat; (* Zeiger auf eine Floatvariable *)
- tFloat = Real; (* Grundlage ist Real *)
-
- pLinkHeader = ^tLinkHeader;
- (* Beginn jedes Link-Kontroll- *)
- tLinkHeader = RECORD (* Blocks (Objekt<->Prozedur) *)
- ShortJMP : Byte; (* short jmp an den Beginn des *)
- Offset : ShortInt;(* eigentlichen Verknüpfungscodes *)
- LinkSize : Word; (* Länge des Kontrollblocks *)
- (* ab hier DataSize eigene Daten *)
- END;
-
- VAR
- BIOSTimer : LongInt ABSOLUTE $40:$6C;
-
- FUNCTION GetInterruptLink(Method, Self : Pointer;
- DataSize : Byte) : Pointer;
- FUNCTION GetProcedureLink(Method, Self : Pointer;
- DataSize : Byte) : Pointer;
- PROCEDURE DisposeLink(VAR Link : Pointer);
-
- FUNCTION GetCPUOccupation : INTEGER;
- (* CPU-Ressourcen in % *)
-
- FUNCTION PtrToInt(p : Pointer) : LongInt;
- FUNCTION IntToPtr(l : LongInt) : Pointer;
- FUNCTION AddPtr(p : Pointer; Size : LongInt) : Pointer;
- PROCEDURE IncPtr(VAR p; Size : LongInt);
- PROCEDURE NormalizePtr(VAR p);
-
- IMPLEMENTATION
-
- CONST
- LowestCPUOccupation : LongInt = 0;
-
- FUNCTION GetCPUOccupation : INTEGER;
- (* Ermittelt die momentane Auslastung der CPU in *)
- (* Prozent relativ zur geringsten Auslastung, bei *)
- (* der diese Routine aufgerufen wurde. Gemessen wird *)
- (* die Beanspruchung des Systems durch Hintergrund- *)
- (* prozesse. *)
- VAR
- StartTimer : LongInt;
- Occupation : LongInt;
- BEGIN
- Occupation := 0;
- StartTimer := BIOSTimer + 1;
- WHILE (StartTimer > BIOSTimer) DO ;
- StartTimer := BIOSTimer + 2;
- WHILE (StartTimer > BIOSTimer) DO
- Inc(Occupation);
- IF (Occupation > LowestCPUOccupation) THEN
- LowestCPUOccupation := Occupation;
- GetCPUOccupation := 100 -
- Round((Occupation / LowestCPUOccupation) * 100);
- END;
-
- PROCEDURE InterruptLink; ASSEMBLER;
- ASM
-
- (* Header wird von der Link-Routine eingefügt! *)
-
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH DS
- PUSH ES
-
- MOV AX, Seg @DATA (* DS mit Datensegment laden *)
- MOV DS, AX
- MOV AX, $FFFF (* Segmentteil von Self *)
- PUSH AX
- MOV AX, $FFFF (* Offsetteil von Self *)
- PUSH AX
- DB $9A (* call intersegment direct *)
- DD 0 (* method address *)
-
- POP ES
- POP DS
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- POP AX
- IRET
- END;
-
- FUNCTION GetInterruptLink(Method, Self : Pointer;
- DataSize : Byte ) : Pointer;
- (* Ermöglicht die Verwendung einer Objekt-Methode als *)
- (* Interrupt-Routine. Die Methode muß dabei ohne *)
- (* Parameter definiert sein. Der zurückgelieferte *)
- (* Kontrollblock dient gleichzeitig zur *)
- (* Deinstallation der Verknüpfung und wird als *)
- (* Interruptroutine verwendet. *)
- (* Eingabe: *)
- (* Method = Zeiger auf die Objektmethode *)
- (* (z.B. @Demo.Method) *)
- (* Self = Zeiger auf die Instanz (immer @Self) *)
- (* DataSize = eventuell noch zusätzlich verwendbarer*)
- (* Speicher auf dem innerhalb des *)
- (* Kontrollblockes (nach dem tLinkHeader)*)
- (* Ausgabe: *)
- (* Zeiger auf den Kontrollblock, der wie ein Zeiger *)
- (* auf eine Interruptroutine verwendet werden kann *)
- (* und zur Deinstallation der Verknüpfung benötigt *)
- (* wird. NIL = Fehler. *)
- TYPE
- pInterruptLink = ^tInterruptLink;
- tInterruptLink = RECORD
- Code1 : ARRAY[1..14] OF BYTE;
- SelfSeg : Word;
- Code2 : ARRAY[1..2] OF BYTE;
- SelfOfs : WORD;
- Code3 : ARRAY[1..2] OF BYTE;
- Method : Pointer;
- Code4 : ARRAY[1..9] OF BYTE;
- END;
- VAR
- Link : Pointer;
- BEGIN
- GetInterruptLink := NIL;
- IF (Method = NIL) OR (Self = NIL) OR
- (DataSize > 122) THEN Exit;
- GetMem(Link, SizeOf(tInterruptLink) +
- SizeOf(tLinkHeader) + DataSize);
- WITH pLinkHeader(Link)^ DO BEGIN
- ShortJMP := $EB;
- Offset := 2 + DataSize;
- LinkSize := SizeOf(tInterruptLink) +
- SizeOf(tLinkHeader) + DataSize;
- END;
- GetInterruptLink := Link;
- IncPtr(Link, SizeOf(tLinkHeader) + DataSize);
- Move(Pointer(@InterruptLink)^, Link^,
- SizeOf(tInterruptLink));
- WITH pInterruptLink(Link)^ DO BEGIN
- SelfSeg := PtrRec(Self).Seg;
- SelfOfs := PtrRec(Self).Ofs;
- END;
- pInterruptLink(Link)^.Method := Method;
- END;
-
- PROCEDURE ProcedureLink; ASSEMBLER;
- ASM
-
- (* Header wird von Link-Prozedur eingefügt,
- DS muß bereits Datensegment
- enthalten, die übrigen Register sind undefiniert... *)
-
- POP AX (* Rücksprungadresse sichern *)
- POP BX
-
- MOV CX, $FFFF (* @Self als impliziten Para- *)
- PUSH CX (* meter auf den Stack *)
- MOV CX, $FFFF
- PUSH CX
-
- PUSH BX (* Rücksprungadresse zurück- *)
- PUSH AX (* schreiben *)
-
- DB $EA (* jump intersegment direct *)
- DD 0 (* method address *)
- END;
-
- FUNCTION GetProcedureLink(Method, Self : Pointer;
- DataSize : BYTE) : Pointer;
- (* Ermöglicht die Verwendung einer Objektmethode als *)
- (* "normale" Funktion bzw. Prozedur z.B. über *)
- (* Prozedurzeiger. *)
- TYPE
- pProcedureLink = ^tProcedureLink;
- tProcedureLink = RECORD
- Code1 : ARRAY [1..3] OF BYTE;
- SelfSeg : WORD;
- Code2 : ARRAY [1..2] OF BYTE;
- SelfOfs : WORD;
- Code3 : ARRAY [1..4] OF BYTE;
- Method : Pointer;
- END;
- VAR
- Link : Pointer;
- BEGIN
- GetProcedureLink := NIL;
- IF (Method = NIL) OR (Self = NIL) OR
- (DataSize > 122) THEN Exit;
- GetMem(Link, SizeOf(tProcedureLink) +
- SizeOf(tLinkHeader) + DataSize);
- WITH pLinkHeader(Link)^ DO BEGIN
- ShortJMP := $EB;
- Offset := 2 + DataSize;
- LinkSize := SizeOf(tProcedureLink) +
- SizeOf(tLinkHeader) + DataSize;
- END;
- GetProcedureLink := Link;
- IncPtr(Link, SizeOf(tLinkHeader) + DataSize);
- Move(Pointer(@ProcedureLink)^, Link^,
- SizeOf(tProcedureLink));
- WITH pProcedureLink(Link)^ DO BEGIN
- SelfSeg := PtrRec(Self).Seg;
- SelfOfs := PtrRec(Self).Ofs;
- END;
- pProcedureLink(Link)^.Method := Method;
- END;
-
- PROCEDURE DisposeLink(VAR Link : Pointer);
- (* Löscht die mittels GetInterruptLink oder *)
- (* GetProcedureLink erstellte Verknüpfung zwischen einer*)
- (* Objektmethode und ihrem Äquvivalent vom Heap. *)
- BEGIN
- IF (Link <> NIL) AND
- (pLinkHeader(Link)^.ShortJMP = $EB) THEN BEGIN
- FreeMem(Link, pLinkHeader(Link )^.LinkSize);
- Link := NIL;
- END;
- END;
-
- FUNCTION PtrToInt(p : Pointer) : LongInt;
- BEGIN
- PtrToInt := (LongInt(PtrRec(p).Seg) SHL 4) +
- PtrRec(p).Ofs;
- END;
-
- FUNCTION IntToPtr(l : LongInt) : Pointer;
- BEGIN
- IntToPtr := Ptr(Word(l SHR 4), l AND $F);
- END;
-
- FUNCTION AddPtr(p : Pointer; Size : LongInt) : Pointer;
- BEGIN
- AddPtr := IntToPtr(PtrToInt(p) + Size);
- END;
-
- PROCEDURE IncPtr(VAR p; Size : LongInt);
- BEGIN
- Pointer(p) := IntToPtr(PtrToInt(Pointer(p)) + Size);
- END;
-
- PROCEDURE NormalizePtr(VAR p);
- BEGIN
- Inc(PtrRec(p).Seg, PtrRec(p).Ofs SHR 4);
- PtrRec(p).Ofs := PtrRec(p).Ofs AND $F;
- END;
-
- END.
- (* ------------------------------------------------------ *)
- (* Ende von UTIL.PAS *)
-