I am coding a program using x86 instruction set. Why is it crashing when i use a local array which is stored in stack of size 40kb.
im using windows7 os with i5 processor and compiling in visual c++ express edition 2008
I think you're hitting the catch in form of the guard page.
To not waste actual memory until it's actually used, Windows initially reserves the full stack space (1MB default; can be changed by editing PE headers) but commits only two pages, and makes the second one a guard page. A guard page is a page (4KB) of memory which triggers a special exception (STATUS_GUARD_PAGE_VIOLATION) on any access to it. When the kernel detects a guard page exception, it commits the touched page and adds another guard page after it. This way, if your functions push small variables on the stack, it keeps growing "by itself".
However, there is a problem if you try to allocate a local variable which is over 4K (4096 bytes) in size. Normally, stack allocation is done by simply subtracting from the ESP. If you subtract more than 4K from it and then try writing to the stack, there is a chance that you shoot over the guard page and will access the reserved memory after it. This one won't be caught by the kernel but will be passed on to your program, and usually results in a crash.
The solution is simple - do stack allocations in chunks of 4K (=4096=0x1000 bytes) and touch the stack after each one to trigger the guard page. The MSVC compiler does it automatically by invoking the __chkstk()
function at the start of the functions which use more than 4K of local variables. Here's the listing of the function from CRT sources:
;***
;_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
push ecx
; Calculate new TOS.
lea ecx, [esp] + 8 - 4 ; TOS before entering function + size for ret value
sub ecx, eax ; new TOS
; Handle allocation size that results in wraparound.
; Wraparound will result in StackOverflow exception.
sbb eax, eax ; 0 if CF==0, ~0 if CF==1
not eax ; ~0 if TOS did not wrapped around, 0 otherwise
and ecx, eax ; set to 0 if wraparound
mov eax, esp ; current TOS
and eax, not ( _PAGESIZE_ - 1) ; Round down to current page boundary
cs10:
cmp ecx, eax ; Is new TOS
jb short cs20 ; in probed page?
mov eax, ecx ; yes.
pop ecx
xchg esp, eax ; update esp
mov eax, dword ptr [eax] ; get return address
mov dword ptr [esp], eax ; and put it at new TOS
ret
; Find next lower page and probe
cs20:
sub eax, _PAGESIZE_ ; decrease by PAGESIZE
test dword ptr [eax],eax ; probe page.
jmp short cs10
_chkstk endp
In your case you probably don't need this complex logic, something like this will do:
xor eax, eax
mov ecx, 40 ; alloc 40 pages
l1:
sub esp, 1000h ; move esp one page
mov [esp], eax ; touch the guard page
loop l1 ; keep looping
sub esp, xxxh ; alloc the remaining variables
See here for more details about stacks and guard pages.