Hi there,

I am confused as to which registers need to be saved at the start of an asm function.

In particular, if an assembly function is being called from C++, one typically doesn't know which registers currently contain valid data at the time of the call given that the allocation is left up to the C++ compiler.

In this case, why isn't it necessary to save all the registers?


Posted on 2002-04-22 20:15:17 by Station
The calling convention under win32 is to preserve ebx,edx,esi,edi,ebp
across function calls - which mean you are free to trash eax,ecx,edx.
Any proc you call have the same liberties.
Posted on 2002-04-22 20:29:26 by f0dder

The operating system rules are preserve EBX ESI and EDI if they are going to be used in a procedure and restore them on exit. EBP and ESP are usually reserved for procedure entry and exit.

What you will find with different compilers is that with internal functions, they do not observe this rule as they often do not call any operating system functions.

As long as you stick with using either STDCALL or C calling conventions, you should not have any problems with the operating system defined rules but unless you have very specific information on the particular compiler you are using, don't use FASTCALL as the calling convention is not published.

I think from memory that it uses EAX ECX and EDX to pass parameters which reduces the stack overhead but unless you know exactly what the compiler is doing, you could end up in trouble.


Posted on 2002-04-22 20:34:23 by hutch--
If you are using MASM, use the USES macro in your functions. That way, MASM PUSHes the registers you nominated, and restores them when it encounters a RET instruction. That means if you have 6 different ways to leave a specific function, MASM will expand your code to include the register restores at each one of those exit points, this saves you a lot of work and possible bugs.
Posted on 2002-04-22 21:03:36 by sluggy
Or if you're really really really lazy, PUSHAD in the beginning of your proc and then POPAD at the end. ;)
Posted on 2002-04-22 21:38:05 by iblis
I started doing Win32Asm before I learned the STDCALL standard properly. I accidentally used esi and edi once (using them as indices - old habits die hard) without saving them and crashed! Then I remembered the time I did mixed-language programming, I remembered C calls required si and di saved, so I saved esi and edi! It worked!

Funny thing is, I kept using ebx WITHOUT saving it. My Win95 system doesn't crash. My Win98 system doesn't crash either. My classmates' systems don't crash. What gives??
Posted on 2002-04-23 19:08:49 by AmkG

Funny thing is, I kept using ebx WITHOUT saving it. My Win95 system doesn't crash. My Win98 system doesn't crash either. My classmates' systems don't crash. What gives??

luck! or, you aren't writing a DLL, so you don't need to return ebx "unharmed"
Posted on 2002-04-23 20:17:55 by jademtech
Well, thing is... just like your progs might not require the use of all
registers, some windows API functions might not require the use
of all registers. 9x is also a lot more forgiving about not preserving
registers (but you better get used to it, or you will get some very
weird and hard-to-debug errors later on). Also know that you don't
have to preserve registers from program start to program end - ie,
you don't have to save/restore ebx,esi,edi,<blah> before and after
each API call (but know that APIs can trash them whenever they
want to, and just because your windows doesn't, doesn't mean
that all windows wont).

The only place you really have to do register preservation is

*) if you require one of the you-must-save registers to remain the
same after an API call.

*) in a callback (wndproc/dlgproc, hooks, WNDENUMPROC, et cetera).

If you want to, you can go register trashing as crazy as you like
in your own procs, as long as you keep in mind you're doing it.
Posted on 2002-04-23 20:52:54 by f0dder
Hi there,

I'm afraid that I'm not getting something important here.

I have this ASM function which is being called from a C++ Windows program. When I first ran the whole program, as soon as it started, it quit. I was able to avoid this behaviour by removing a single command. The command was ' mov ebp, esi '.

I'd pushed ebp at the start of the ASM function and popped it right at the end.

So, do I have more responsibilities than simply making sure that some registers are the same at the end of the function as they were at the start?

Is it not actually possible to use some registers anywhere within a Windows program?

If this is indeed the case, then why is it so?


Posted on 2002-04-25 11:44:31 by Station
ebp is used to reference your parameters and your local variables.

So if your proc uses parameters OR local variables... I'm sorry you can't use ebp that way! Otherwise it would trash on the first instrtuction that needed a local var or parameter.
Posted on 2002-04-25 18:03:50 by AmkG