View Full Version : Register preservation?
-h
19th January 2003, 05:27
I've been wondering for a while now, which registers should be preserved by function calls? Until now I've thought you could do whatever you liked to eax/ecx/edx, but ebx/esi/edi/ebp all had to be push'ed and pop'ed for the sake of the calling routine.
I just realised I've never read anything concerning the subject and did this out of habit. I'm wondering if anyone knows exactly what I should be preserving, and whether there are differences between platforms/compilers.
-h
trbarry
19th January 2003, 18:52
At least in VS6 I think you are allowed to trash eax, ebx, ecx, edx, esi, edi, and the mmx regs & float regs. Just preserve esp, ebp (?), and the segment regs. And use emms to not leave the float regs in an undefined state where they can't even be zeroed.
If you are compiling with the Fastcall option then you also have to preserve ecx.
But I'm doing this from memory and for all I know could have been doing it wrong for years. ;)
- Tom
mpucoder
19th January 2003, 19:07
Yes, you definately must restore ebp. It is used for referencing the actual parameter area (invocation record). Stack segment and data segment registers should be restored, but the extra (es, fs, and gs) need not be. The code segment will be restored by the ret.
ENTER and LEAVE will handle esp and ebp for you.
Some languages have further restrictions, such as Fortran (I know, who uses that, but it's an example I can remember atm) requires EDI and ESI to be preserved.
trbarry
19th January 2003, 19:56
While we are on this, does anyone know of any (commonly used) projects that do use the Fastcall option in Visual Studio?
I typically do not and so probably have not always kept ecx intact. But I wonder if there are any out there to watch out for.
- Tom
vlad59
19th January 2003, 21:12
[Thinking deeply]
IIRC Dvd2avi is using __fastcall for each IDCT code
[/Thinking deeply]
alexnoe
19th January 2003, 21:42
eax, ecx, edx (not ebx!) are considered "general registers", and you can trash them. But trashing any other register could cause side effects.
trbarry
20th January 2003, 01:20
alexnoe -
I'm not aware of anything special about ebx except sometimes it is confused with ebp. What's it used for and why does it have to be kept intact?
IIRC Dvd2avi is using __fastcall for each IDCT code
Vlad -
I didn't know that. I don't remember if I kept ecx intact in my version of DVD2AVI. That might account for some of the strange optimization related bugs that happen with excessive inlining.
- Tom
-h
21st January 2003, 07:31
I guess the must-push-ebp-esp-esi-edi mantra came from experience with gcc-compatible code, as gcc requires those registers to be preserved (http://www.delorie.com/djgpp/doc/ug/asm/calling.html).
Indeed for inline assembly, VC6 only needs ebp and esp to be preserved (http://msdn.microsoft.com/library/en-us/vccore98/HTML/_core_using_and_preserving_registers_in_inline_assembly.asp). However, I've not been able to find anything concrete, but seeing as most core win32 functions preserve ebp, ebx, esi and edi (http://www.eskimo.com/~htak/win32asm/winxlate.htm) I guess it's good form to do the same when not using inline assembly. It's a tad disappointing that there's nothing I can find in VC's documentation saying "if you jump to an arbitrary piece of linked code, VC expects these registers to be preserved upon returning."
Ah well.
-h
alexnoe
21st January 2003, 09:39
EBX is sometimes used as index, as in
[esi+4*ebx], and I know that the Delphi compiler
requires ebx to be restored.
I don't know if VC6 requires it to be restored,
but if you encounter strange effects, then try
restoring it...
Steady
23rd January 2003, 04:02
I tend to write 'hybrid' code, where the variables and initialization is done in C++, and the heavy processing is done in _asm{}; blocks. My experience is - never touch esp (interrupts can happen at any time). EBP is used to access local variables(don't use it unless you are really desperate for a register). If you have a lot of local variables (I think more than about 256 bytes worth, not counting passed arguments) then EBX becomes a secondary local variable pointer. (If ebx is used this way, I get a warning from the compiler if I change it).
trbarry
23rd January 2003, 16:52
If you have a lot of local variables (I think more than about 256 bytes worth, not counting passed arguments) then EBX becomes a secondary local variable pointer. (If ebx is used this way, I get a warning from the compiler if I change it).
Yikes!
I thought all that stuff went away with 16 bit mode. I can't imagine why they would need a 2nd pointer into local data in 32 bit mode. But I've never seen the message, so I guess I won't worry about it.
- Tom
Prettz
1st February 2003, 21:57
VC++ 6.0's MSDN documentation says you *should* always preserve everything but eax and edx. edx is generally used by the compiler for the most temporary of temp variable. C++ member functions obviously must restore ecx before restoring because the compiler always assumes the 'this' pointer is there when a member function returns. VC++ usually uses ebx for "important" pointers if it doesn't have a better use for it.
Keep in mind that VC++ 6.0 automatically detects what registers you use and which ones you backup, both for inlined asm code and all-asm __declspec(naked) functions. Compiled code around your asm code will only backup registers itself if your asm code doesn't preserve them.
I'm still unsure about when you do/don't need to use ebp as the stack frame pointer. Unless a function (and every function it calls) is declared with throw(), the compiler forces this, even if you tell it to suppress using stack frames. I think if, in addition to being declared nothrow, your function doesn't declare any local C++ objects, you're safe using ebp. But even then that might not be a good idea unless you can further guarantee that no hardware exceptions will be thrown before you restore its value.
edit: I forgot to say that if your function doesn't use a stack frame and you don't use ebp yourself, you DON'T have to back it up; it's enough if you leave it pointing to the caller's stack frame.
edit2: heh, I got a little carried away there. I just thought I would recite everything I know in case some interested newbies happened by who didn't have the resources to find this stuff out on their own.
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.