Точнее сказать в спец.буфере процессора - RSB (return stack buffer), он же RAS (return address stack)
Блин, хорошо, плохо... мне вообще всегда было интересно, - почему M$ не сделали вызов системных сервисов через прерывания.......
Y_Mur Не знаю какое кэширование тут рулит (лишняя нагрузка на кэш инструкций), но вот число релоков действительно уменьшается, хотя Quantum почему-то считает, что "это не так" Но думается мне, что использования "санок" в дельфях обусловлено не заботой о скорости загрузки проги или длл, а собственными корыстными интересами Бормана - упрощением своего "супербыстрого" компилятора. Можно копнуть дальше. Например, в дельфях если объявить импорт одной и той же функции в разных модулях, то компилер не утруждает себя излишним анализом и создает отдельные санки для каждого объявления. Еще более вопиющий пример "антиоптимизации" - создание двойных ссылок на глобальные переменные, объявленые в другом модуле. Если переменная объявлена в Unit1, то все ссылки на нее в этом модуле идут напрямую, а для других модулей эта переменная является внешней - на нее в .data заводится теневая переменная=константа, в которую пишется адрес настоящей переменной, и обращения из других модулей идут через mov eax,[XXX] + mov eax,[eax]. Число релоков при таком подходе не уменьшается и обращения становятся медленнее - минимум 3 такта на лишнее чтение + проблема AGI на атлонах (это вам не jmp, которому нужно прочитать фиксированный адрес прыжка да и то один раз, а затем рулит предсказание и реальные потери составляют 1-2 такта). А пофиг - Борману так удобнее и плевал он с высоты VCL на нашу оптимизацию, к тому же и мануалы учат избегать злоупотреблений глобальными переменными - кто знает, тот избегает, а другим и так сойдет
Y_Mur Разработчики ПО делают как: 1. Если их разработка работает и через 10 лет, то они ее не меняют, если это не критично для рынка! А теперь вспомни когда создавалась Delphi ? ЭТо же не вчера или позавчера! Это черт знает когда начали разрабатывать, вероятно тогда о технике: call dword[addr_api] наверное и не знали, а если и знали то наверное уже был готовый кусок для компиллера, который переписывать означает от срочка выхода релиза, а это потеря бабок! Но как всегда, это очередное мнение. Замечу в статье Мэтта Питрека про PE формат, было описано что в 1.0 версии компиллер делал только call - > jmp dword[addr_api] и только потом добавили возможность техники call dword[addr_api]
leo Имелось в виду, что при подготовке запуска проги когда в релоках сидят адреса call, разбросанных по всему файлу то имеем случайный доступ, а когда они в jmp и все рядом..... то только сейчас (пока писал) дошло, что здесь не чтение, а запись и это не важно )) Значит немного выиграть можно только в размере таблицы релоков (за счёт разницы в количествах jmp и call) Собственно завёл тему потому что всегда лечил МАСМ от jmp на call, но когда тоже самое увидел в дельфёвой проге немного усомнился - "раз и там так делают - может это хоть зачем-нибудь нужно" ) Quantum Наконец дошло, что я исправляю call на jmp по другому... (ЗЫ: чёт я торможу в этом топике ) Вопрос 2: Ага ещё и этот эффект кроме лишнего перехода Удивляет, что дзенный Fasm рекомендует приветствовать мир (т.е. начинать знакомство с программированием), именно с этого кривого приёма ((
leo Ну, стормозил Quantum... В той статье под фиксапами, если я правильно понял, подразумевалось заполнение lookup-таблиц в импорте загрузчиком, а не релоки по коду. Число этих фиксапов (ячеек в таблицах) не уменьшается, а релоков - да.
Есть такое. Написали, видимо, для простоты и наглядности. А вот реализация строк подкачала, опять же, из-за простоты макроса.
Y_Mur Не совсем так: если ты будешь использовать формат MS COFF, то линкер соберёт все кусочки .data в один. А для PE есть пример реализации "сборки строк" в макросах S_T_A_S_'a.
Y_Mur Да нет и при обычной (write-back) записи кэширование тоже важно, поэтому правильнее сказать так: использование jmp уменьшает число релоков, и как следствие 1) умешьшает размер таблицы релоков и 2) сокращает время загрузки dll при изменении ImageBase за счет уменьшения числа записей и улучшения условий их кэширования (хотя при наличии других релоков основное время уйдет на обработку отказов страниц или еще хуже на copy-on-write Ну а минус - лишняя пара тиков на вызов функции в "нормальных условиях" или десяток-другой при первом вызове или кэш-промахах
leo Спасибо за подробные разьяснения. IceStudent Спасибо учту, но всё же жаль, что это не штатная возможность Fasm
Fasm'e есть хорошие макросы iglobal/uglobal. Они позволяют собирать вместе все инициализированные данные и вместе все неинициализированные данные. Потом, правда, нужно в секции .data написать IncludeIGlobals, а в секции .bss IncludeUGlobals. Найти эти макросы можно, например, в файле kglobals.inc в исходниках KolibriOS (kolibrios.org), где он взят по-моему из Fresh (но там он еще не адаптирован под новый fasm).