Почему RAX не используется для передачи параметра в System V AMD64 ABI? - PullRequest
0 голосов
/ 09 октября 2018

Я не понимаю, какая польза от передачи параметра в RAX, поскольку возвращаемое значение в RAX, в любом случае, будет вызвано вызываемым объектом.

Может кто-нибудь объяснить?

1 Ответ

0 голосов
/ 09 октября 2018

x86-64 Система V использует использование AL для функций с переменным числом: вызывающий передает число аргументов FP в регистрах XMM.

(Это толькооптимизация, позволяющая вызываемому объекту не сбрасывать все векторные регистры в массив; разрешается, чтобы число в AL превышало количество аргументов FP. На практике код ggen для функций variadic просто проверяет, является ли оно ненулевым, ивыводит либо none, либо все 8 из xmm0..7. Я думаю, что ABI гарантирует, что безопасно всегда передавать al=8, даже если на самом деле нет никаких аргументов FP, и что вы не можете передавать аргументы FP в стеке.вместо этого, установив al=0)


Но почему бы не использовать r9b для этого и использовать RAX для 6-го аргумента?Или RAX для некоторого более раннего аргумента?

Поскольку RAX имеет так много неявных применений в x86 , и эксперименты при разработке соглашения о вызовах (http://web.archive.org/web/20140414124645/http://www.x86-64.org/pipermail/discuss/2000-November/001257.html) обнаружили, что использование RAX обычно требуетдополнительные инструкции в вызывающем или вызываемом объекте, например, потому что RAX часто требовался как часть вычисления других аргументов в вызывающем объекте, или был необходим при выполнении чего-либо с одним из других аргументов, прежде чем код сможет использовать аргумент, переданный в RAX.

RAX используется для rep stos (который gcc использовал более агрессивно для встроенного memset) и для div и расширения (с одним операндом) mul / imul, чтоgcc использует для деления на константу времени компиляции. ( Почему GCC использует умножение на странное число при реализации целочисленного деления? ).

Большинство других специальных применений RAX просто корочекодировки вещей, которые вы также можете делать с другими регистрами, например cdqe против movsxd rax, eax (или между любыми другими регистрами) или add eax,imm32 (без ModRM) против add r/m32, imm32 (или большинстводругие инструкции ALU).Смотрите один из моих ответов на Советы по игре в гольф в машинном коде x86 / x64 .В оригинальном 8086 отсутствовали многие более длинные альтернативы без AX, но между 8086 и 386 были добавлены такие вещи, как imul r32,r32 и movsx / movzx.Другие инструкции только для RAX не стоит использовать при оптимизации скорости (например, xlatb, lodsd) или устарели из-за расширений P6 / AMD64 (lahf, поскольку часть FP сравнивает устаревшие fucomi и использует SSE/ SSE2 ucomisd для математики FP), или являются специализированными инструкциями, такими как cmpxchg или cpuid, которые слишком редки, чтобы оказать влияние на разработку соглашения о вызовах.В любом случае, компиляторы не использовали инструкции BCD, такие как aaa, а AMD64 удалила их.


Разработчики соглашения о вызовах System V для x86-64 (в первую очередь Ян Хубичка для целочисленного регистра передачи аргументов arg)дизайн), как правило, направлен на то, чтобы избежать регистров со многими / распространенными неявными применениями.rdx предшествует rcx в порядке прохождения аргументов, потому что cl требуется для переменного числа сдвигов (без BMI2).Возможно, они встречаются чаще, чем mul и div, поскольку 2-операнд imul reg,reg допускает нормальное умножение без расширения без дробления RDX: RAX.

На выбор rdi и rsi в качествепервые 2 аргумента были, по-видимому, мотивированы включением memset или memcpy как rep movs (что gcc сделал в 2000 году, хотя на самом деле это не был хороший выбор во многих случаях, когда gcc делал это).Несмотря на то, что rep -строковые инструкции используют RCX в качестве счетчика, они все же нашли в среднем сохраненные инструкции для передачи 3-го аргумента в RDX вместо RCX, поэтому соглашение о вызовах не вполне работает, чтобы memcpy было rep stosb / ret.

Ян Хубичка (Jan Hubička) оценил многочисленные варианты регистров передачи аргументов путем компиляции SpecInt с текущей версией x86-64 gcc.См. Мой ответ по Почему Windows64 использует соглашение о вызовах, отличное от всех других операционных систем на x86-64? , чтобы узнать больше подробностей и ссылок.

Один из вычисленных им порядков регистра arg былRAX, RDX, RCX, RBX, RSI, RDI, но он нашел это менее удачным, чем другие варианты.(См. Сообщение в списке рассылки, указанное выше).


Соглашения о вызовах RISC довольно часто передают первый аргумент в первый регистр возвращаемого значения.ARM делает это (r0), и я думаю, что делает PowerPC.Другие (например, MIPS) этого не делают.Но во всех этих архитектурах нет неявного использования большинства целочисленных регистров, часто это просто регистр ссылок и, возможно, указатель стека.

x86-64 SysV и Windows делают это для аргументов FP: xmm0 для передачи и возврата.

...