enter is much more complex than leave, it don't just push ebp/mov ebp, esp:
Quote
temp_RBP = RSP // This value of RSP will eventually be loaded // into RBP. IF (temp_LEVEL>0) // Push "temp_LEVEL" parameters to the stack. { ENTER_START: temp_ALLOC_SPACE = word-sized immediate specified in the instruction (first operand), zero-extended to 64 bits temp_LEVEL = byte-sized immediate specified in the instruction (second operand), zero-extended to 64 bits temp_LEVEL = temp_LEVEL AND 0x1f // only keep 5 bits of level count PUSH.v old_RBP FOR (I=1; I<temp_LEVEL; I++) // All but one of the parameters are copied // from higher up on the stack. { temp_DATA = READ_MEM.v [SS:old_RBP-I*V] PUSH.v temp_DATA } PUSH.v temp_RBP // The last parameter is the offset of the old // value of RSP on the stack. } RSP.s = RSP - temp_ALLOC_SPACE // Leave "temp_ALLOC_SPACE" free bytes on // the stack WRITE_MEM.v [SS:RSP.s] = temp_unused // ENTER finishes with a memory write // check on the final stack pointer, // but no write actually occurs. RBP.v = temp_RBP EXIT
I never needed the second parameter, and i guess most of you neither, but it exists and the processor must intepret it,
Both leave and pop generates 2 uops, but pop can't be used alone to exit a stack frame.
Yes, the second parameter is for nested procedures - almost no language supports them (not even Java IIRC) I think ML and Haskell might, but I'm rusty on those languages.