Комментарии 29
Но чтобы эти данные как-то изменить, их в начале необходимо загрузить в регистры.Вообще говоря это неверно для архитектуры x86. Есть команды (методы адресации) которые делают RMW или W напрямую с памятью. К примеру INC mem или MOV/ADD mem, imm
В доисторической рускоязычной литературе для обозначения регистров часто использовалась аббревиатура СОЗУ (сверхоперативное ЗУ). По сути регистры — это специального вида память, которая адресуется именами регистров (во многих современных архитектурах не мудрствуют и просто называют их r0, r1,… rN). Можно, для накала, рассматривать регистры как кэш управляемый вручную.
На x86 можно написать аналог любой программы, которая использует регистры без использования оных (а вот на load-store архитектуре — не выйдет). Да, ценой быстродействия. Собстно регистровая адресация это всего-лишь способ устранения ботлнека с памятью и ничего более.
Это я к тому, что данные загружаются в регистры не «так или иначе», а для устранения проблем быстродействия связанных с доступом к памяти (как и прозрачные кэши любого уровня).
Ну или точнее, как она их ожидает получить? Через стек?
ideone.com/uSmc8Y
Однако функция с переменным числом параметров похоже тоже забирает что-то из регистров.
А что происходит дальше — навскидку пока непонятно.
godbolt.org/g/HkqX5r
Кстати, ` reinterpret_cast(accumulateFunction);` является UB:
The effect of calling a function through a pointer to a function type that is not the same as the type used in the definition of the function is undefined.
Если посмотреть на ассемблер, то видно, что регистр `al` не очищается при вызове через указатель, то приводит, собственно, к UB.
Иначе не получится в цикле считывать неизвестное количество аргументов. Если они все на стеке, то можно просто читать [rsp, rsp+sizeof(arg))
.
Та функция, которая с фиксированным набором параметров мне кажется то же самое делает.
Вот если бы статья была озаглавлена "особенности вызова функций в clang (или даже llvm)" — я бы понял. А вы тут просто в одну кучу свалили всё — С++, ассемблер (кстати, зачем какие-то левые сайты, есть же директива -S у фронтенда, чтоб сразу получить ассемблер, как в gcc, не? У вас получилась статья на тему llvm abi для архитектуры x86_64. Думаю, к С++ или другому языку она имеет весьма опосредованное отношение (и не удивлюсь, если какой-нибудь скрипт js/lua после jit (если таковой есть через llvm) не будет ничем отличаться).
В целом выглядит эпично, но мне кажется такие вещи было бы гораздо познавательнее выразить через анализ ОТКРЫТЫХ исходников того же clang, чем через reverse-engineering скомпилированного кода (опять же, в свете того, что даже этот шаг можно было бы сразу вывести в формате asm, минуя ненужный дизассемблинг; ещё бы пиратскую IDA тут заюзали для наглядности...). Что подсказывает, что в этих самых исходниках ещё и камменты есть на тему что и почему...
Лично я не знаю, что там использует какой-то сайт (да, честно говоря, и знать это особо незачем, видя результат). И "левый" он как раз по причине, что он тут совершенно лишнее звено. ОСОБЕННО если, как вы говорите, он всего лишь запускает где-то там у себя gcc/clang с ключиком -S.
Все, нужные лично мне для работы. Нынче во время время докеров и быстрого интернета это минутная задача.
А gcc/clang это уже левые софтины? Ну здрассть…
Сборки под centos/rhel6/7, под long-term debian/ubuntu есть, плюс макось — а остальное неинтересно.
Особенности вызова функций в С++