Прочитал о проблемах fastcall'a де он совсем не 'fast' и замер в нерешительности. Народ у кого есть дельная информация о сравнительной скорости\проблемах. Какую конвенцию лучше использовать в глубинах своего кода?
Что же это за проблемы такие? Передать два параметра не через стек, а в регистрах eax/edx? Что здесь проблематичного, кроме необходимости помнить, что fastcall, а не stdcall?
Реальная проблема (во всяком случае, из тех, которые мне известны) лишь в том, что fastcall не столь стандартизирован, как cdecl или stdcall - в компиляторах Microsoft и Borland (Watcom тоже, но про него я знаю мало) он реализован по разному: - Microsoft: передача первых двух параметров в регистрах ecx и edx, остальные через стек справа-налево (как cdecl или stdcall); - Borland: передача первых трех параметров в регистрах eax, edx и ecx, остальные через стек _слева-направо_ (как pascal; читал, что Borland впервые ввела этот тип в Delphi). В результате могут возникнуть сложности при использовании библиотек РАЗНЫХ компиляторов. Хотя, fastcall практически не используется для экспорта, так что вероятность нарваться на такое невелика. Ну а об этом можно и не задумываться. ;о) Относительно проблем со скоростью, так это как поглядеть. Вот здесь - http://www.tantalon.com/pete/cppopt/compiler.htm#FastCall - например, утверждается, что в типичных приложениях fastcall на ~2% (! :o)) быстрее cdecl. Можно выиграть в скорости, создавая безфреймовые функции. С другой стороны, вызываемая функция может "испортить" содержимое регистра, следовательно, его требуется где-то сохранять, а это тоже потеря... Так что все зависит от обстоятельств. Дать "глобальный" :о) совет тут невозможно.
В своём коде можно делать как угодно. Это же ассемблер. Вспомним классику: «Параметры можно передавать с помощью одного из шести механизмов: <ul type=disc> <li>по значению; <li>по ссылке; <li>по возвращаемому значению; <li>по результату; <li>по имени; <li>отложенным вычислением. </ul> Параметры можно передавать в одном из пяти мест: <ul type=disc> <li>в регистрах; <li>в глобальных переменных; <li>в стеке; <li>в потоке кода; <li>в блоке параметров. </ul> » Зубков.
SErgey_R > "вызываемая функция может "испортить" содержимое регистра" Регистров мало, поэтому eax,ecx,edx она запортит с вероятностью ~99.9(9)% А вот суммарный выигрыш от fastcall действительно мизерный, т.к. кроме жалких 2-3х push\mov "типичная функция типичного приложения" выполняет массу других полезных и более трудоемких действий
Извините за неточность формулировки. Под fastcall'ом имел в виду передачу параметров в регистрах(любых: ecx,r27,xmm0 или каких там еще) и передачу их в стеке(stdcall/cdecl) Сформулирую вопрос иначе. Я не спрашиваю как работает fastcall Borland/Microsoft etc Я хотел найти инфу о проблемах передачи параметров в регистрах вообще(fastcall) по сравнению с передачей их в стеке(stdcall/cdecl). Прочитал где-то что при вызовах большого уровня вложенности и малых размерах функций издержки fastcall'a превышают stdcall'ные. Фреймовость/безфреймовость тут не при чем. Хотел бы узнать механизм этого явления и сделать выводы для написания собственного кода.
ravenX - ну дык конечно будут издержки в случае fastcall и рекурсии. Т.к. все функции используют фактически одну и ту же область памяти для передачи параметров (регистры), то перед вызовом функции их нужно куда-то сохранять. Соответственно компилятор скорее всего генерирует нечто типа pusha/popa А вообще - что за вопросы. Возьми пару компилеров сделай рекурсивную функцию с fastcall и посмотри сгенерированный код. Кстати. Касательно плюсов и минусов. Использование в ядре 2.6 fastcall, а так же использование при компиляции софта MMX регистров для передачи параметров - дает весьма заметный прирост производительности на linux-системах.
ravenX Разумеется fastcall имеет смысл, когда функция сразу использует данные в регистрах по назначению без необходимости их пушить в стек, а затем заново извлекать. А если в начале функции идет вызов API или чего другого, то регистры приходится все равно пушить\попить, если они еще понадобятся. Поэтому подход должен быть индивидуальным. Fastcall рулит для простых и быстрых функций, которые сразу используют переданные параметры без необходимости их пушить в стек. Если же регистры приходится пушить, или функция имеет большое число параметров, или работает она сравнительно долго, то fastcall ничего хорошего не дает. Еще кстати при fastcall можно оптимально с точки зрения логики функции задавать последовательность передачи параметров (что в какой регистр, что в стек), хоть это может выглядеть и не совсем логично с точки зрения объявления прототипа
2 rst Я сам генерирую кодСл-но брать и тестировать компилеры мне не надо. 2 leo Ммм. До этого можно и своим умом дойти. А на более "фундаментальные" исследования ссылоки не дашь? P.S. ravenX это я(просьба к админам удалить аккаунт тк я пароль посеял)