News:

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

Using the stack for scratch

Started by Jimg, July 02, 2009, 02:36:50 AM

Previous topic - Next topic

Jimg

If one writes a proc without a stack frame, does no pushes or pops, and does not call any external routines, is it save to use the stack directly for scratch, or is it possible windows will grab control in the middle of your routine and push stuff onto the stack, thus trashing your scratch variables?

e.g.

myproc proc  ; no stack frame

p1 equ dword ptr [esp-4]  ; scratch variable 1
p2 equ dword ptr [esp-8]  ; scratch variable 2

mov p1,123
.
.  ; misc benign opcodes not involving the stack or esp
.
mov eax,p1   ; is there any possibility this may have been changed by some external process?

ret
myproc endp

dedndave

if you need stack space, simply reserve it
if you need 256 bytes....

        sub     esp,100h

we were having a discussion about this very thing on another thread (Gabor's thread on sound synth)
supposedly, windows assigns private stacks for all other threads
but, if you use invoke, i am not sure that windows switches to an internal stack or not
to be on the safe side, adjust the stack pointer so the memory you want to use is above it
oh - don't forget to readjust it when you are done - lol
(btw - stack addresses should always be a multiple of 4)

here is that other thread
the opinions vary a bit - lol
http://www.masm32.com/board/index.php?topic=11608.15

MichaelW

I know that data stored in the free area of the stack would be at risk in a real-mode DOS application where hardware interrupts would use whatever stack was active at the time the interrupt occurred. But in a Windows application, under the specified conditions, I can't see any problem.
eschew obfuscation

dedndave

we need to devise some kind of test for this theory - lol
i have no idea what windows condition would use the stack for a process
and, it seems to me that, if you test it thoroughly under one OS, that doesn't make it safe under others
i dunno - i think you are asking for trouble

hutch--

This is normal stuff from writing a stack frame free procedure. What you have to do is keep track of the stack if there are any stack based arguments in nested procedures above it. Just work out what you are doing with normal LOCAL variables in a stack frame to get the stack direction then directly write a procedure without a stack frame to do the same thing.

It comes at a price, you cannot call another procedure from a proc written like this as it will mess the stack up in the calling proc. The safer alternative is doing normal stack space allocation as Dave has mentioned. This works fine and is nestable to the stack size limit.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

dedndave

better yet...

        lea     esp,[esp-256]    ;reserve 256 bytes
.
.
.
        lea     esp,[esp+256]    ;free reserved space

Jimg

Okay, thanks guys.

The only purpose for doing such a thing is to save a few cycles on an often called routine.  Messing with esp wipes out the paltry savings.

Tedd

Anything below the stack-pointer is safe (for obvious reasons,) above is considered trash - but you already knew that.
As long as you don't call any other functions, it should be safe -- i.e. no-one else uses your stack. Processes run in separate address spaces, so the pages for your stack are YOURS.
The only potential problem comes from task-switching, where your stack could be used for temporary storage of your state, but the stack is automatically switched during a ring transition, so your stack should still be left untouched.
If you want to be entirely safe, you could simply 'allocate' a chunk from the stack once at the very start of your program, and then you can consider that space completely safe and free to use - even if you call other functions. Although then you have the problem of getting a pointer to that area - ebp could be used as long as you don't use it elsewhere - but if the function is called from the same nesting (e.g. in a loop) then the location of that free area will always be at the same offset from the current stack pointer anyway, so it's just an offset from esp, which you'd be using if you were to access it directly above esp.
No snowflake in an avalanche feels responsible.