Pull to refresh

Comments 29

Но чтобы эти данные как-то изменить, их в начале необходимо загрузить в регистры.
Вообще говоря это неверно для архитектуры x86. Есть команды (методы адресации) которые делают RMW или W напрямую с памятью. К примеру INC mem или MOV/ADD mem, imm
Ага, изменил формулировку. Я имел ввиду, что обычно нельзя изменить данные вообще не используя регистры. Тот же ADD не работает для двух memory операндов.
Да я, это, собсно, так, побуквоедствовать.
В доисторической рускоязычной литературе для обозначения регистров часто использовалась аббревиатура СОЗУ (сверхоперативное ЗУ). По сути регистры — это специального вида память, которая адресуется именами регистров (во многих современных архитектурах не мудрствуют и просто называют их r0, r1,… rN). Можно, для накала, рассматривать регистры как кэш управляемый вручную.
На x86 можно написать аналог любой программы, которая использует регистры без использования оных (а вот на load-store архитектуре — не выйдет). Да, ценой быстродействия. Собстно регистровая адресация это всего-лишь способ устранения ботлнека с памятью и ничего более.
Это я к тому, что данные загружаются в регистры не «так или иначе», а для устранения проблем быстродействия связанных с доступом к памяти (как и прозрачные кэши любого уровня).
А как передаются параметры в функцию с переменным числом аргументов?
Ну или точнее, как она их ожидает получить? Через стек?

ideone.com/uSmc8Y
Смотрю в main вызовы обеих функций абсолютно идентичны. Что, в общем-то, не удивительно: они вызываются через один и тот же указатель.
Однако функция с переменным числом параметров похоже тоже забирает что-то из регистров.
А что происходит дальше — навскидку пока непонятно.
godbolt.org/g/HkqX5r
На 20 странице pdf описываются особенности при переменном числе аргументов. Суть в том, что в регистре `al` передаётся число используемых xmm регистров. Остальное то же самое. Внутри метода абсолютно все регистры, в которых могут быть аргументы, копируются на стек, после чего читаются из него по смещению.

Кстати, ` 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)).

Та функция, которая с фиксированным набором параметров мне кажется то же самое делает.

Если скомпилировать с оптимизацией (хотя бы -O1), то не делает:


accumulate3Function(int, int, int):
  add edi, esi
  lea eax, [rdi+rdx]
  ret

GCC, кстати, хитрый. Если в функции не вызывается va_arg(args, double);, то он даже не проверяет регистр al.

Да, но зачем в такой схеме вообще регистры?

Судя по всему, когда xmm регистров ещё не было, или в других ABI, va_arg функции были совместимы с обычными. То есть, можно было их вызывать через указатель на обычную функцию, или делать объявления с фиксированным количеством аргументов. Потом появился SSE и это стало UB.

Вот если бы статья была озаглавлена "особенности вызова функций в clang (или даже llvm)" — я бы понял. А вы тут просто в одну кучу свалили всё — С++, ассемблер (кстати, зачем какие-то левые сайты, есть же директива -S у фронтенда, чтоб сразу получить ассемблер, как в gcc, не? У вас получилась статья на тему llvm abi для архитектуры x86_64. Думаю, к С++ или другому языку она имеет весьма опосредованное отношение (и не удивлюсь, если какой-нибудь скрипт js/lua после jit (если таковой есть через llvm) не будет ничем отличаться).


В целом выглядит эпично, но мне кажется такие вещи было бы гораздо познавательнее выразить через анализ ОТКРЫТЫХ исходников того же clang, чем через reverse-engineering скомпилированного кода (опять же, в свете того, что даже этот шаг можно было бы сразу вывести в формате asm, минуя ненужный дизассемблинг; ещё бы пиратскую IDA тут заюзали для наглядности...). Что подсказывает, что в этих самых исходниках ещё и камменты есть на тему что и почему...

Да, возможно надо было более явно указать для какой конфигурации проводился обзор. С другой стороны, для других x86_64 компиляторов выводы будут примерно такие же. ABI и стандарт С++ накладывают ограничения.
В windows ABI отличается.
UFO just landed and posted this here
Ага, добавил про gcc. Clang, как я заметил, испытывает некоторые трудности с оптимизацией хитрых манипуляций с регистрами.
А где вы тут видите дизассемблинг? Насколько я знаю, используемый автором godbolt.org как раз ключ -S и использует. Кстати, почему вы называете его «левым сайтом»?

Лично я не знаю, что там использует какой-то сайт (да, честно говоря, и знать это особо незачем, видя результат). И "левый" он как раз по причине, что он тут совершенно лишнее звено. ОСОБЕННО если, как вы говорите, он всего лишь запускает где-то там у себя gcc/clang с ключиком -S.

Все, нужные лично мне для работы. Нынче во время время докеров и быстрого интернета это минутная задача.

То есть вы вместо официальных репозиториев используете какие-то левые софтины и непонятное хранилище образов? :-)

А gcc/clang это уже левые софтины? Ну здрассть…
Сборки под centos/rhel6/7, под long-term debian/ubuntu есть, плюс макось — а остальное неинтересно.

Нет, «левой софтиной» я в шутку назвал докер. По крайней мере, два года назад он точно попадал в эту категорию.
UFO just landed and posted this here
Спасибо за интересную статью, но один момент очень режет глаза. Скажите пожалуйста, в чём смысл делать оглавление и названия разделов на английском? Тут, конечно, большинство его понимает, но от этого возникает ощущение неряшливого перевода, брошенного почти в конце.
Изначально была идея сохранить терминологию. Хотя сейчас, после множества изменений текста, она уже не особенно актуальна.
Спасибо за труд, впечатляет, очень полезно.
Спасибо за статью, полезно посмотреть что и как, у самого руки не так часто доходят:) В дополнение к статье добавлю свеженькое видео от Jason Turner на схожую тему — Negative Cost Structs
Sign up to leave a comment.

Articles