News:

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

Why doesn't windows preserve registers?

Started by Alloy, December 04, 2008, 02:50:13 AM

Previous topic - Next topic

sinsi

I'm pretty sure that the API assumes CLD, but not sure if it restores it if it uses STD.

Since EAX is used so often for a return value (from a function or as an error code) there's no
need to save it, but I agree with saving ECX - any register will do as a counter, but ECX is traditional...

Didn't DOS push all registers (including flags) on entry to INT 21 then use [BP+xx] to return values via popping all registers?
Light travels faster than sound, that's why some people seem bright until you hear them.

jj2007

Quote from: raymond on December 09, 2008, 03:06:00 AM
Run a small app (which includes the display of a MessageBox) in Ollydbg and watch what happens to the FPU content while the MessageBox is being displayed and you simply hover over it with the mouse cursor!!! :boohoo: :boohoo:


Can't reproduce the hovering effect but indeed when the MsgBox is ready, the FPU is empty. Attached a test app. I tried a Run trace from calling the MsgBox to leaving it but could not find any FPU commands in the log file...

EDIT: Here is the culprit, it seems:

Address          Hex dump          Command                        Comments
KiFastSystemCall  8BD4             mov edx, esp
7C90EB8D          0F34             sysenter


At the moment of the call:
edx=esp=13F6BC
eax=0011DA
ecx=000108
Sysenter works more or less like an int2e interrupt, see here for a good description. The problem is that Olly cannot follow the SysEnter call, apparently.

[attachment deleted by admin]

BlackVortex

sysenter is used to make the switch to kernel mode, so that's off limits for user-level debuggers. You can try using a kernel debugger though.

Rockoon

Quote from: donkey on December 09, 2008, 06:45:50 AM
AFAIK direction flags are not changed by the API though I recall that there are API functions that will fail if the direction flag is set on entry, I still need an example of an API changing the flag before I can agree that Windows doesn't do it already.

The direction flag under stdcall is defined as always defaulting to 0. If you set DF in your own function, you should clear it before making an API call yourself, as well as before returning.

The interrupt flag should never be changed outside of ring0.

All the other flags are defined as volatile, but as you rightly observed, boolean return values are sometimes returned in the carry flag (C compilers are the main culprit in not adhering to this stdcall convention even when told to)

---

Someone had suggested that the FPU state has no definition under stdcall but thats not accurate.

The FPU should be emptied and ready for FPU work (EMMS if MMX was used) before calling a function
Functions which return a floating point value should return exactly 1 value on top of the FPU stack
Functions which do not return a floating point value should return with the FPU stack clear and ready for FPU work (EMMS if MMX was used)

When C++ compilers can be coerced to emit rcl and rcr, I *might* consider using one.

jj2007

Quote from: Rockoon on December 09, 2008, 09:19:21 PM
The FPU should be emptied and ready for FPU work (EMMS if MMX was used) before calling a function

What you write makes sense. Do you have a link, or another quotable source?

The example posted above loads all 8 FPU registers (via the MsgBox button), then calls the MessageBox. The latter works fine, but after clicking OK, the FPU is gone bananas. Which raises questions:

If MsgBox uses the FPU, why does it have no problem with a fully loaded stack? Because it uses finit??

I can't follow the Sysenter, but it seems logical, otherwise the FPU would not be usable. If it works with finit, though, then Rockoon's rule above is not necessary.

raymond

QuoteCan't reproduce the hovering effect

I had observed the hovering effect on my old P4 computer. I've just tried it on my newer computer (a Core2Duo) where I cannot reproduce that hovering effect but the FPU still gets trashed. I could be that the mouse movement is being monitored by the OS on the second core but the MessageBox is being displayed by the main core.

jj: Were you trying to observe the hovering effect on a DuoCore?
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

Rockoon

Quote from: jj2007 on December 09, 2008, 10:56:11 PM
Quote from: Rockoon on December 09, 2008, 09:19:21 PM
The FPU should be emptied and ready for FPU work (EMMS if MMX was used) before calling a function

What you write makes sense. Do you have a link, or another quotable source?

Agner Fog's calling convention reference.

http://www.agner.org/optimize/

Quote from: jj2007 on December 09, 2008, 10:56:11 PM
The example posted above loads all 8 FPU registers (via the MsgBox button), then calls the MessageBox. The latter works fine, but after clicking OK, the FPU is gone bananas. Which raises questions:

If MsgBox uses the FPU, why does it have no problem with a fully loaded stack? Because it uses finit??

It probably not only uses finit, it probably also saves and then sets its own rounding and precision flags.

Nothing is stopping a function from going above-and-beyond what is strictly required.
When C++ compilers can be coerced to emit rcl and rcr, I *might* consider using one.

Mirno

The FPU and MMX/SSE registers were originally shared within the microprocessor.
As a part of x86 64 AMD split them into separate register sets - you should not see the FPU stack getting corrupted certainly on Athlon64s and above, and I suspect the same may be true of Intel Core processors....

As to the point of the thread, the standard is the standard, the proposal that all registers should be saved and restored, and return values returned by reference, then you would find that some other programmers would have the exact same argument in reverse ("My app is using way too much stack space when I call this recursive function, why do Microsoft insist on saving the flags and registers when most of the time we don't care about them! I bet they could get away with having a standard where they only made 3 of the GPRs unchangeable, and you could then return results in eax!").

If you'll excuse me I have to go eat my boiled egg with the pointy end upwards - the proper way to do it!

Mirno

jj2007

Quote from: raymond on December 10, 2008, 01:57:19 AM

jj: Were you trying to observe the hovering effect on a DuoCore?


Yes. Which answers also Mirno's question: No, they are still shared, apparently.

Tedd

Quote from: Mirno on December 10, 2008, 03:04:53 PM
If you'll excuse me I have to go eat my boiled egg with the pointy end upwards - the proper way to do it!

Infidel!!
No snowflake in an avalanche feels responsible.

vanjast

This matters nothing to me...

I never assume anything...
I preserve all registers that I use, and pop them at the end.

A 'stitch in time saves nine'... :bg


NightWare

#41
just read this one, but there is a lot of confusion in this topic... it seems you have difficulties to separate your work from the work of the os... you must preserve the registers for YOU ! windows preserve ebx/esi/edi for HIS usage, to use those register and restaure them when finished, because of some intel instructions.

in an app, what is the interest to preserve ebx/esi/edi ? coz it's made by the os !, here for you... by doing this you simply reduce the memory bottleneck, with this useless work made twice.

you must preserve ebx/esi/edi only when you alter them. not all the time... AND FOR YOUR OWN USAGE, otherwise it's useless... however for ecx/edx and eax (when you don't need a return value) you should preserve those registers, FOR YOU !

THE UNIQUE CASE, where you absolutely need to preserve ebx/esi/edi is when you code a library, for system compatibility !

so,
1. it's not abnormal that xp don't care if YOU restaure in the wrong order, coz it's for YOU.
the abnormal thing is that win98 CARE.

2. cld/std is preserved by the OS, coz it use it. If YOU encounter a problem it's because YOU didn't reset the position like it should.

3. FPU and SIMD registers are ALSO preserved AT THEIR STATE by the OS, otherwise how can you expect to keep the values you've put inside when the OS give the hand again to your app. do you think  that your app is the only one using those registers ?

:toothy damn... i'm tired now....

EDIT :
halala... i'm more tired than expected... i confuse API, and OS managment... corrections :
-fpu shouldn't be subject to preservation due to his functionnement... but an api can perfectly alterate the content
-SIMD registers are automatically preserved coz they aren't used by OS api, the danger are others api...
-cld/std are redefined following the need of the api...

vanjast, stop digging up those topics for nothing...

old programmer

Quote from: KeepingRealBusy on December 06, 2008, 01:51:55 PM
I return only a status indicating success (Zero) or failure (non-zero).
Sorry for the change of topic --how does one do that here?-- but that does not cover all cases. It is one of Unix s
mistakes that an system operation either succeeds or completely fails. Because of this, Unix never could handle
reel-to-reel tape--nor any in cassetts or cartridges, either. Inasmuch as DOS copies Unix, DOS has the same problem.