Когда прога пишется на асме, удобно делать ebp фрейм, чтобы вместо push [esp+4] push [esp+4+4] push [esp+8+4] писать push [ebp+4] push [ebp+4] push [ebp+4] или даже push [arg1] Но зачем компиляторы ЯВУ делают ebp-фреймы? Им-то несложно отслеживать esp и подставлять необходимое смещение.
GoldFinch 1. esp очень "непостоянный", он очень часто меняется: при передаче параметров функции, при сохранении регистра, при создани временной переменной в стеке, итп... А ebp можно сразу установить каким нужно и без всяких перерасчетов обращаться к локальным переменным и аргументам, переданным в текущую функцию. 2. Сейчас это не актуально, но в Win16, как писал Агнер Фог, прерывание таймера будет менять верхнее слово esp, когда это невозможно преугадать. 3. просто удобней, а затраты на создание стекового фрейма очень незначительные. Это меньшее о чем вы должны беспокоится.
GoldFinch Объяснение этому исключительно историческое: в 16-разрядных процессорах для адресации данных в памяти можно было использовать только регистры BX, BP, SI и DI. Остальные четыре регистра, в том числе SP, использоваться для адресации не могли. В 80386 уже появилась возможность адресоваться по любым регистрам, однако, чтобы её использовать, нужно было существенно переделывать компиляторы ("в лоб" переделать с 16- на 32-разрядный куда проще, чем заставить его использовать все возможности 32-разрядной архитектуры).
Ну вообще-то есть ещё то обстоятельство, что адресация через esp занимает на один байт больше, чем через прочие регистры. В Код (Text): mov eax,[esp+4] mov eax,[ebp+4] первая инструкция занимает 4 байта (8B 44 24 04 - дополнительно включается байт SIB "24"), а вторая - только 3 (8B 45 04). Естественно, при адресации через ebp тратятся дополнительные байты на пролог/эпилог, но если обращений к локальным переменным много, получается выигрыш.
GoldFinch Ф-ции с esp-адресацией неудобны при отладке - стек обратных вызовов после них получается ненадёжным.
diamond Не через прочие, а как раз черех AX, CX, DX и SP или их 32-разрядные версии. А лишний байт возник как раз из-за расширения системы команд; в старом формате, без SIBа, задать эти четыре регистра в качестве компонента адреса было невозможно. В объёме памяти -- безусловно, а вот в скорости -- обычно нет. Скорость выполнения инструкций в современных процах не зависит как таковая от используемой адресации и длины кода команды. Другое дело, что более длинная процедура сожрёт больше кэша, а это может привести к падению производительности, но это уже косвенное влияние, оценить которое очень сложно. green Для компилятора нет проблем с отладкой, это не ручное написание процедуры на асме с ручным же отслеживанием состояния указателя стека.
SII 16-битная и 32-битная адресации отличаются. В 16-битной вообще невозможно адресовать через AX, CX, DX и SP. А в 32-битной все регистры, кроме esp и ebp, эквивалентны, mov edx,[eax] и mov edx,[ebx] занимают по два байта. Это верно, по скорости прямого влияния нет, но есть косвенные - одно за счёт раздувания кэша, а другое за счёт освобождения ebp под другие нужды.
diamond Да. Но регистры в полном смысле эквивалентными в 32-разрядном режиме не являются, что Вы, собственно, и сами раньше сказали, указав, что адресация через ESP требует большего объёма памяти под код команды. Ну а если заняться формированием адреса из нескольких компонентов (пара регистров, отклонение, множитель), то вообще кошмар получается Но возвращаясь к теме, повторю, что главная причина сохранения стековых фреймов -- историческая. Компиляторы были разработаны под неё, поскольку в 16-разрядном режиме иначе нельзя, и это продолжало тянуться, поскольку логику компиляторов существенно не меняли, а лишь дорабатывали. Чисто же технических проблем для отказа от EBP как базы фрейма не было никаких уже в 80386.
push ebp mov ebp,esp mov eax,[ebp] ; eax = ebp предыдущего фрейма (параметры/возврат/локали) mov eax,[eax] ; eax = ebp предпредыдущего фрейма только недавно сталкивался с такой штукой. При компиляции с оптимизацией прога слетала. Использовалось для улучшеного вывода сообщений, от чего отказываться не хотелось. Впрочем и так понятно как это может быть полезно. Есть и другие способы организации стека дающие другие бонусы. (те это не обязательно, а просто удобно иногда) ну и отлаживать безсорцово удобнее гораздо.
это свидетельствует ток об ее неправельности, или отстойности копилятора. Я вон GCC перекомпилил с хардкорными опшенами так ексешко 400кб скинуло(а таг гдет 3метра весил)! Конечно для тесту я заново перекомпилил компилер улутшеным компилером. Как по мне - работает шустрее. К сожалению на попадало все... Там компиль по умолчанию в 3-х регистрах парамы передает. eax, ecx, edx, (то к чему я так привык в кагбе дельфе, да)) Благо на моих несложных прогах оно работает.