down stack space

Started by
27 comments, last by fir 10 years, 3 months ago
Some times ago i was writing simple asm routines for test (32 bit windows with nasm)
and i created this

RoundToInt:
  fld dword [esp+4]
  fistp dword [esp-4]
  mov eax, dword [esp-4]
  ret
attention, this procedure is probably wrong (i not noticed it back then only later) because i used low 'undocumented'(?) part of stack
[esp+4] is first caller argument here
[esp] is call return adres
[esp-4] and further down is unused stack but probably can be overvrited if some interrupt will appear (???)
- I am not sure because i do not know if interrupts are using the same stack as regular process (probably no but i am not sure and this way of using down stack is like 'undocumented') :/
well maybe i will make a topic for that maybe someone will answer me
does somebody know ? is it physically safe but legally unsafe (can break on the other system)? or maybe it is safe both ways safe or both ways unsafe?
Advertisement

http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html has documentation for each assembly instruction, including IRET and INT, to answer exactly how every single instruction uses ESP, every other register, what faults can occur, etc.

I will link to someone else doing what you are doing so you can see the normal way that doesn't risk a corrupt stack: http://stereopsis.com/FPU.html (look under fistp section). Creating the extra stack variable to use will almost never run slower on a modern x86 CPU due to optimizations they perform. It would also be safer to reuse your call parameter (switching from float to int) than to use unallocated stack space if you're dead set on not making an extra stack variable.

I dont know why you are still wasting time with such micro-useless optimization, but anyway, take a look at this.

I dont mean to be rude, but you've been arguing for a week in the other thread about the same kind of stuffs, even after 20 different ppl told you so.

Im casting int to float and vice versa often in my code and i've never really seen any noticable performance hit so bad that i would have to ressort to assembly,

and im pretty sure compilers are smart enough to generate very good code for this. (And no i dont have a core-i7, im still on my olddd athlon 5000+)

I dont know why you are still wasting time with such micro-useless optimization, but anyway, take a look at this.

I dont mean to be rude, but you've been arguing for a week in the other thread about the same kind of stuffs, even after 20 different ppl told you so.

Im casting int to float and vice versa often in my code and i've never really seen any noticable performance hit so bad that i would have to ressort to assembly,

and im pretty sure compilers are smart enough to generate very good code for this. (And no i dont have a core-i7, im still on my olddd athlon 5000+)

this was not me, here i am curious just for knowledge (not every day you must spped up for coding gameplay, you could also wonder about the details of architecture sometimes ;/

http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html has documentation for each assembly instruction, including IRET and INT, to answer exactly how every single instruction uses ESP, every other register, what faults can occur, etc.

I will link to someone else doing what you are doing so you can see the normal way that doesn't risk a corrupt stack: http://stereopsis.com/FPU.html (look under fistp section). Creating the extra stack variable to use will almost never run slower on a modern x86 CPU due to optimizations they perform. It would also be safer to reuse your call parameter (switching from float to int) than to use unallocated stack space if you're dead set on not making an extra stack variable.

I know i could just use 4 global temp bytes, or just owerwrite input float

(this is wasted anyway) but i am just curious if this downstack can be

corrupted or this is yet- safe

This is a poor habit to get into for a number of reasons, but in this precise case I think it has no negative side effects.

Traditionally the compiler will open a function's body with a sub esp,nn instruction which "reserves" a certain chunk of stack space, and then local variables are esp+nn inside that chunk of space. You're just using the stack space without making sure esp is in the correct location first.

The reason this is a bad idea is that many, many instructions (not to mention other function calls) rely on esp being "correct." The full documentation has already been linked, but e.g. you cannot safely use push, pop, call, ret, etc. without esp being accurate. In fact it's very easy for something like this to accidentally clobber the pointer used by call/ret to store the return address, meaning you could ret into random memory and crash the process easily.

More insidious possible bugs include corrupting stack frames and confusing debuggers; stomping data; reading and returning stack garbage instead of correct values; and possibly more depending on what instructions you execute while abusing things like this.

In a nutshell: don't do this.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

This is a poor habit to get into for a number of reasons, but in this precise case I think it has no negative side effects.

Traditionally the compiler will open a function's body with a sub esp,nn instruction which "reserves" a certain chunk of stack space, and then local variables are esp+nn inside that chunk of space. You're just using the stack space without making sure esp is in the correct location first.

The reason this is a bad idea is that many, many instructions (not to mention other function calls) rely on esp being "correct." The full documentation has already been linked, but e.g. you cannot safely use push, pop, call, ret, etc. without esp being accurate. In fact it's very easy for something like this to accidentally clobber the pointer used by call/ret to store the return address, meaning you could ret into random memory and crash the process easily.

More insidious possible bugs include corrupting stack frames and confusing debuggers; stomping data; reading and returning stack garbage instead of correct values; and possibly more depending on what instructions you execute while abusing things like this.

In a nutshell: don't do this.

I do not understand - esp is correct here all the time - the only thing to worry is if using the stack values down the pointer is save (if this is avaliable or if this is not getting corrupted by some system activity

or something like that - because values down the pointer are usualy

considered as an unused part of the stack

someone was saing to me back then that interrupt can overvrite it

but i am not sure if this is possible as far as I know we got so many stacks as threads and i doubt if system interrupts use the client

processes stacks

I don't know how 32-bit Windows handles things like clock and keyboard interrupts, but in the days of MS-DOS when I did the bulk of my unsafe assembly programming, this was not safe precisely because a hardware interrupt could write junk over the unused stack space. It is possible that these days all such interrupts are handled by the OS and the user processes don't see that kind of nasty, but I doubt you are gaining anything from this potentially unsafe code.

As it was explained recently by many of us, optimizations only make sense in the context of a program that is too slow and then only in the critical parts, as identified by a profiler. Talking about this type of micro-optimization in a vacuum makes no sense.

I don't know how 32-bit Windows handles things like clock and keyboard interrupts, but in the days of MS-DOS when I did the bulk of my unsafe assembly programming, this was not safe precisely because a hardware interrupt could write junk over the unused stack space. It is possible that these days all such interrupts are handled by the OS and the user processes don't see that kind of nasty, but I doubt you are gaining anything from this potentially unsafe code.

As it was explained recently by many of us, optimizations only make sense in the context of a program that is too slow and then only in the critical parts, as identified by a profiler. Talking about this type of micro-optimization in a vacuum makes no sense.

it can make sense for example when i do write 4k demo.. or just for knowledge..

No. It's not safe. Unreserved stack space cannot be relied on to remain stable. Is it really that much trouble to just push the stack and use [esp]?

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

This topic is closed to new replies.

Advertisement