143 lines
5.4 KiB
NASM
143 lines
5.4 KiB
NASM
|
page ,132
|
||
|
title chkstk - C stack checking routine
|
||
|
;***
|
||
|
;chkstk.asm - C stack checking routine
|
||
|
;
|
||
|
; Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
|
||
|
;
|
||
|
;Purpose:
|
||
|
; Provides support for automatic stack checking in C procedures
|
||
|
; when stack checking is enabled.
|
||
|
;
|
||
|
;Revision History:
|
||
|
; 04-21-87 SKS Added conditional assembly switch for STKHQQ = 0
|
||
|
; 07-23-87 MAG [1] Added run-time CS:IP error processing for QC
|
||
|
; 08-17-87 JLS [2] Remove all references to DGROUP
|
||
|
; 08-25-87 JLS [3] Shift include files
|
||
|
; 11-13-87 SKS OS/2 Reentrant version, add thread ID check
|
||
|
; 11-18-87 SKS Make STKHQQ an array (oops!)
|
||
|
; 12-14-87 SKS add .286p to allow PUSH immediate value
|
||
|
; 02-19-88 SKS Change minimum bottom limit to STACKSLOP, not 0
|
||
|
; 06-01-88 PHG Merge DLL and normal versions
|
||
|
; 09-21-88 WAJ initial 386 version
|
||
|
; 10-18-88 JCR Chkstk was trashing bx... not good on 386
|
||
|
; 06-06-89 JCR 386 mthread support
|
||
|
; 06-20-89 JCR 386: Removed _LOAD_DGROUP code
|
||
|
; 04-06-90 GJF Fixed the copyright.
|
||
|
; 06-21-90 GJF Rewritten to probe pages
|
||
|
; 10-15-90 GJF Restored _end and STKHQQ.
|
||
|
; 03-19-91 GJF Revised to preserve all registers except eax. Note
|
||
|
; this is _rchkstk functionality so there is no longer
|
||
|
; a separate _rchkstk routine.
|
||
|
; 08-01-91 GJF Got rid of _end and STKHQQ, except for Cruiser
|
||
|
; (probably not needed for Cruiser either) [_WIN32_].
|
||
|
; 09-27-91 JCR Merged Stevewo' changes from NT tree
|
||
|
; 09-06-94 CFW Nuke Cruiser.
|
||
|
; 12-03-94 SKS Remove include of obsolete file msdos.inc
|
||
|
; 12-13-94 GJF Better version from Intel (old jmp eax method of
|
||
|
; returning is too expensive on P6).
|
||
|
; 09-11-98 GJF Fixed handling of very small frames.
|
||
|
; 12-10-99 GB Changed both _chkstk and _alloca_probe to procedure
|
||
|
;
|
||
|
;*******************************************************************************
|
||
|
|
||
|
.xlist
|
||
|
include cruntime.inc
|
||
|
.list
|
||
|
|
||
|
; size of a page of memory
|
||
|
|
||
|
_PAGESIZE_ equ 1000h
|
||
|
|
||
|
|
||
|
CODESEG
|
||
|
|
||
|
page
|
||
|
;***
|
||
|
;_chkstk - check stack upon procedure entry
|
||
|
;
|
||
|
;Purpose:
|
||
|
; Provide stack checking on procedure entry. Method is to simply probe
|
||
|
; each page of memory required for the stack in descending order. This
|
||
|
; causes the necessary pages of memory to be allocated via the guard
|
||
|
; page scheme, if possible. In the event of failure, the OS raises the
|
||
|
; _XCPT_UNABLE_TO_GROW_STACK exception.
|
||
|
;
|
||
|
; NOTE: Currently, the (EAX < _PAGESIZE_) code path falls through
|
||
|
; to the "lastpage" label of the (EAX >= _PAGESIZE_) code path. This
|
||
|
; is small; a minor speed optimization would be to special case
|
||
|
; this up top. This would avoid the painful save/restore of
|
||
|
; ecx and would shorten the code path by 4-6 instructions.
|
||
|
;
|
||
|
;Entry:
|
||
|
; EAX = size of local frame
|
||
|
;
|
||
|
;Exit:
|
||
|
; ESP = new stackframe, if successful
|
||
|
;
|
||
|
;Uses:
|
||
|
; EAX
|
||
|
;
|
||
|
;Exceptions:
|
||
|
; _XCPT_GUARD_PAGE_VIOLATION - May be raised on a page probe. NEVER TRAP
|
||
|
; THIS!!!! It is used by the OS to grow the
|
||
|
; stack on demand.
|
||
|
; _XCPT_UNABLE_TO_GROW_STACK - The stack cannot be grown. More precisely,
|
||
|
; the attempt by the OS memory manager to
|
||
|
; allocate another guard page in response
|
||
|
; to a _XCPT_GUARD_PAGE_VIOLATION has
|
||
|
; failed.
|
||
|
;
|
||
|
;*******************************************************************************
|
||
|
|
||
|
public _alloca_probe
|
||
|
|
||
|
_chkstk proc
|
||
|
|
||
|
_alloca_probe = _chkstk
|
||
|
|
||
|
cmp eax, _PAGESIZE_ ; more than one page?
|
||
|
jae short probesetup ; yes, go setup probe loop
|
||
|
; no
|
||
|
neg eax ; compute new stack pointer in eax
|
||
|
add eax,esp
|
||
|
add eax,4
|
||
|
test dword ptr [eax],eax ; probe it
|
||
|
xchg eax,esp
|
||
|
mov eax,dword ptr [eax]
|
||
|
push eax
|
||
|
ret
|
||
|
|
||
|
probesetup:
|
||
|
push ecx ; save ecx
|
||
|
lea ecx,[esp] + 8 ; compute new stack pointer in ecx
|
||
|
; correct for return address and
|
||
|
; saved ecx
|
||
|
|
||
|
probepages:
|
||
|
sub ecx,_PAGESIZE_ ; yes, move down a page
|
||
|
sub eax,_PAGESIZE_ ; adjust request and...
|
||
|
|
||
|
test dword ptr [ecx],eax ; ...probe it
|
||
|
|
||
|
cmp eax,_PAGESIZE_ ; more than one page requested?
|
||
|
jae short probepages ; no
|
||
|
|
||
|
lastpage:
|
||
|
sub ecx,eax ; move stack down by eax
|
||
|
mov eax,esp ; save current tos and do a...
|
||
|
|
||
|
test dword ptr [ecx],eax ; ...probe in case a page was crossed
|
||
|
|
||
|
mov esp,ecx ; set the new stack pointer
|
||
|
|
||
|
mov ecx,dword ptr [eax] ; recover ecx
|
||
|
mov eax,dword ptr [eax + 4] ; recover return address
|
||
|
|
||
|
push eax ; prepare return address
|
||
|
; ...probe in case a page was crossed
|
||
|
ret
|
||
|
_chkstk endp
|
||
|
|
||
|
end
|