UNIT StackChk;

{$I platform.inc}

INTERFACE

PROCEDURE StackChk_Init;
FUNCTION StackChk_FindUnused : WORD;


IMPLEMENTATION


{ The stack under DOS is at most 64Kb large. The stack segment register SS }
{ is initialised to a given segment and the stack pointer register SP is   }
{ set to the maximum stack size and counts down to 0 as the stack is used. }


{--------------------------------------------------------------------------}
{ StackChk_Init                                                            }
{                                                                          }
{ This routine fills the stack with a fixed pattern. The FindUnused        }
{ routine then counts how many of these pattern words are present from     }
{ the top of the stack.
{                                                                          }
PROCEDURE StackChk_Init;

LABEL WriteLp;

BEGIN
{$IFNDEF PLATFORM_OS2_WIN32}
     ASM
        MOV AX,$EAEA        { pattern to write }
        MOV DI,16           { start at top of stack }
                            { plus little offset to avoid DPMI stack check method }
        MOV CX,SP           { get distance from top to current stack }
        SUB CX,16           { correct for offset from top we use }
        SHR CX,1            { div 2 since we write 16 bits per loop }
        SUB CX,4            { keep some margin }

     WriteLp:
        SEGSS MOV [DI],AX
        ADD DI,2
        LOOP WriteLp
     END;
{$ENDIF}
END;


FUNCTION StackChk_FindUnused : WORD;

VAR Left : WORD;

LABEL CheckLp;

BEGIN
{$IFDEF PLATFORM_OS2_WIN32}
     Left:=0;
{$ELSE}
     ASM
        MOV BX,$EAEA        { compare against this }
        MOV DI,16           { start at top of stack }
        MOV CX,SP           { distance to current stack top (=max to check) }
        SHR CX,1            { div 2 since we check 16 bits at a time }

     CheckLp:
        SEGSS MOV AX,[DI]   { read the pattern at this address }
        ADD DI,2            { increment in advance }
        CMP AX,BX           { is this the expected pattern? }
        JE CheckLp          { yes-> keep on checking }

        SUB DI,2            { correct for increment }
        MOV AX,DI           { cannot write DI to register }
        MOV Left,AX         { return result to pascal code }
     END;
{$ENDIF}
     StackChk_FindUnused:=Left;
END;


BEGIN
     StackChk_Init;
END.
