The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Webring on June 21, 2005, 05:08:19 PM

Title: Local byte declaration
Post by: Webring on June 21, 2005, 05:08:19 PM
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
Title: Re: Local byte declaration
Post by: Jeff on June 21, 2005, 05:21:29 PM
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.  ;)
Title: Re: Local byte declaration
Post by: thomasantony on June 22, 2005, 03:29:01 AM
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
Title: Re: Local byte declaration
Post by: chep on June 22, 2005, 05:31:21 AM
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... ::)
Title: Re: Local byte declaration
Post by: farrier on June 22, 2005, 06:51:54 AM
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
Title: Re: Local byte declaration
Post by: chep on June 22, 2005, 07:02:45 AM
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
Title: Re: Local byte declaration
Post by: Jeff on June 22, 2005, 07:39:35 AM
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.
Title: Re: Local byte declaration
Post by: chep on June 22, 2005, 08:23:24 AM
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!
Title: Re: Local byte declaration
Post by: Jeff on June 22, 2005, 08:41:21 AM
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
Title: Re: Local byte declaration
Post by: chep on June 22, 2005, 08:50:24 AM
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
Title: Re: Local byte declaration
Post by: 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.  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.
Title: Re: Local byte declaration
Post by: chep on June 22, 2005, 09:17:39 AM
"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
Title: Re: Local byte declaration
Post by: Jeff on June 22, 2005, 09:34:37 AM
  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 )
Title: Re: Local byte declaration
Post by: Momoass on June 26, 2005, 12:28:26 PM
14000Bytes, the default stack is not enough.
you must change the stack size of the linker option.