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