home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / win_lrn / memory / stack / stack.asm < prev   
Encoding:
Assembly Source File  |  1988-12-15  |  4.0 KB  |  129 lines

  1. ;
  2. ; WINDOWS STACK USAGE CHECKER
  3. ;
  4. ; This code checks for the amount of stack being used by a Windows application.
  5. ; It does this check by initializing the stack to a known value, then going 
  6. ; from the end of stack up until it finds the first value changed.  If the
  7. ; first value checked is changed, then it assumes the stack overflowed.
  8. ;
  9. ; The way it finds the end of the stack is by the variable rsrvptrs[6].  This
  10. ; is initialized by the Windows initialization code.  Also, the start of the
  11. ; stack is rsrvptrs[A].  rsrvptrs[8] is the stack low-water mark, but this is
  12. ; only set if _chkstk is called, and Windows doesn't call this on its entry
  13. ; points (why, I don't know).
  14. ;
  15. ; The routine InitStackUsed() initializes the stack to a known value.  The
  16. ; routine ReportStackUsed() returns an integer value which is the amount of
  17. ; stack space used, -1 if stack overflow was detected.
  18. ;
  19. ; Written 10/87 by Bill Turner.  Original concept by Bill Turner (modified from
  20. ; similar code for another environment)
  21. ;
  22.  
  23. ;
  24. ; See what memory model to use for the stack checking routines.  This is
  25. ; specified when the module is assembled by specifying -D?S for small,
  26. ; -D?M for medium.
  27. ;
  28.  
  29. if1
  30.     ifdef ?S
  31.         memS = 1
  32.         %out ! Compiling for SWINLIBC.LIB
  33.     else
  34.         memM = 1
  35.         %out ! Compiling for MWINLIBC.LIB/LWINLIBC.LIB
  36.     endif
  37. endif
  38.  
  39. ;
  40. ;   Now include the Windows macro definition file.
  41. ;
  42.  
  43. .xlist
  44. ?PLM = 1;
  45. ?WIN = 1;
  46. include cmacros.inc
  47. .list
  48.  
  49. sBegin  DATA
  50.         externW rsrvptrs
  51. sEnd    DATA
  52.  
  53. sBegin  CODE
  54. assumes CS,CODE
  55. assumes DS,DATA
  56.  
  57.         PUBLIC  InitStackUsed
  58.         PUBLIC  ReportStackUsed
  59.  
  60. ;
  61. ; void PASCAL InitStackUsed();
  62. ;
  63. ; This routine initializes the stack to a known value.  It uses the STOSW
  64. ; instruction, and therefore wipes ES, DI, AX, and CX.
  65. ;
  66.  
  67. cProc   InitStackUsed
  68. cBegin
  69.  
  70.         push    ss
  71.         pop     es
  72.         mov     di, rsrvptrs[6]         ; minimum SP value
  73.         mov     cx, sp
  74.         sub     cx, di                  ; space from end of stack to current
  75.                                         ; SP value (in bytes)
  76.         shr     cx,1                    ; convert to word count
  77.         mov     ax, 0AAAAh              ; "known value" for comparison
  78.         cld                             ; move to high memory   
  79.         rep     stosw                   ; fill memory
  80.  
  81. cEnd
  82.  
  83.  
  84. ;
  85. ; int PASCAL ReportStackUsed();
  86. ;
  87. ; This checks to see how much stack was actually used.  If the min SP value
  88. ; has been changed (ss:rsrvptrs[6]), then assume a stack overflow has occured.
  89. ; Otherwise, scan through memory until a changed address is found, and subtract
  90. ; the address from the maximum SP value (rsrvptrs[A]).  This is the amount of
  91. ; stack space used.  This routine wipes out ES, DI, AX, and CX.
  92. ;
  93.  
  94. cProc ReportStackUsed
  95. cBegin
  96.  
  97.         xor     cx, cx
  98.         dec     cx              ; put -1 into CX -- so that REPZ will go until
  99.                                 ; an address that changed is found.
  100.         push    ss
  101.         pop     es
  102.         mov     di, rsrvptrs[6]
  103.         mov     ax, 0AAAAh      ; "known value" stack was initialized to
  104.         cld                     ; move to high memory
  105.         repz    scasw
  106. ;
  107. ; At this point, DI is the next word after the change was detected.  Decrement
  108. ; by one word, and calculate stack usage.
  109. ;
  110.         cmp     di, rsrvptrs[6]         ; same as minimum value:
  111.         jz      overflowed              ; YES, report overflow
  112.         sub     di, rsrvptrs[0Ah]       ; difference in bytes (negative value)
  113.         mov     ax, di                  ; move into AX for return.
  114.         neg     ax                      ; and make a positive number
  115.         jmp     do_rtn
  116.  
  117. overflowed:
  118.         xor     ax, ax
  119.         dec     ax                      ; move -1 into AX
  120.  
  121. do_rtn:                                 ; dummy label for end of procedure
  122.  
  123. cEnd
  124.  
  125. sEnd    CODE
  126.  
  127.         end
  128. 
  129.