News:

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

Question about reg preservation.

Started by Rainstorm, March 16, 2006, 02:29:09 AM

Previous topic - Next topic

Rainstorm

Hi.

- have a question abou reg preservation.

in the help file it says,..
QuoteThe registers that must be preserved are EBX ESI and EDI. The remaining 3 are EAX ECX and EDX and they can be freely modified within the procedure that is using them..

then later..
QuoteWhen you call a Windows API function, you can assume that the function will also preserve EBX ESI and EDI but it can also freely modify EAX, ECX and EDX so if you have any values in these registers that must remain the same after the API call has been made, you must also preserve them as well.

1.  what does it mean that 'the function will also preserve EBX ESI and EDI...'
     I have the picture that if the function will preserve them, what's the need for me to
     preserve  them. - could someone elaborate.
     or does that mean after the call is finished their needed values are preserved by windows
      so i can use them freely again

2.  but it can also freely modify EAX, ECX and EDX -  does that mean before a
     windows API call i have to preserve all six ?

thanks

Rainstorm

-


hutch--

Preserve in this context means that the content of the 3 registers mentioned must be the same on exit from the proc as they were on entry to the proc. With code that uses these registers in a procedure, you usually get this type of preservation.


item PROC args etc .....

    push ebx
    push esi
    push edi

  ; write the code here

    pop edi
    pop esi
    pop ebx

    ret

item ENDP


Within a proc written in this manner, you can freely modify EAX ECX and EDX without having to save preserve their values but remember that as soon as you call another proc from within your own proc, it can do the same thing as well.

One of the trick is to use EBX ESI + EDI for variables in your own proc as you know for sure that they will not be modified by another proc that is written correctly.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Rainstorm


asmfan

Steven said it right,
but i'd like to add some facts that every API call assumes that when you call it it will preserve not only the EBX, ESI, EDI, but also EBP and ESP. direction flag must be cleared when you call the API function... that's the truth...
Russia is a weird place

raymond

Rainstorm,

Within your own program, you can do almost anything you want with the registers (even EBP) as long as you know what you are doing. :red

The only detail you MUST remember is to "clean" the stack before your final return to the operating system and avoid modifying the return address if you don't want to reboot your computer.

The register preservation rules should apply to procedures which you may write for future use by other programs.

And there's no need to preserve EAX/ECX/EDX in your program before calling APIs unless you absolutely need the register's content for some other purpose after the API returns (such as a counter for a loop, or a handle returned by another API, etc. etc.).

Raymond
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

Rainstorm


dicky96

Dug up this old thread as it is on topic for what I was gonna ask

This register preservation stuff, what I was wondering is if I use for example edi in my procedure, do I have to restore it to it's entry value before I call a winapi function?

I've been paranoid of causing weird crashes, so when I need to use edi,esi,ebp,ebx what I have been doing is something like......


myproc
...
...
...
push edi
...
...
do some stuff using edi
...
...
pop edi
invoke some api proc
push edi
do some other stuff using edi
pop edi
invoke some other api proc

etc

now I'm wondering if I need to be doing that, or just making sure I push edi before I use it, and pop it before my procedure returns, and not worry about api calls I invoke in between?

Hopefully someone will clarify this for me.   Also if I use "proc uses edi" syntax will it just do this preservation stuff for me?


TIA
dicky



TNick

QuoteAlso if I use "proc uses edi" syntax will it just do this preservation stuff for me?
YES

Here is what I think you should do:
- if anywhere in your proc (not including procs you INVOKE) you use ebx and/or esi and/or edi, use this <proc uses ebx esi edi>
- if not, don't worry about them

- when you INVOKE a proc (yours or a API or ...), you may be shure that what you have in ebx, esi and edii before the call will be the same as what you have in ebx, esi and edi after the call
- when you INVOKE a proc (yours or a API or ...), you may be shure that what you have in eax, ecx, edx before the call will NOT be the same as what you have in eax, ecx, edx after the call

this is all you should know


PS:
what uses ebx - for example - does is to do a push ebx  when you enter the proc and a pop ebx whenever you get out

Nick

dicky96

Thanks that's waht I wanted to hear.   

One thing still confusing me, if My proc (say callback proc) is invoked by windows, then I change change esi or edi for my own use, and then invoke a windows api proc,   why does the api call not crash, seeing as I changed one or more of those registers?

dicky96

Ahh no - hold on, it came to me like an inspiration and big light bulb turned on in my head .......   it's because the api call I invoke (the callee) does not care what is in these registers, but will preserve the contents of these registers for my procedure (the caller) when it returns, just like I must preserve them for whichever bit of windows OS called my proc    :dance:  :dance:  :dance:

Mark Jones

ESI, EDI, and EBX are used by windows and are considered "reserved." In some cases you can use these in your program just fine (without preserving their contents), but execution is not guaranteed and the program might crash for no reason.

Just preserve any of these if you use them, then no strange problems will crop up. You can do that with a procedure defined as "MyProc PROC USES ESI EDI EBX", etc. Or by putting a PUSHAD before your code and POPAD after. Experiment. Open your executable with OllyDbg and press F8 repeatedly... see what is actually going on inside.
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

lingo

Most of the C like Windows examples in assembly use at least two procedures: Main and WndProc(callback proc)
Main proc finished with Message loop usage of GetMessage,TranslateMessage and DispatchMessage APIs

DispatchMessage API transfers control to the CALLBACK procĀ  with address in WNDPROC lpfnWndProc member of the WNDCLASSEX structure (for instance in our case WndProc)
With the address of properly filled WNDCLASSEX structure we registered our main window class with RegisterClassEx API in the beginning of the main proc.

So, when DispatchMessage API transfers control to the WndProc CALLBACK proc
and if we use EBX,ESI,EDI,EBP registers in it we should preserve them because WndProc is a CALLBACK proc.
It is true for all Windows CALLBACK procs ONLY.

In the Main proc we can use EBX,ESI,EDI register WITHOUT preservation
because it is NOT a CALLBACK proc
Example:
....
....

MLoop1: ;
mov ebp, offset msg ; ebp->offset of MSG structure
mov esi, offset GetMessage
mov ebx, offset TranslateMessage
jmp MLoop3 ; start the message loop
MLoop2: ;
mov [esp], ebp ; ebp->offset of MSG structure
call ebx ; ebx->address of TranslateMessage API
mov [esp], ebp ; ebp->offset of MSG structure
call edi ; edi-> address of DispatchMessage API
MLoop3: ;
movd MM7, ebp ; ebp->offset of MSG structure
pxor MM6,MM6 ;
add esp, -6*4 ; room for 6 parameters (for 3 APIs)
movq [esp], MM7 ;
movq [esp+2*4], MM6 ;
call esi ; esi->address of GetMessage API
add eax, 1 ; -1 test (see MSDN)
jne MLoop2 ; if not zero loop again
MLoopExit: ;
...
...
here is final code
before ExitProcess API


We can use EBX,ESI,EDI registers without preservation, if we don't use DispatchMessage API, hence we don't use CALLBACK WndProc too.
In this case our Windows program will be with ONE Main proc ONLY.. but it is other story

Regards,
Lingo