2

An x86 assembler routine typically begins with the following prologue:

push        ebp                ; Save ebp
mov         ebp, esp           ; Set stack frame pointer
sub         esp, localbytes    ; Allocate space for locals
push        <registers>        ; Save registers

I have seen functions push anywhere from 1 to 4 registers.

Besides pushing ebp, which is required, what determines whether you push edi, esi, and/or ebx as well?

Should you always push them? I can't find a reference to settle this issue for me.

matmul
  • 589
  • 5
  • 16
  • 2
    Although there is an x86 ABI and a 64 bit ABI, (use your favorite search enging) which tells of volatile and non-volatile registers and calling conventions; you are under no obligation to save any registers. Although, f you are going to interact with the OS or another library, then you must abide by the ABI for that OS. You are using Assembly, you have total control! – Gunner Jun 13 '14 at 04:12
  • 1
    Some compilers (such as Microsoft) have a no frame pointer option, which frees up EBP to be used for other purposes. It would still needed to be saved (if used) though. – rcgldr Jun 13 '14 at 04:41
  • " what determines whether you push.." your use determines which ones you want or need to push. You push those you modify, and want their original values back after you're done with them. – Deleted User Jun 13 '14 at 07:06
  • @Gunner: Agreed - the ABI is what counts here and that will tell you what you can change. But by "you are under no obligation to save any registers" I assume you mean "unless you play with them" :-) – carveone Jun 13 '14 at 11:29

3 Answers3

3

There's no point in pushing registers you don't modify. Beyond that it's your choice of which registers you preserve. Adopt some convention so that both the calling code and the called code knows what it's responsible for.

  • If you do push registers that you dont modify, and then restore them, is there any harm? other than extra work, will it cause a crash? – matmul Jun 13 '14 at 17:29
  • Pushing registers consumes time and stack space. It won't, of itself, cause a crash, but it will use system resources that might result in one if they're exhausted. In a PC environment where neither stack nor execution time are particularly tightly limited this probably isn't too important. In an environment with tight constraints (such as an embedded microcontroller) things might be different. –  Jun 13 '14 at 20:54
  • > Beyond that it's your choice of which registers you preserve. No it isn't. The ABI says which registers you have to preserve. If you modify (for instance) ESI without preserving/restoring it then functions that call you may crash because they expect the contents of ESI to be untouched by the functions that they call. If you own both sides of the function call (caller and callee) then you can preserve whatever registers you want, but redefining the ABI should be very rare. – Bruce Dawson Aug 26 '15 at 21:55
1

You're seeing caller vs callee save registers. The basic idea is that if you want to store a value in a callee-saved register, you need to save its current value somewhere so that you can restore it at the end of your function call.

Community
  • 1
  • 1
Patrick Collins
  • 10,306
  • 5
  • 30
  • 69
1

This Wikipedia section might help: http://en.wikipedia.org/wiki/X86_calling_conventions#Register_preservation

Generally speaking you preserve every registers except the ones you are specifically told you do not have to preserve. If in 32 bit code and being called, you don't have to preserve EAX, ECX or EDX, but you do have to preserve everything else. In 64 bit code there are more registers so you have to preserve them too.

In your example, you have to push EBP because you change it. It's quite common when writing assembly to use EBP to index your parameters. The parameters are pushed onto the stack, then the return address. So to get to your parameters you have to access the stack. If ESP is changing it's a massive pain to remember where your parameters are relative to ESP. So we save a "bookmark" using EBP.

But if you don't need to do this, then don't! For example - the __fastcall calling convention as used by Microsoft, would pass the first parameter in ECX. I have simple code that never pushes anything to the stack and just uses EAX and ECX.

carveone
  • 889
  • 9
  • 16