Вибір чотирьох регістрів аргументів на x64 - загальний для UN * X / Win64
Однією з речей, про які слід пам’ятати про x86, є те, що ім’я регістру для кодування «reg reg number» не очевидно; з точки зору кодування інструкцій ( байт MOD R / M , див. http://www.c-jump.com/CIS77/CPU/x86/X77_0060_mod_reg_r_m_byte.htm ), регістрові номери 0 ... 7 знаходяться - у такому порядку - ?AX
, ?CX
, ?DX
, ?BX
, ?SP
, ?BP
, ?SI
, ?DI
.
Отже, вибір A / C / D (рег. 0..2) для значення повернення, і перші два аргументи (що є "класичною" 32-бітовою умовою __fastcall
) є логічним вибором. Що стосується переходу на 64-бітну, то впорядковані "вищі" регістри, і Microsoft і UN * X / Linux пішли на R8
/ R9
як перші.
Маючи це у вигляді, вибір Microsoft по RAX
(яке значення) і RCX
, RDX
, R8
, R9
(Arg [0..3]) є зрозумілим вибором , якщо ви вибираєте чотири регістра для аргументів.
Я не знаю, чому AMD64 UN * X ABI вибирав RDX
раніше RCX
.
Вибір шести регістрів аргументів на x64 - UN * X
UN * X, в архітектурах RISC, традиційно робив аргументи, передаючи регістри - конкретно, для перших шести аргументів (саме так це стосується PPC, SPARC, MIPS). Що може бути однією з головних причин, чому дизайнери AMI64 (UN * X) ABI вирішили також використовувати шість регістрів для цієї архітектури.
Так що якщо ви хочете шість регістрів для передачі аргументів на, і це логічно вибрати RCX
, RDX
, R8
і R9
чотири з них, які інших двох ви повинні вибрати?
Для "вищих" регістрів потрібен додатковий байт префікса інструкції, щоб вибрати їх, і тому вони мають більший розмір розміру інструкції, тому ви не хочете вибирати жоден із них, якщо у вас є варіанти. З класичних регістрів, з-за неявного значення RBP
та RSP
їх немає, і RBX
традиційно він має особливе застосування на UN * X (глобальна таблиця зміщення), з якою дизайнери AMD64 ABI, схоже, не хотіли б непотрібно ставати несумісними.
Ерго, єдиним вибором були RSI
/ RDI
.
Тож якщо вам доведеться приймати RSI
/ RDI
як регістри аргументів, якими вони повинні бути?
Виготовлення їх arg[0]
і arg[1]
має деякі переваги. Дивіться коментар cHao.
?SI
і ?DI
є рядковими операндами джерела / призначення, і, як згадував cHao, їх використання в якості регістрів аргументів означає, що згідно з умовами виклику AMD64 UN * X найпростіша можлива strcpy()
функція, наприклад, складається лише з двох інструкцій процесора, repz movsb; ret
оскільки джерело / ціль адреси були внесені абонентом у правильні регістри. Існує, особливо, в "клеєвому" коді, створеному низьким рівнем і створеним компілятором (подумайте, наприклад, деякі C ++ купи-розподільники об'єктів, що заповнюють нуль, на будівництві, або ж сторпинки з нульовим заповненням ядра наsbrk()
або скопіюйте за допомогою запису сторінок) величезну кількість блокової копії / заповнення, отже, це буде корисно для коду, який часто використовується для збереження двох-трьох інструкцій ЦП, які інакше завантажують такі аргументи джерела / цільової адреси в "правильні" регістри.
Таким чином , в певному сенсі, UN * X і Win64 відрізняються тільки тим , що UN * X «поміщає» два додаткових аргументу, в цілеспрямовано обраних RSI
/ RDI
регістрів, до природного вибору чотирьох аргументів в RCX
, RDX
, R8
та R9
.
Поза цим ...
Існує більше відмінностей між ABI UN * X та Windows x64, ніж просто відображення аргументів на конкретні регістри. Для огляду Win64 перевірте:
http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx
Win64 та AMD64 UN * X також разюче відрізняються за способом використання стекових просторів; Наприклад, на Win64, абонент повинен виділити стекову область для аргументів функції, навіть якщо в регістри передаються аргументи 0 ... 3. Для UN * X, з іншого боку, функції аркуша (тобто тієї, яка не викликає інших функцій) навіть не потрібно взагалі виділяти стекову область, якщо їй потрібно не більше 128 байт (так, ви володієте і можете використовувати певна кількість стека, не виділяючи його ... ну, якщо ви не код ядра, джерело чудових помилок). Все це є особливим варіантом оптимізації, більша частина обґрунтування цього пояснюється в повних посиланнях ABI, на які посилається оригінальна вікіпедія оригінального афіші.