[Back to MEMORY SWAG index] [Back to Main SWAG index] [Original]
{
The program StackUse below measures your EXACT stack usage
(REAL mode only). Make sure the constant Ssize is equal to the
actual physical stack size as defined with the $M directive or
in the Turbo Pascal IDE settings (the Options/MemorySizes menu).
For your own programs, you just need to call Initstack at the very
start, then call StackReport whenever you want - or calculate for
yourself, (Ssize-(VirginStack-StackLimit)) equals the number of
stack bytes actually used.
Sptr gives you the current stack pointer, and StackLimit is
a TP system variable (WORD) that contains the current bottom of
of the stack. StackLimit is usually zero, but some 'sneaky'
programs raise it so they can hide something there - for example,
c1;0compiling your program using the replacement run-time libraries
by Norbert Juffa can raise the StackLimit to 512.
The stack is filled from top to bottom, so a stack overflow
means Sptr <= StackLimit.
UseStack is just an example of a procedure that makes heavy
use of the stack.
This code can be freely included in any FAQ,
SNIPPETS, SWAG or what-have-you.
 Erik de Neve
 Internet:    100121.1070@compuserve.com
 Last update:  March  8, 1994
{ -*- CUT HERE -*- }
Program StackUse;
{$M 16384,0,0 }
CONST
 Ssize = 16384; {should match stack size as set by the $M directive }
Procedure Initstack;  { fills unused stack with marker value }
 Assembler;
 ASM
   PUSH SS      { SS = the stack segment }
   POP  ES
   MOV  DI,StackLimit
   MOV  CX,SP    { SP = stack pointer register }
   SUB  CX,DI
   MOV  AL,77    { arbitrary marker value }
   CLD
   REP  STOSB
 END;
Function VirginStack:word;  { finds highest unused byte on stack }
 Assembler;
 ASM
   PUSH SS
   POP  ES
   MOV  DI,StackLimit   { is usually 0 }
   MOV  CX,SP
   SUB  CX,DI
   MOV  AL,77  { marker value, must be the same as in InitStack }
   CLD
   REPE SCASB  { scan empty stack }
   DEC  DI     { adjust for last non-matching byte in the scan }
   MOV  AX,DI
 END;
Procedure StackReport; { Reports all sizes in bytes and percentages }
begin
 WriteLn('Stack Bottom : ',StackLimit:6);
 WriteLn('Current SP   : ',Sptr:6);
 WriteLn('Total Stack  : ',Ssize:6,
 ' bytes   = 100.00 %');
 WriteLn('  Now used   : ',Ssize-(Sptr-StackLimit):6,
 ' bytes   = ',(Ssize-(Sptr-StackLimit))/Ssize *100:6:2,' %');
 WriteLn(' Ever used   : ',Ssize-(VirginStack-StackLimit):6,
 ' bytes   = ',(Ssize-(VirginStack-StackLimit))/Ssize *100:6:2,' %');
 WriteLn('Never used   : ',(VirginStack-StackLimit):6,
 ' bytes   = ',(VirginStack-StackLimit)/Ssize *100:6:2,' %');
end;
Procedure UseStack(CNT:WORD); Assembler;  { example stack usage }
 ASM
   MOV  AX,0    {dummy value}
   MOV  CX,CNT
@pushit:        {perform CNT PUSHes}
   PUSH AX
   LOOP @pushit
   MOV  CX,CNT
@poppit:        {perform CNT POPs}
   POP  AX
   LOOP @poppit
 END;
BEGIN
 InitStack;      { prepare stack }
 UseStack(1000); { perform a number of PUSHes and POPs }
 StackReport;    { report stack usage }
END.
[Back to MEMORY SWAG index] [Back to Main SWAG index] [Original]