News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Retrieve available stack space

Started by Eddy, May 04, 2005, 02:10:18 PM

Previous topic - Next topic

Eddy

Hi all,

Is it possible to retrieve the amount of free stack space?

I have a recursive sub and I would like to check how much stack space I got left before my app crashes on me...
I can find the current stack pointer by reading the ESP register, but I can't find a way to find the beginning or end of the stack...

BTW, I have to confess that I normally program in PowerBASIC, with occasionally some inline assembler. So I am certainly not a die-hard assembly programmer..
Hope someone will give me some advice anyway... :wink

Kind regards
Eddy
Eddy
www.devotechs.com -- HIME : Huge Integer Math and Encryption library--

roticv

The closest I know of is fs:[4h] and fs:[8h], but I don't think that is what you want.

Eddy

I remember seeing that on the internet somewhere. If I only knew what the 'fs' stands for....  ::)   (thanks for your patience... )

[added later]
Aha! Segment register..! Got it!   :U
[/added later]


Eddy
www.devotechs.com -- HIME : Huge Integer Math and Encryption library--

doomsday

Hi Eddy,

Since you set the size of the stack when you build the program, you should be able to calculate how much ESP has moved from where it started, right?

Another way to keep track of a recursive routine is something like:

dwRecursionCount   dd   0

foo_recursive_proc:
inc    [dwRecursionCount]
;print "recursion count is now "+dwRecursionCount

; insert some code here

dec   [dwRecursionCount]
ret


Hope this helps.

regards,
-Brent

hutch--

Hi Eddy,

Welcome on board. The trick is to know first how much stack space you have and I think Bob has an ajustment with the PB compilers. Once you have this you work out what the stack overhead is for each recursion and you can work out what your limits is easily enough. If you have to run a very deep recursive algo, it may be worth increasing the stack memory. It may be a setting in PB but there are a few tools that will change the stack setting in a PE header as well.

To calcukate yor stack overhead each recursion, ad together the parameter byte count plus any locals you use and you will know what the single instance overhad is. divide your available stack memory by this figure and you will know how deep you can go. If it is possible, I would be inclined to try an iterative procedure as it saves you from recursive stack limits.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Eddy

Well, a fact is that this function is in a dll, so I do not know in advance how large the stack is. It depends on the calling app. I guess I could check the PE header to find out.

It just amazes me that it seems so difficult to find the stack limits (start and end). I expected it would be something as simple as grabbing the stack pointer from the ESP register, but apparently it is not... :(

I tried grabbing fs:[4h] and fs:[8h], but I am not sure what these values represent.  fs:[4h] could be the top of the stack, but the value of fs:[8h] seems too low to be the bottom of the stack...

Thanks all for your replies so far!!

Kind regards
Eddy
Eddy
www.devotechs.com -- HIME : Huge Integer Math and Encryption library--

Eddy

Ok, so fs:[4h] and fs:[8h] are the stacks top and base.
I read them, but the difference between the two is only 12288 (bytes??), while I have not changed default stack size, so stack should be 1 MB...

Kind regards
Eddy
Eddy
www.devotechs.com -- HIME : Huge Integer Math and Encryption library--

MichaelW

This doesn't directly determine the free stack space, but it does determine how much stack "consumption" is too much.

; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .486                       ; create 32 bit code
    .model flat, stdcall       ; 32 bit memory model
    option casemap :none       ; case sensitive

    include \masm32\include\windows.inc
    include \masm32\include\masm32.inc
    include \masm32\include\kernel32.inc
    includelib \masm32\lib\masm32.lib
    includelib \masm32\lib\kernel32.lib
    include \masm32\macros\macros.asm

; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
        start_esp dd 0
    .code
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    ; Terminated on first recursion
    ;BITESIZE EQU 2048

    ; Terminated at ~1MB
    ;BITESIZE EQU 1024

    ; Terminated at ~1MB, no change in fs:[8] for ~8 recursions ??
    BITESIZE EQU 256

    mov   start_esp,esp
    print chr$("start_esp = ")
    print ustr$(start_esp)
    print chr$(13,10,13,10)
    call  eatstack
    mov   eax,input(13,10,"Press enter to exit...")
    exit

eatstack proc
    local junk[BITESIZE]:DWORD

    assume fs:nothing

    mov   ebx,start_esp
    sub   ebx,esp
    print chr$("start_esp - esp = ")
    print ustr$(ebx)
    print chr$(" bytes",13,10)
    mov   ebx,4
    mov   ebx,fs:[ebx]
    print chr$("fs:[4] = ")
    print ustr$(ebx)
    print chr$(", fs:[8] = ")
    mov   esi,8
    mov   esi,fs:[esi]
    print ustr$(esi)
    sub   ebx,esi
    print chr$(", fs:[4] - fs:[8] = ")
    print ustr$(ebx)   
    mov   eax,input(" bytes",13,10,"Press enter to continue...",13,10)
    call eatstack
eatstack endp
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start



[attachment deleted by admin]
eschew obfuscation

ToutEnMasm

Hello,
Use VirtualQuery
invoke VirtualQuery,esp,addr memoirepile,sizeof memoirepile
memoirepile is a MEMORY_BASIC_INFORMATION structure

AllocationBase is the bottom of the region ,esp - AllocationBase = stack space available

                            ToutEnMasm

roticv

Eddy,

fs:[4h] and fs:[8h] are just the limits of the stack - ie if the stack address goes above or below it, there would be a nasty error (or rather autoexitingorprocess). That is why I said that it is not exactly what you are seeking.

http://board.win32asmcommunity.net/index.php?topic=8527.0

pbrennick

Hi Eddy,
Something worth remembering is that fs:[4h] and fs:[8h] is the stack verification cross-check used by APIs.  If you move ESP without making mods in those 2 areas the OS will kill your process as soon as it is aware (it essentially sends the equivallent of an int 3 to the process).

Also remember that the OS lives in Ring0 and maintains its own stack space.  Your process lives in Ring3 and killing your process will not harm the OS (neither will messing with ESP).  That is the 'true beauty' of the modern Windows OS.

hth:
Paul

Eddy

Guys,

I think I can do something useful with fs:[4h] and fs:[8h].
If I understand correctly, it goes something like this:
fs:[4h] is the top of the stack, which is normally fixed. fs:[8h] is the current bottom of the stack that is currently reserved by the OS. If your exe's stack size is (the default) 1MB, this 1 MB is not reserved immediately from the start of your app. Windows reserves only as much stack space as is required at that time. When your app requires more stack space, Windows reserves more stack space, hereby decreasing fs:[8h].
It is only when the reserved stack space reaches/exceeds 1 MB (or any other stack size you specified at compile time) that your app crashes...

Probably someone else can explain this better or correct me, but if Windows works like this, I can monitor the current stack space by watching fs:[4h] and fs:[8h]. If the difference between these addresses comes close to the apps stack size (1 MB default), I can sound the alarm..

The sample prog posted by MichaelW seems to confirm this...


Kind regards
Eddy
Eddy
www.devotechs.com -- HIME : Huge Integer Math and Encryption library--

QvasiModo

I think this is how it works: the system reserves 1MB, and commits as much as needed. The difference between fs:[8] and fs:[4] seems to be the currently commited stack space. This is not the difference between esp and the top of the stack... remember that virtual memory works on entire pages (4 kilobytes).

I don't know if the system will try to reserve more pages or not, after the 1MB limit is reached. :dazzled:

Eddy

Yes, that is the correct terminology and I believe that is how it works.
fs:[8] will always be less than ESP (it will be on a 4k boundary).
When the difference between fs:[8] and fs:[4] reaches 1MB (or the stack size you set) the app crashes. I tested this.

So, the actual used stack space should be the difference between fs:[4] and ESP....
I'll test this..

Thanks all for your input so far !!  :U

Kind regards
Eddy

Eddy
www.devotechs.com -- HIME : Huge Integer Math and Encryption library--

Eddy

small demo prog:

[attachment deleted by admin]
Eddy
www.devotechs.com -- HIME : Huge Integer Math and Encryption library--