6

The common calling conventions for IA-32 say:

• Callee-save registers
%ebx, %esi, %edi, %ebp, %esp
Callee must not change these.  (Or restore the caller's values before returning.)

• Caller-save registers
%eax, %edx, %ecx, condition flags
Caller saves these if it wants to preserve them.  Callee can freely clobber.

Why does this strange convention exist? Why not save all the registers before calling another function? Or have the callee save and restore everything with pusha/popa?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Bruce
  • 33,927
  • 76
  • 174
  • 262
  • 2
    Which part is 'non-intuitive'? The specific choices about which registers should be callee vs. caller save, or the fact that there are differentiated callee and caller save registers? – Gian Dec 01 '11 at 02:07

4 Answers4

10

Why would you want to write code to save registers in every function that you might not need? That would add extra code and extra memory writes to every single function call. It may not seem significant now, but back in the 80's when this convention was created it probably did matter.

And note that ia-32 doesn't have a fixed calling convention - what you list is only an external convention - ia-32 doesn't enforce it. If you're writing your own code you use the registers however you wish.

Also see the discussion History of Calling Conventions at the Old New Thing Blog.

When deciding which registers should be preserved by a calling convention, you need to balance the needs of the caller against the needs of the callee. The caller would prefer that all registers be preserved, since that removes the need for the caller to worry about saving/restoring the value across a call. The callee would prefer that no registers be preserved, since that removes the need to save the value on entry and restore it on exit.

If you require too few registers to be preserved, then callers become filled with register save/restore code. But if you require too many registers to be preserved, then callees become obligated to save and restore registers that the caller might not have really cared about. This is particularly important for leaf functions (functions that do not call any other functions).

shf301
  • 31,086
  • 2
  • 52
  • 86
  • I would love to know if this answer applies equally well to functional code with lots of tail calls. My thinking is caller-preserve-all and no need to preserve anything in case of tail call. – Rich Remer Jul 17 '14 at 19:22
  • @RichRemer: Does functional code tend to not have many **non-tail** calls? Those still benefit from some call-preserved registers. And it doesn't defeat the tail-call optimization of jumping instead of call/ret: Just restore the callee-saved registers before jumping to the tailcalled function. On entry to the function you jumped to, the callee-saved registers will have the values they should have when it eventually returns. You're right that if most calls are tail-calls, saving/restoring registers in each function is mostly wasted work. – Peter Cordes Feb 06 '16 at 03:05
5

A guess:

If the caller saves all registers it will still need after a function call, it wastes time when the called function doesn't modify all those registers.

If the callee saves all registers it changes, it wastes time when the caller didn't need the values in those registers again.

When some registers are saved by caller and some by callee, the compiler (or assembly programmer) can choose which kind to use depending on if the value is needed after the next function call.

Baffe Boyois
  • 2,120
  • 15
  • 15
  • 1
    This is correct. Note that sometimes callers only need to restore, because the value in a reg was already in memory, and they were just caching it in a register. Having maybe one more call-clobbered regs might lead to better code, at least for modern compilers that inline very small functions. (The ABI was designed way before modern compilers, unfortunately.) OTOH, many library functions are small, but don't get inlined. Save/restore code is needed at every call site, and many functions have multiple callers, so having the save/restore code once in the callee is a win. – Peter Cordes Feb 06 '16 at 03:42
5

If you look a little deeper into the registers used, you can see why they won't be preserved by the callee:

  • EAX: used for function returns, so quite obviously it cannot be preserved.
  • EDX:EAX: used for 64bit function returns, same as EAX.
  • ECX: this is the count register, and back in the older days of x86 when LOOPcc was 'cool', this register would be thrashed like mad, even today there are still quite a few instructions using ECX as a counter (like REP prefixed instructions). However, thanks to the advent of __thiscall and __fastcall, it gets used to pass args in, which means its very likely to change, so there is almost not point in preserving it.
  • ESP: this is a little side exception, as its not really preserved, its altered in accordance with stack changes. Though it can be preserved to prevent stack pointer corruption/security or unbalancing thanks to inline assembly (via stack frames).

Now it actually becomes intuitive :)

Necrolis
  • 25,836
  • 3
  • 63
  • 101
  • Why must the callee preserve %ebx, %esi, %edi? Is there an intuitive explanation for that? – Bruce Dec 01 '11 at 09:53
  • @Bruce: so that it can be called by anything, ie: the caller need not know anything about the internals of the callee, as the callers data will be preserved (`ESI` & `EDI` are the data src/dest registers, so this keeps in line with separating the caller data from the callee). – Necrolis Dec 01 '11 at 10:59
  • 1
    Since those are your base and offset registers, they are used in looping over strings, etc. Likely, these are callee preserved so that calls can be made inside these loops without having to push/pop them every time. – rich remer Jul 07 '14 at 02:25
-1

In short, caller save are because of argument passing. Everything else is callee save.

Brian Knoblauch
  • 20,639
  • 15
  • 57
  • 92
  • This is not correct. Even pure stack-args calling conventions like the SysV convention used by 32bit Linux treat eax, ecx, and edx as call-clobbered. edx:eax is used to return 64bit integers, but ecx is a scratch register because it's useful to have a decent number of regs. Having one or two more call-clobbered regs that can freely be used as scratch registers would probably lead to better code, though, at least for modern compilers that inline very small functions. (The ABI was designed way before modern compilers, unfortunately.) – Peter Cordes Feb 06 '16 at 03:34
  • Actually, even with inlining, a lot of code still makes function calls from inside loops with a lot of "live" state, so probably only three scratch regs is a good choice for 32bit x86 to reduce spills/reloads in the caller. `push` and `pop` are cheap and small (one byte each). But this answer is still wrong >. – Peter Cordes May 31 '16 at 18:53