I downloaded MemGraph by John A Lyons. It generated GPF in a second. Looked in the source, found callback WndProc ebx edi esi were not preserved, put uses edi esi ebx - all done. No GPF anymore. People, I understand that it's very amusing to paint your windows in different colors or make your buttons barking. But I beg you - spend a little time to understand WHY such "ebx edi esi" rule exist! Stop treating it as "black box rule"! It's very simple - procs that called from your code and returned to your code may do anything with regesters and not preserving them it WILL NOT generates GPF, the only bad thing that may happend is that you expect some regs to have the same value and rely on it but value was spoiled, it can make you apps run wrong but it's your apps problem not system problem. CALLBACK PROCS ARE THE OTHER CASE!!!!!!! It's not you it's SYSTEM who call them and respectively they RETURNED to SYSTEM CODE. And the system code relies on previous value of edi esi ebx! So if you put in callback WndProc proc uses edi esi ebx ......... and here you mess with value of edi esi ebx or you call some stdproc wich don't preserve the value WndProc endp Nothing wrong will happen to system cause it still will have the value of ebx edi esi upon return from callback proc that it was before the call. The only problem that might happen if you expect some value and some proc you called will change it: mov edi,hSomeHandle call SomeProcWichChangeEDI invoke OtherProc,edi ; the OtherProc may fail 'case of SomeProcWichChangeEDI BUT if you forget to preseve registers before callback proc and restore them after - any changed edi esi ebx in any part of callback proc or other proc wich called by it will lead to GPF. It's very important and not so hard to understand. The Svin.
I totally agree :)
I agree with this general drift as the convention for preserving registers serves a useful function. You could write an operating system that used PUSHAD/POPAD before and after every function call but it would be slower and you could not easily pass values in registers. The convention is to preserve EBX, ESI & EDI if they are used at all in your own proc but you can freely use EAX, ECX and EDX. This leaves you with an interesting problem, if you use a register like ECX as a counter and call another function that uses ECX for something else, your counter value gets trashed so you have to keep in mind when calling other procedures. What is happening is that the procedure that is called preserves EBX, ESI & EDI but uses ECX in its own code. The general rule is if your code uses EBX, ESI or EDI, preserve them and be aware that other procedure calls do the same thing. This in particular applies to operating system code including API calls. Windows works on this convention so if you want you code to be robust, you will observe it yourself. I personally do the pushes and pops manually as I prefer code to assembler notation but if you bother to do so, it will reflect in more reliable code. Regards, email@example.com
You guys just saved me another day of hair-pulling! "uses edi esi ebx" It was that simple... Xtreme