Registers are a precious resource and the windows OS makes use of most of them. However, sometimes it would be convenient to have another register (apart from ebp) that you can count on API functions preserving AND is not "hands off" from your app's perspective.

Heres an example scenario in Pseudo-asm:

//////////////////////////////////////////

enter WNDCLASS_size, 0

%define wc ebp-WNDCLASS_size

;wc expands to ebp - 40

lea edx,

GetMessage edx,...etc

/////////////////////////////////////////

Now since I can't count on edx being preserved on the other side of the GetMessage call,
I have to do further leas:

///////////////////////////////////////

lea edx,

TranslateMessage edx

lea edx,

DispatchMessageA, edx

///////////////////////////////////////

That is an example of the situation. Windows preserves ebp, but wc is defined relative to ebp
so I can't touch it. I know that Windows also preserves the segment registers but I don't think I can store anything in them without crashing my App. Many have predefined uses (eg FS for exceptions).

What I can do besides storing the effective address in memory or doing
successive leas? Is there at least one other register that I can store temporary data in and assume it won't be modifed until I explicitly change it?

Thanks in advance for your comments.

I am a little hazy on windows' use of the some of the general purpose registers.

BTW, I did check all the popular sources (Iczelion's tutorials etc.)
Posted on 2002-09-17 11:05:32 by Thanatos
ebx ?
Posted on 2002-09-17 11:09:15 by JimmyClif
I didn't know if I was required to preserve ebx as well, before calling an API function.
That would be kind of silly but most of the time windows preserves registers for totally selfish reasons.

Bah...I was just confused, plain and simple...heh.
Thanks for that unambiguous response. (minus the '?') :)
Posted on 2002-09-17 11:35:20 by Thanatos
lol... np :)
Posted on 2002-09-17 11:42:13 by JimmyClif
ALL windows API calls preserve ebx, esi, and edi for you.
Posted on 2002-09-17 12:22:00 by Qweerdy
Qweerdy is right.

If you need another register use EDI or ESI, they are there for that.
Posted on 2002-09-17 13:04:17 by slop
In the particular example you posted, I would consider using globals instead of locals. That way, you don't need to calculate the effective address and disturb a variable. For example, I always code my WNDCLASSEX and MSG structures as globals.


Of course, there are always cases where you want a register preserved over an API call, but careful programming can sometimes eliminate these situations. For those times where you can't there's ebx, esi, edi


--Chorus
Posted on 2002-09-17 14:07:51 by chorus
Thanks all.

And yes chorus. The example was a bit contrived. Its easier to make the WNDCLASS and MSG structues global.
Posted on 2002-09-17 22:24:29 by Thanatos
Just making sure ;)

BTW, you could also do some creative pushing to avoid the extra lea, since your going to have to push it later anyways:



lea eax,msg
push eax
push eax
call TranslateMessage
call DispatchMessage


or pushing/popping the value temporarily is pretty cheap


lea eax,msg
push eax
invoke DispatchMessage,eax
pop eax
invoke GetMessage,eax,NULL,NULL,NULL


--Chorus
Posted on 2002-09-17 23:31:33 by chorus
I could go for a FAQ on registers that would comprise those that:

    [*]are perserved by the Win32 API, those that
    [*]must be perserved by my App
    [*]are fair game for my App
    [*]are trashed by the Win32 API
Posted on 2002-09-18 01:29:45 by eet_1024
registers that are preserved by the Win32 API
esi, edi, ebx, ebp, esp
ebp and esp are preserved in prolog of API:
push ebp
mov ebp, esp
sub esp, xx
. . .

and restored in epilog of API:
. . .
mov esp, ebp
pop ebp
ret xx

or
. . .
leave
ret xx

If API is going to alter esi, edi or ebx it is responsible for preserving the value of these registers.
eax, ecx, edx are used by API (if needed) without preservation.

registers that must be preserved by my App
esi, edi, ebx, ebp, esp

registers that are fair game for my App
eax, ecx, edx without preservation.
And any other (except segment regs) with preservation.

registers that are trashed by the Win32 API
It depends on particular API, on parameters passed to API and many other reasons. But anyway, you should not expect that eax, ecx, edx and flags will be the same after API return. If API returns result (most of API do it), it's returned in the eax register (for 32-bit values), or the edx:eax registers (for 64-bit values). eax is most often used inside the API.

And of course you should play with esp by the rule.
And you must not change segment registers.
Posted on 2002-09-18 09:42:03 by Four-F
Four-F-, I have used ebx without preservation and I haven't run into any problems.
It seems to me that windows preserves ebx and MyApp doesn't have to.

THAT is the kind of register I am looking for.
However, According to your synopsis there is NO such register. The API will trash ecx, edx and eax and while it will preserve the value of ebx, I have to do so also. My (albeit limited) experiments say that isn't the case. My application has crashed from not preserving ebx.

Basically, I am looking for a register that windows preserves and I don't have to preserve. Ebx seems to be one such register...yes?
Posted on 2002-09-18 14:32:54 by Thanatos
I'm hearing all kinds of answers on this.
Personnally I would think that the "USES" clause would handle all of this
but what do I know.

Maybe a tut by EOIN would be in order.
Posted on 2002-09-18 16:58:15 by shankle
Yeah, it is very unclear stuff. Microsoft doesn't seem to document this.
Posted on 2002-09-18 17:15:55 by Thanatos
There is only one answer to register preservation in 32 bit windows coding and that is to use the Windows convention that Four-F has described in detail. Write API code any other way and it will be unreliable and subject to crashes on different versions of Windows.

To avoid some of the folklore surrounding this area, any procedure you write that uses EBX ESI EDI !!!!!!! MUST !!!!!!!! preserve them but can modify EAX ECX EDX.

If your procedure calls an API function, you need to remember that that API function can modify EAX ECX EDX as well so if you cannot select EBX ESI EDI for things like counters etc ... preserve them first before calling the API function.

Don't be fooled into thinking there is a simpler or easier way, vary from this Windows convention and risk your code crashing on different windows versions.

There are exceptions in nested procedures that do NOT call API functions and in this instance, you must design your own to work if you do it this way.

Regards,

hutch@movsd.com
Posted on 2002-09-18 18:51:23 by hutch--
Thanks,

Sounds reasonable (if unfavourable from the application progarmmer's perspective). I was hoping that if windows preserved ebx I could modify it without care. Apparently that's not the case.

Here's one thread I'm saving for future reference :)
Posted on 2002-09-18 22:05:25 by Thanatos
So I have to preserve all registars needed by my app after an API call AND I must restore esi, edi, ebx, ebp, esp
before an API call or exiting.

I think that it be more correct to not molest ebp and esp since the all mighty processor manages stackframes with them.
Posted on 2002-09-19 00:47:19 by eet_1024

Thanks,

Sounds reasonable (if unfavourable from the application progarmmer's perspective). I was hoping that if windows preserved ebx I could modify it without care. Apparently that's not the case.

Here's one thread I'm saving for future reference :)


You have got it all backwards.

All Win API functions preserves the value YOU placed in ebx, esi and edi BEFORE you called the API. In the same way, you must preserve the values that windows api placed in ebx, esi and edi when it called WndProc or any other callback in your app.

In other words, if you use ebx, esi or edi in any procedure, you should place 'uses ebx esi edi' in the proc declaration like this:

stuff PROC uses ebx esi edi thing:DWORD
mov ebx, thing
imul ebx, ebx
mov esi, ebx
imul esi, esi
mov edi, esi
imul edi, edi
mov eax, edi
stuff ENDP

Of course, you don't have to place for example 'esi' after 'uses' if you don't use esi in your proc. What MASM does when you put 'uses ebx esi edi' in the proc is equivalent of writing:

stuff PROC thing:DWORD

push ebx
push esi
push edi

mov ebx, thing
imul ebx, ebx
mov esi, ebx
imul esi, esi
mov edi, esi
imul edi, edi
mov eax, edi

pop edi
pop esi
pop ebx

stuff ENDP


All Win API functions also pushes and pops ebx, esi and/or edi if it uses them.
Posted on 2002-09-19 01:07:53 by gliptic
...called WndProc...


Opps, still in console App mode.
Posted on 2002-09-19 02:05:03 by eet_1024
Yeah, that's pretty much the understanding I got gliptic. Basically, your functions should treat ebx, esi and edi just like they treat ebp.
Posted on 2002-09-19 09:58:09 by Thanatos