Чтобы завершить тему: как это реализуется. На сам деле - до тупого просто. Состоит из двух частей (дальнейшее изложение идет на примере x86 - у остальных птичек тоже самое): Первая - как вообще реализуются вложенные функции/процедуры: как большинство помнит при входе в функцию обычно оформляется так называемый stack frame - парой команд: push %ebp mov %esp, %ebp В результате мы получаем в %ebp ссылу на начало стекового фрейма текущей функции, причем по адресу [%ebp] лежит ссылка на аналогичный фрейм вызывающей функции. Получается список фреймов, провязанный в цепочку. Это так называемая "динамическая цепочка вызовов". Она очень полезна для отладчика, но увы - не годится для доступа к переменным статического окружения данной функции. На деле нам нужна прошивка не по динамической вложенности вызовов, а по статической вложенности функций - тн "статическая цепочка". Дальше возможны варианты - если мы забиваем на отладчика (или вытаскиваем в нем стек вызовов как-то иначе, опираясь на отладчную информацию - для отладчика скорость тут не слишком важна) - самое простое - перед вызовом подсунуть в %ebp ссылку на нужный фрейм. Это несложно сделать - в подавляющем большинстве случаев он и так совпадает с %ebp, в остальных если у нас прошивка идет по статической цепочке - просто надо отсчитать сколько надо (определяется текстуальной вложенностью функций) фреймов вверх по статической цепочке. Cохранять базу как правило (за исключением случаев когда стек может действительно динамически расти - как при использовании с-шной функции alloca ) не надо - обычно мы знаем ее смещение от %esp и потом можно просто загрузить правильное значение Ну собственно турбопаскаль и прочие так примерно и делали. Часть вторая - это все хорошо пока мы вызываем процедуру которую знаем. Но что если мы имеем дело с процедурным параметром или переменной? А очень просто - в этом случае процедурное значение представляется не одним словом - а парой - соственно адресом точки входа и "базой" - то есть тем значением, которое надо поместить в %ebp перед вызовом. Собственно все. Легко видеть, что в отсутствие использования процедурных значений оверхед от поддержки отсутствует полностью, в случае формирования процедурного значения - некоторый есть конечно - но небольшой. В качестве вбоквела - таким образом кстати можно представлять и "ссылку на метод" - не в смысле С++ - а в смысле что вот у нас есть экземпляр объекта и мы из него выбираем метод и хотим это превратить в процедурное значение - ну тоже самое только базой тут будет адрес объекта (при условии что соглашения о вызове под это подточены). На сам деле объект вполне можно рассматривать как стек фрейм функции "пустившийся в свободное плавание" - оставшийся после выполнения кода процедуры (АКА конструктора) - в Симуле-67 это было отражено буквально даже на уровне синтаксиса: Class Rectangle (Width, Height); Real Width, Height; ! Class with two parameters; Begin Real Area, Perimeter; ! Attributes; Procedure Update; ! Methods (Can be Virtual); Begin Area := Width * Height; Perimeter := 2*(Width + Height) End of Update; Boolean Procedure IsSquare; IsSquare := Width=Height; Update; ! Life of rectangle started at creation; OutText("Rectangle created: "); OutFix(Width,2,6); OutFix(Height,2,6); OutImage End of Rectangle; Легко заметить что от описания процедуры отличается только тем, что вместо слова Procedure используется слово Class Ну вот собственно и почти все - еще будет мелкий бонус про GNU C :)