home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* STACK.PAS *)
- (* (c) 1991 Gerd Cebulla & DMV-Verlag *)
- (* ------------------------------------------------------ *)
- UNIT Stack;
-
- INTERFACE
-
- TYPE
- HexString = STRING[4];
- StackProc = PROCEDURE;
-
- CONST
- Display : BOOLEAN = TRUE;
- WaitKey : BOOLEAN = TRUE;
- MinStack : WORD = $FFFF;
- OutX : BYTE = 1;
- OutY : BYTE = 1;
-
- VAR
- SystemStackProc : StackProc;
- StackSize,
- StackPtr,
- LocalSize : WORD;
- CallAddr : POINTER;
-
-
- PROCEDURE SetStackProc(NewStackProc : StackProc);
- PROCEDURE ResetStackProc;
- PROCEDURE MakeHexStr( Wert : WORD;
- VAR HexStr : HexString);
- PROCEDURE StackTracer;
- PROCEDURE Analyze;
- INLINE(
- $A3 / LocalSize / { mov LocalSize,ax }
- $89 / $E0 / { mov ax,sp }
- $05 / $06 / $00 / { add ax,6 }
- $A3 / StackPtr / { mov StackPtr,ax }
- $8B / $46 / $02 / { mov ax,[bp+2] }
- $A3 / CallAddr / { mov CallAddr,ax }
- $8B / $46 / $04 / { mov ax,[bp+4] }
- $2B / $06 / PREFIXSEG / { sub ax,PrefixSeg }
- $2D / $10 / $00 / { sub ax,10h }
- $A3 / CallAddr + 2 { mov CallAddr+2,ax }
- );
-
- IMPLEMENTATION
-
- USES
- Crt;
-
- TYPE
- CallCodePtr = ^CallCode;
- CallCode = RECORD
- Opcode : BYTE;
- ADDR : StackProc;
- END;
-
- VAR
- SaveSystemCode : CallCode;
-
-
- PROCEDURE SetStackProc(NewStackProc : StackProc);
- BEGIN
- WITH CallCodePtr(@SystemStackProc)^ DO BEGIN
- Opcode := $EA; { "jmp far" }
- ADDR := NewStackProc;
- END; { with }
- END;
-
- PROCEDURE ResetStackProc;
- BEGIN
- CallCodePtr(@SystemStackProc)^ := SaveSystemCode;
- END; { ResetStackproc }
-
- {$S-} { <-- unbedingt notwendig! }
- PROCEDURE MakeHexStr( Wert : WORD;
- VAR HexStr : HexString);
- VAR
- i,
- Nibble : BYTE;
- BEGIN
- HexStr[0] := #4;
- FOR i := 4 DOWNTO 1 DO BEGIN
- Nibble := Wert AND $000F;
- IF Nibble < 10 THEN
- HexStr[i] := CHR(Nibble + ORD('0'))
- ELSE
- HexStr[i] := CHR(Nibble - 10 + ORD('A'));
- Wert := Wert SHR 4;
- END; { for }
- END; { MakeHexStr }
-
- VAR
- Hex : HexString;
- SaveX,
- SaveY : BYTE;
-
- PROCEDURE StackTracer;
- BEGIN
- Analyze;
- IF StackPtr - LocalSize < MinStack THEN
- MinStack := StackPtr - LocalSize;
- IF Display THEN BEGIN
- SaveX := WhereX;
- SaveY := WhereY;
- GotoXY(OutX, OutY);
- MakeHexStr(SEG(CallAddr^), Hex);
- Write('Adr.=', Hex);
- MakeHexStr(OFS(CallAddr^), Hex);
- Write(':', Hex);
- MakeHexStr(StackPtr, Hex);
- Write(' SP=', Hex);
- MakeHexStr(LocalSize, Hex);
- Write(' Lok.Var.=', Hex);
- IF WaitKey THEN
- REPEAT UNTIL ReadKey <> #0;
- GotoXY(SaveX, SaveY);
- END;
- END;
-
- {$S+} { <-- unbedingt notwendig! }
- PROCEDURE InitStack;
- BEGIN
- INLINE(
- $E8 / $00 / $00 / { call $+3 ("push ip") }
- $5B / { pop bx }
- $2E / $8B / $47 / $F9 / { mov ax,cs:[bx-7] }
- $A3 / SystemStackProc / { mov SystemStackProc,ax }
- $2E / $8B / $47 / $FB / { mov ax,cs:[bx-5] }
- $A3 / SystemStackProc + 2 /
- { mov SystemStackProc+2,ax }
- $89 / $E0 / { mov ax,sp }
- $05 / $0C / $00 / { add ax,12 }
- $A3 / StackSize { mov StackSize,ax }
- );
- SaveSystemCode := CallCodePtr(@SystemStackProc)^;
- END;
-
- BEGIN
- InitStack;
- END.
- (* ------------------------------------------------------ *)
- (* Ende von STACK.PAS *)
-