4

Reading a program's disassembly, I've noticed a pattern. When setting up a function's frame, the instruction enter is rarely used. I also used compiler explorer with the latest GCC -- GCC does not use enter but uses leave.

Why isn't the instuction enter used? Why do compilers use two or more instructions to preform an action that can be done in one instruction? (pushing rbp, saving rsp, and allocating on the stack using sub rsp, rather than using enter 0x20, 0). But leave is used... is there something else that leave does that I'm not aware of? As far as I know, leave is equivalent to

mov ebp, esp
pop ebp

GCC uses leave whereas MSVC does not. I don't understand why enter is never used and leave is sometimes used.

Arush Agarampur
  • 1,340
  • 7
  • 20
  • 1
    tl;dr: One instruction instead of two doesn't always mean faster. – Joseph Sible-Reinstate Monica Jul 12 '20 at 05:39
  • Yeah that's good, thanks. – Arush Agarampur Jul 12 '20 at 05:41
  • The problem is not what `leave` does, it's what `enter` does. `enter` is *insane*, it was supposed to give assembly support for nested stack frames in block structured high-level languages. Because the general form of `enter` *cannot* be made fast by a modern processor, even the *less insane* version that only reserves stack space for the current stack frame has been neglected by processor implementers. If you look at Agner Fog's instruction tables, you see `enter a, 0` ~3-4x slower than `push; mov; sub`, and `enter a,b` effectively taking an eternity. – EOF Jul 12 '20 at 05:42
  • Also, modern compilers can usually avoid using frame pointers (because modern debug and unwind tables make frame pointers redundant), so frame pointers are mostly a relic of the past, particularly on register starved architectures like x86(_64), where an extra register for the compiler's register allocator is *very* valuable. – EOF Jul 12 '20 at 05:46
  • Oh? I still have two questions. If we don't use `enter`, why is `leave` sometimes used? Also, where can I learn more about unwind tables? (Like examples) @EOF – Arush Agarampur Jul 12 '20 at 05:53
  • `leave` is *much simpler*, it really is only `mov; pop`. Compilers use `leave` under the following conditions: 1) The function uses variable-legth arrays, `alloca()`, the target ABI *requires* a frame pointer or the programmer explicitly requests that the compiler produce worse code by using a frame pointer AND 2) The code density advantage (a single instruction with a single-byte opcode versus multiple instructions, one of which takes multiple bytes to encode) outweighs the execution speed disadvantage (which is pretty small). – EOF Jul 12 '20 at 06:43
  • If you want to learn about debug info and unwind tables, you need to ask somebody else, because I have no idea how they actually work. You might find something useful by searching for `dwarf debug info`. – EOF Jul 12 '20 at 06:46
  • Thanks man, especially for that explanation on `leave` @EOF – Arush Agarampur Jul 12 '20 at 07:43

1 Answers1

3

Why are the instructions ENTER and LEAVE not used by compilers?

These instructions have been used in the i286 and i386 era, so before 1999.

Today, these machine instructions are generally slower than simpler equivalents. Compiler writers do know that, so avoid emitting these machine instructions.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547