* http://jdebp.info./FGA/metaware-iterator-driven-for.html
In theory, the extra frame pointer mechanisms of the ENTER and LEAVE instructions in the Intel ISA were there for supporting this kind of nested function. MetaWare High C/C++ did not use them, preferring to use a variant calling convention where (if I recall correctly) ECX contained the extra hidden parameter.
ENTER copies M words from the caller's stack frame. The pointer passed by MetaWare High C/C++ in the register could equally well have been placed at the relevant position in the caller's stack frame, just as other arguments are, and an ENTER N,1 used as part of the perilogue.
The only consideration here is speed of the ENTER instruction versus having the hidden pointer in a register, not that this sort of nested function implementation is somehow impossible with ENTER. It's just another case of ENTER is slow and other instructions do the same thing better.
* http://jdebp.info./FGA/function-perilogues.html#Standardx86
(Part of that consideration is making non-nested functions usable via full function pointers.)
The environment is a struct containing what is captured; so for example, it would contain an &T if your closure captures a T by reference. You don’t need to walk a set of stack pointers to find it, just follow the reference directly there.
If it is the enclosing function, it's just a single pointer to it. The "walking" comes from if you're accessing the enclosing function's enclosing function's frame.
This is achieved by adding a hidden parameter that is a pointer to the enclosing function's stack frame. This forms a threaded list so variables in nested enclosing functions can be accessed by walking that list.
This is the same way Pascal does it.
It also means that taking the address of a nested function produces a pair - a pointer to the function, and this hidden parameter to the enclosing stack frame.