Those familiar with x86 assembly programming are very used to the typical function prologue / epilogue:
push ebp ; Save old frame pointer.
mov ebp, esp ; Point frame pointer to top-of-stack.
sub esp, [size of local variables]
...
mov esp, ebp ; Restore frame pointer and remove stack space for locals.
pop ebp
ret
This same sequence of code can also be implemented with the ENTER
and LEAVE
instructions:
enter [size of local variables], 0
...
leave
ret
The ENTER
instruction's second operand is the nesting level, which allows multiple parent frames to be accessed from the called function.
This is not used in C because there are no nested functions; local variables have only the scope of the function they're declared in. This construct does not exist (although sometimes I wish it did):
void func_a(void)
{
int a1 = 7;
void func_b(void)
{
printf("a1 = %d\n", a1); /* a1 inherited from func_a() */
}
func_b();
}
Python however does have nested functions which behave this way:
def func_a():
a1 = 7
def func_b():
print 'a1 = %d' % a1 # a1 inherited from func_a()
func_b()
Of course Python code isn't translated directly to x86 machine code, and thus would be unable (unlikely?) to take advantage of this instruction.
Are there any languages which compile to x86 and provide nested functions? Are there compilers which will emit an ENTER
instruction with a nonzero second operand?
Intel invested a nonzero amount of time/money into that nesting level operand, and basically I'm just curious if anyone uses it :-)
References:
grep
-inggcc-4.8.2/gcc/config/i386/i386.c:10339
that GCC simply never emitsENTER
at all nowadays. And the comment at that line is quite clear:/* Note: AT&T enter does NOT have reversed args. Enter is probably slower on all targets. Also sdb doesn't like it. */
– Iwillnotexist Idonotexistgit log -p
on their cvs->svn->git converted repository shows that it already existed in the initial check-in in 1992. – user743382llvm/lib/Target/X86/X86FrameLowering.cpp:355
a comment for theemitPrologue()
method which reads in part; Spill general-purpose registers [for all callee-saved GPRs] pushq %<reg> [if not needs FP] .cfi_def_cfa_offset (offset from RETADDR) .seh_pushreg %<reg>
. There are no mentions ofENTER
, only pushes; And the enum constant for x86ENTER
occurs only 3 times in all of LLVM; It doesn't even look as though they have testcases for it. – Iwillnotexist Idonotexist