The FAQ has an entry about register preservation of Windows API functions. The answer to which registers are preserved says like this:

ebx, esi and edi (well, and ebp, too)

Does this mean that preservation of ebp is less standard than the others, or why is it mentioned separately? Can I always count on ebp being preserved too, even in future Windows versions?

I'm sorry about asking about a FAQ question, but maybe this FAQ reply should be edited to be more clear?

Thanks!
Posted on 2002-12-23 18:56:02 by dELTA
Well the EBP register is used everytime you call a procedure (doesnt
matter if it's api/user proc.). Normally this will always be restored
when the procedure is done. The only time EBP is not preserved is when
the user have done some modifications to it.

So in other words it's always preserved. I tend to use it as a replacement
for '0' when i call api etc. In order to save some bytes.

example: This is what you see when you code.
MyProc proc var:dword


ret
MyProc endp
example: This is the code you dont see. The code you see here is what
happens when you use 'var:dword'. And it changes depending on the number of
arguments, size of arguments, etc.
MyProc proc var:dword

push ebp ;--Save EBP
mov ebp,esp

leave ;--Restore EBP
ret 4 ;
MyProc endp
The ESP reg. contains the value pushed onto the stack before you called the
proc. In other words it contains the value you wanted 'var:dword' to be.
And it moves the ESP into EBP to avoid complications when the stack is
used inside the proc.


Hope this clears it up for you. :alright:
Posted on 2002-12-23 19:25:28 by natas
Thanks for the reply natas!

I think you might have misunderstood my question a little though. :( I know how stackframes work, and how ebp is often used in them, but this is no guarantee that each and every Win32 API function will preserve the ebp register. Some of them might e.g. hypothetically be very small assembly hacks without stackframes, but still using the ebp register, hence having modified it upon return.

My question is if the "Win32 API standard" says that only ebx, edi and esi are always preserved, or if this standard also includes ebp (so that it is not just "almost always" preserved, like a de facto standard, but really guaranteed).

Thanks!
Posted on 2002-12-23 19:45:16 by dELTA
I might have stumbled off the path(a little bit). You say that you
want a guarantee of the preservation concerning EBP. Although
I have never discovered that the EBP was not preserved after an
api call. This might happen if the api/proc. dont preserve the stack
by using ebp, or/and does some modifications to ebp(without preserving)
.

This is windows programming, and I dont believe that they would
code api's that would not preserve the ebp register. Since the
code inside that api would be more open to failure / and more
limited. One api call does usually call more api calls inside it's own
code(and therefore use the stack). All in all the stack is used alot
inside procedures, for many reasons.

I havent read about the preservation of the EBP, and im defintly not
an expert on this topic. So this is just what I think is correct.
Posted on 2002-12-23 20:02:38 by natas
esi, edi, ebx are preserved explicity via push/pop.

But ebp is preserved implicity in prolog/epilog of API.

Some optimizing compilers don't use the ebp, but esp directly, to touch the stack.
In such optimized code, ebp is usually used as zero register. In this case ebp is preserved explicity via push/pop.

Anyway every M$ API designed in above described manner. And every HLL compilers also generate such API.
So, you may be 100% sure about preserving ebp.
Posted on 2002-12-24 02:09:18 by Four-F
HeapAlloc trashes ecx on W2k
Posted on 2002-12-24 03:34:48 by ThoughtCriminal

HeapAlloc trashes ecx on W2k
That's ok, since only EBX,ESI,EDI and EBP get preserved.
EAX,ECX,EDX can be modified.
Posted on 2002-12-24 04:28:05 by Maverick
Ok, thanks for the insight guys!

And a merry (ea)x-mas to all of you! :grin:
Posted on 2002-12-24 05:22:45 by dELTA
wsprintf also thrash ecx
Posted on 2002-12-24 10:44:28 by roticv

wsprintf also thrash ecx


Is there a register to api reference for such things? Or do you just have to play around with it.
This is probably a poor example, but if an API doesnt modify EAX, ECX, and/or EDX then I am
guessing it would be the same as it being preserved? Kinda...

Like so:
I have a variable in ECX
Call API DrawText
Use of ECX here is OK because DrawText did not modify it

I guess I am wondering if anyone knows of a site or something that lists which registers are used
with which APIs... perhaps it is easy to figure out and I just dont know how.

I think it would be useful and produce more efficient code as I am probably preserving registers I
dont need to because I cant tell which ones are really in use at any given moment.
Posted on 2002-12-24 12:00:30 by Graebel
you have the list of preserved registers above. Any other registers may or
may not be trashed, but you must think of them as being trashed. Using ecx
because you found an api doesn't trash it is bloody foolish and dangerous -
you can't depend on the observation to hold true on the next windows version
(or even service pack). Play by the rules.
Posted on 2002-12-24 12:47:36 by f0dder
dELTA,
You can depend on the big four registers surviving a trip to any API, unless the documentation says otherwise. I don't know of any documentation excemption. You must not return changes to the DF, SEG registers, and certain bits of the system registers. And of course, you must return the big four unchanged and the stack must be balanced when returning to the kernel. Ratch
Posted on 2002-12-25 11:41:28 by Ratch
is there any masm directive that I can use to preserve ALL registers in my procedure, instead of writing this



myproc proc uses eax,ebx,edx,ecx,esi,edi,ebp p1:dword, p2:dword
....
myproc endp


this actually push every single register separately which is also unoptimised, since there is pushad instruction that can do this from once
(using pushad manualy inside your procedure will disorder esp and thus parameters on stack will be in not expected place referenced by ebp)
Posted on 2002-12-25 16:22:51 by Mikky

is there any masm directive that I can use to preserve ALL registers in my procedure, instead of writing this



myproc proc uses eax,ebx,edx,ecx,esi,edi,ebp p1:dword, p2:dword
....
myproc endp


this actually push every single register separately which is also unoptimised, since there is pushad instruction that can do this from once
(using pushad manualy inside your procedure will disorder esp and thus parameters on stack will be in not expected place referenced by ebp)

I cant recall any MASM directives wich will preserve all registers inside
a procedure. Why cant you just use them outside the procedure instead.
[color=sienna]pushad

invoke MyProc,addr blah,addr blah
popad[/color]
Why do you need to preserve all registers? If your procedure use all/most registers.
IMHO, I think you should try to optimize the code inside the procedure. Using less
registers, and more of the stack. Ofcourse that depends on what it does.
Posted on 2002-12-25 16:54:33 by natas