Thanks fodder for the reply. I think you gave me more than I asked for, so I am not sure that I followed the answer. My fault, not yours.

Outside of procedures, can I use ebx, esi, and edi as I wish, without any attempt at preserving them?

I understand that if I call something of the API (or any other procedure for that matter) the registers eax, ecx, edx may be changed. That's OK by me, and I can deal with it. What I need is what does Windows require outside of procedures?

I am not concerned with the flags or segment registers in this question.

Posted on 2003-04-28 03:49:54 by bushpilot
"Outside procedures", there's not much windows requires - the thing you'd be most likely to bump your head on would be unaligned stack, and that is not very common.

As long as you handle register preservation in your callbacks, you're free to do anything you want inbetween. Whether you _should_ do that or not is another question :alright:
Posted on 2003-04-28 03:53:11 by f0dder

Just take note of the old convention as it is wider than just callback procedures. I posted in a dump of a standard Wndproc that shows the basis of how its done, if you modify any of the registers that are defined by convention, you must preserve them and in the dump, it shows ESP and EBP preserved in the normal manner.

If you want to add code of your own in a WndProc that used EBX ESI or EDI, you must protect them in the same manner.

Once you have these registers protected somewhere down a tree of function calls, if you want to be creative and write procedures without a stack frame or use EBP as a normal register, it all can be done as long as you understand what is going on.

Any API function you call will automatically preserve EBX ESI & EDI in the normal register but will often change EAX ECX EDX according to the convention.

There is a very sensible logic in the convention, particularly when you are writing code the is multiple levels of function calls deep. ESP & EBP are normally used for entry and exit of procedures and with the 6 registers left, 3 are preserved and three are free to be modified.

If you observe the convention and protect EBX ESI EDI, you can use those registers in that procedure for things like counters or any other value that you want to be retained between other procedure calls or API calls as long as the procedures above it observe the same convention.

The convention works by a normal condition, if you are going to change it, preserve it first and restore it later. Once you have this done, you can write anything you like. I use a compiler that in fact uses registers in a different way once the normal stuff is done and the advantage is in terms of speed when registers can be used freely in the code design.

What you must make sure of if you take this approach is how you interact with the operating system under those conditions as the OS does use this covention.

A callback is no more than an address that you instruct the OS to send information to. In a normal WinMain, you place that address in the WNDCLASSEX structure. With other callback procedures you must also supply the address for the OS as well.

What the OS does is call that address with the correct number of memory operands on the stack and there are no registers involved except the stack pointer which tells the procedure where the parameters are.

Under this condition, ther is no way a register can be modified unless you write code that does modify it so the convention hold in that if you modify the register, you must preserve it and restore it at the end of the procedure.

What is important here is that a callback procedure is a subset of all procedures and it needs to be treated in the same manner as any other as the convention applies to all procedures, not just callbacks. Where you change it is after you have observed the convention and as long as you don't them interact with the OS without observing the same convention.

Posted on 2003-04-28 06:54:06 by hutch--
Humm, as far as I can see, there isn't really anything in the last post of Hutches that disagrees with what I or Thomas have stated - so what's all the bickering about? :) (phrasing is different though)
Posted on 2003-04-28 10:18:06 by f0dder
Increase post count? :grin:
Posted on 2003-04-28 10:25:26 by roticv
So... somebody explain the unaligned stack thing to me. What's the big deal?
Posted on 2003-04-28 10:31:27 by iblis
I don't really know why it's a problem (perhaps some optimization somewhere of some weird kind - I think it's a fair assumption anyway, since non-4byte aligned stack iirc gives performance penalty). Basically, try sub'ing 2 from ESP and doing a MessageBox. Especially on NT. That will show that there _is_ a problem.

Other aligned stuff might show up at certain structures, or when using stuff like performance counters. Again, dunno _why_ this is a problem, but I don't care much - you should keep your stuff aligned to at least 4 anyway. Microsoft didn't bother documenting this (all modern C/C++ compilers I know of for 32bit envionrments does at least 4byte alignment), and they're focusing on C programmers since that's the probably tge largest programmer base. (outside of visual basic :grin: )
Posted on 2003-04-28 10:36:44 by f0dder
Yes, I think esp have to be aligned to dword because of

Accessing 64-bit variables that are not 8-byte aligned costs an extra three cycles on the
Pentium processor. When such a variable crosses a 32-byte cache line boundary it can cause
a DCU split in Pentium Pro and Pentium II processors. Some commercial compilers do not
align doubles on 8-byte boundaries. If, by using the Misaligned Accesses performance
counter, you discover your data is not aligned, the following methods may be used to align
your data: (from intel's IntelArchitectureOptimizationManual)

Hmmm well, Microsoft does mention stack alignment but of course it is more focus for the C programmers as there is a bigger pool of them. :)
Posted on 2003-04-28 10:50:26 by roticv