LINUX.ORG.RU

Что имеется ввиду под "заголовком функции" (кто-то из нас тормозит, может быть даже я).

anonymous
()
Ответ на: комментарий от anonymous

при вызове функции ее параметры помещаются в стек. кроме этих параметров туда еще что-то кладется. вот и хочу выяснить, что и сколько это кушает

anonymous
()

В коде функции в стек всегда сначала кладется четырехбайтовй %ebp, чтобы
запомнить, где был указатель стека для последующего избавления от локальных переменных функции, которые, при их наличии, кладутся следом за %ebp. Не знаю, как дело обстоит при оптимизации, но обычно эта схема верна даже когда локальных переменных и вообще операций со стеком в функции нет.

JekLove
()

при врубленой оптимизации и параметры и локальные переменные могут держаться в регистрах, про %ebp --- info gcc на предмет -fomit-frame-pointer итд.

anonymous
()

Зависит от архитектуры. В случае x86:

В стек кладутся аргументы (в обратном порядке) и адрес возврата (неявно, командой call).

Параметры могут передаваться в регистрах, если у функции __attribute__((regparm(n))).

Что касается сохранения ebp, то это делает ВЫЗЫВАЕМАЯ функция, если не -fomit-frame-pointer. Это нужно для отладки, позволяет делать call-trace.

А вообще-то у gcc есть ключик -S.

idle ★★★★★
()

Блин, мазафака. Уже не первый день пытаюсь отправить, но LOR как раз в это время падает. Может быть сейчас пройдет:


>при вызове функции ее параметры помещаются в стек. кроме этих параметров туда еще
> что-то кладется. вот и хочу выяснить, что и сколько это кушает

А-а.. Теперь уже яснее.
В стек пихаются параметры в обратном порядке, чтобы была возможность иметь переменное их число.
Т.е. для функции int func (int a, int b) параметры будут:
адрес возврата [esp+0], 4 байта.
int a в [esp+4] или [ebp+8], если в заголовке ebp пихается в стек.
int b в [esp+8] или [ebp+12]

>В коде функции в стек всегда сначала кладется четырехбайтовй %ebp, чтобы
>запомнить, где был указатель стека для последующего избавления от локальных
>переменных функции, которые, при их наличии, кладутся следом за %ebp.

Верно. А я еще и умное название скажу: frame pointer :-)
Но так же верно, что если нет локальных переменных, то и ebp в стек пихать не обязательно. Например, в strlen() и регистров хватит.

> Не знаю, как дело обстоит при оптимизации, но обычно эта схема верна даже когда
>локальных переменных и вообще операций со стеком в функции нет.

Да. GCC так делает, пока ему не сказать -fomit-frame-pointer, после этого он избыточные push/pop убирает. Оптимизация, мать ее.


2автор сообщения (дополнительно):

Вообще все очень просто. Пишешь к-либо функцию, затем говоришь
gcc -S файл.c (добавь -mintel-syntax, если не нравится AT&T синтаксис, но только в gcc>3.0 вроде)
или
icl /FAs файл.c (если есть интелевый компилер).
и изучаешь исходник - где чего и как вызывается и что при этом в стек кладется.

anonymous
()

Можно поинтересоваться - а нафига знать сколько занимает заголовок?

Писать код, закладываясь на такого рода информацию - моветон, и
вообще получается абсолютно непереносимый код.

Кроме того, каждый компилятор использует свои методы оптимизации, даже разные версии одного компилятора - то есть наверняка сказать никогда нельзя сколько займёт заголовок. Кроме того, функция вообще может быть объявлена inline, и там совсем всё иначе.

Ну разве что из чистого интереса - тогда понимаю...

Dimentiy ★★
()
Ответ на: комментарий от Dimentiy

2Dimentiy: решал, как функцию делать - рекурсивную или итерационную. соответственно, хотелось узнать, в какие расходы памяти выльется рекурсия, потому как итерационная версия оказалась несколько медленней.

2Олл: спасибо за исчерпывающие ответы и за наводки, где копать

anonymous
()

> Писать код, закладываясь на такого рода информацию - моветон, и
> вообще получается абсолютно непереносимый код.

Золотые слова, типа.

> Кроме того, каждый компилятор использует свои методы оптимизации,
> даже разные версии одного компилятора - то есть наверняка сказать
> никогда нельзя сколько займёт заголовок.

Ну, зря ты так. По крайней мере все мне известные x86/32-компилеры (i386: gcc, watcom, symantec, borland, intel, ms, lcc, вроде никого не забыл) генерируют совместимый код, если, конечно, им не сказать передавать параметры в регистрах (тогда только сами с собой), это соглашения такие. И ассемблерная процедура, написанная под intel для винды так же будет работать и в gcc freebsd (nasm rulez).
Так же, dll, откомпилированная в mingw цепляется в MSVC (если только она не сиплюсовая). При условии, что написано это все правильно, разумеется.

> Кроме того, функция вообще может быть объявлена inline, и там совсем всё иначе.

Если функция объявлена inline, это еще ничего не значит. Это говорит только о том, что ее код _может быть_ будет скопирован в вызывающую функцию, но при этом она останется обычной функцией, ее можно будет вызвать из другого модуля.
Рекурсивные, к примеру, функции не могут быть заинлайнены, если только не сводятся к хвостовой рекурсии (AFAIR, без вариантов).
Если функция оптимизируется настолько, что нарушает соглашения, то для нее создается еще один вариант (пример - leaf-функция, где есть соблазн заменить call-ret на jmp(туда)-jmp(обратно), или функция, вызываемая с константой в качестве параметра - "function cloning").
Конечно, если компилер умеет так оптимизировать.

Обычные же трансформации пролог/эпилог не трогают.

anonymous
()

Имейте в виду, что на стеке может оказаться больше, чем frame. Вот
еще одно умное слово - register spilling (как это по-русски?): если
не хватает регистров, промежуточные результаты кладутся на стек.
Это уже совершенно непредсказуемо, так как зависит от логики в run
time.

anonymous
()

> Имейте в виду, что на стеке может оказаться больше, чем frame. Вот
> еще одно умное слово - register spilling (как это по-русски?): если
> не хватает регистров, промежуточные результаты кладутся на стек.
> Это уже совершенно непредсказуемо, так как зависит от логики в run
time.


Про register spilling: AFAIK run-time тут и рядом не валялся, все предопределяется на этапе генерации кода, так как то, что регистров не будет хватать известно заранее (кол-во регистров константа, не так ли?)

А насчет русских эквивалентов: про "register spilling" мне тоже интересно, и еще кто бы
сказал, как перевести "leaf procedure" на русский (не по смыслу, а как термин).

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.