[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]