I was just curious why the follow doesn't work(makes app just exit silently)
test proc
LOCAL one[2000]:byte
LOCAL two[2000]:byte
LOCAL three[2000]:byte
LOCAL four[2000]:byte
LOCAL five[2000]:byte
LOCAL six[2000]:byte
LOCAL seven[2000]:byte
invoke MessageBox,0,SADD("test"),NULL,MB_OK
ret
test endp
yet the following works
test proc
LOCAL one[2000]:byte,two,three,four,five,six,seven
invoke MessageBox,0,SADD("test"),NULL,MB_OK
ret
test endp
just a hunch, but i think you ran out of stack space trying to create 14000 bytes of local memory. you could try reserving more stack space using .STACK 32768. however, i do not know the absolute limit for variable sizes. i do however know that you cannot have a single variable one million bytes big. ;)
Hi,
LOCAL one[2000]:byte,two,three,four,five,six,seven
I think in the second case, you only get the ONE var in 2000 bytes and the rest are DWORDS.
So it takes only 2024 bytes. The other one takes 14000 bytes.
Thomas :U
This is a typical stack probing problem.
I just saw that MASM allows us to write custom PROLOGUE/EPILOGUE macros so I'm starting to work on a stack probe macro.
Hopefully it may be ready soon... ::)
You may find the solution at these links:
http://board.win32asmcommunity.net/viewtopic.php?t=19497
and
http://www.old.masmforum.com/viewtopic.php?t=4543&highlight=
hth,
farrier
Here is a draft of a PROLOGUE macro that takes care of everything for you :
http://www.masmforum.com/simple/index.php?topic=2011.msg15878#msg15878
if it wouldnt be too much trouble, could someone explain the idea (in detail) of stack probing or point me in the right direction as to where to find info? looking at the code found in the "old forum", i cant quite picture what is going on. i see that the EBP register gets zeroed out but thats about it.
Hmmm... details won't be 100% exact but at least you'll get the main idea...
Windows only *reserves* the stack memory, it doesn't commit it fully at program startup.
This means that past the top of the stack (or should I say the bottom, I never know, well past the lower addresses :toothy) there is uncommitted memory that generates a GPF if you try to access it.
To allow the stack to "grow" automatically, the first uncommitted page is turned by Windows into a guard page, so that whenever this page is touched, Windows can commit it and make the next uncommitted page the guard page.
Roughly :
Higher addresses
+------------------+ <-- Start of stack
| Committed page |
+------------------+
| Committed page |
+------------------+
| Committed page | <-- ESP in this page
+------------------+
| Guard page |
+------------------+
| Uncommitted page |
+------------------+
| Uncommitted page |
+------------------+
| Uncommitted page |
+------------------+ <-- End of stack
Lower addresses
In the figure above, if you move ESP down by less than 4kb (a page size), no problem as it will be pointing to the guard page. The next access to the stack memory will trigger Windows "auto-stack-growing" feature, ie the guard page will be committed and the next uncommitted page becomes the guard page.
But if you move ESP down by more than 4kb, it will be pointing to an uncommited memory area. Thus the next access will generate a GPF, and as it occurs on the stack Windows gets scared and kills your application silently (just like if you had exhausted the whole stack memory).
The idea behing "stack probing" is : never decrement ESP by more than 4kb at a time without first dirtying the guard page.
So to allocate 8kb of stack space, you should use the following method :
sub esp, 4096
mov dword ptr [esp], 0 ; dirty the guard page
sub esp, 4096
mov dword ptr [esp], 0
; etc if you need to allocate more stack memory
Hope I am clear enough!
so its kinda like this?
at (multiples of) 4096 bytes (a page) below the current esp or ebp locations contains a 'bouncer' saying, "HEY! YOU'RE NOT GETTING PASSED ME!" i kill the 'bouncer' so im free to roam around this area.
or
the 'bouncers' are only pages away from the first committed page (at each line in your diagram). (tho as far as i can see, this contradicts the example code)
or
i am not getting it. :D
(i hope that was a good analogy) :U
In fact the "bouncer" is the *whole* guard page. Any address in the guard page triggers the "auto-grow" feature.
Whenever you "kill" the bouncer page you're free to roam around the newly committed page, and the bouncer "resurrects" into the next uncommited page.
Good analogy BTW :U
oh so the guard pages only watch the esp/ebp registers to see if they ever pass to produce the GPFs. then, if any memory location is accessed or modified in the guard's "follower", the follower is "promoted" to guard and the former guard becomes "brainwashed" follow to the cause of the program. :D
thanks for the explanation chep.
"brainwashed"... LOL! :U
Just a little comment for the sake of completeness. (If I misunderstood you and just say exactly what you said just ignore me, I don't always perfectly understand english :wink)
Quote from: Jeff on June 22, 2005, 09:03:41 AM
oh so the guard pages only watch the esp/ebp registers to see if they ever pass to produce the GPFs.
the esp/ebp registers are not watched, the trigger only occurs when the memory is really accessed (by a mov, push, ...)
Quote from: Jeff on June 22, 2005, 09:03:41 AM
then, if any memory location is accessed or modified in the guard's "follower", the follower is "promoted" to guard and the former guard becomes "brainwashed" follow to the cause of the program. :D
I would say : "if any memory location is accessed or modified in the guard page itself, ..."
Well, that was 2 comments in fact. Never mind :toothy
Higher addresses
+------------------+ <-- Start of stack
| Committed page |
+------------------+
| Committed page |
+------------------+
| Committed page | <-- ESP in this page
+------------------+
| Guard page |
+------------------+
| Uncommitted page |
+------------------+
| Uncommitted page |
+------------------+
| Uncommitted page |
+------------------+ <-- End of stack
Lower addresses
sub esp,4096...
oh hah ok. thats what i had thought at first but then i looked at the diagram wierd thinking esp/ebp was in the guard page and changed it. :green
damn i have a grammar error in that post (evidence of the change :wink )
14000Bytes, the default stack is not enough.
you must change the stack size of the linker option.