Первая часть: все библиотечные функции соответствуют стандартному соглашению о вызовах . На всех платформах x86-64, кроме Windows, это x86-64 System V ABI.
- Где документирован x86-64 System V ABI?
- Какие регистры сохраняются при вызове функции linux x86-64 цитирует ABI do c, для которого регистры сохраняются при вызове по сравнению с вызовом-закрыто. Вы должны предположить, что каждый закрытый вызовом регистр является перекрытым любым вызовом функции; используйте сохраняемые вызовы регистры для значений, которые вы хотите пережить при вызове.
Каковы соглашения о вызовах для системных вызовов UNIX & Linux на i386 и x86-64 - в частности, целочисленные / указательные аргументы передаются в RDI, RSI, RDX, RCX, R8, R9 в том же порядке в x86-64 System V. Дополнительные аргументы go в стеке. (И RSP всегда должен быть выровнен на 16 байт перед call
).
Вы также можете посмотреть на вывод компилятора для функции C, которая выполняет вызов функции или принимает аргументы, чтобы увидеть, получили ли вы это правильно, если вы знаете, что вещи даже искать. (например, с помощью gcc -S -fverbose-asm
или https://godbolt.org/).
Вы можете создавать свои собственные соглашения при написании собственных функций asm, например, возвращая несколько различных значения в нескольких регистрах вместо того, чтобы ограничивать себя только тем, что вы могли бы сделать компилятором C.
(например, вы могли бы написать memcmp
, который возвращает позицию первой разницы в RDI и фактическую <= или> во FLAGS, например, от выполнения cmp
для несовпадающих байтов.)
Но функции, сгенерированные компилятором, которые вы можете вызывать из asm (включая C стандартные функции библиотеки), всегда будут следовать ABI .
Вторая часть: неявное использование регистров некоторыми инструкциями : обратитесь к руководству по ISA для получения соответствующих инструкций. Если вы этого не знаете, не просто предполагайте по названию.
Вы можете выполнить пошаговый отладчик, который выделяет изменения значений регистра, чтобы помочь вам заметить любой случай, когда изменения реестра были вами вообще ничего не ожидаю.
Посмотрите инструкции в руководстве Intel vol.2 (или аналоге AMD). например, HTML извлечение PDF-файла Intel по адресу https://www.felixcloutier.com/x86/, в частности запись для loop
. Также Как именно работает инструкция x86 L OOP? объясняет, что это похоже на dec rcx / jnz
, за исключением того, что без установки FLAGS.
Не так много инструкций с неявными операндами. Наиболее часто используемыми являются инструкции стека, такие как push / pop, неявно использующие RSP очевидным образом.
Другие известные включают E / RAX и E / RDX, используемые одним операндом [i]mul
и [i]div
. (И cdq
, чтобы подписать расширение EAX в EDX: EAX, чтобы настроить для idiv, или cdqe
в RAX)
CL для переменных значений смещения неявно присутствует в машинном коде, но явным образом в источнике asm. (например, shr rdx, cl
).
команды rep- «string» неявно используют RCX, плюс RSI и / или RDI.
Большинство из этих неявных применений пришло из старых 8086 история. См. Почему нет регистра, содержащего старшие байты EAX? . Инструкции, такие как loop
и jrcxz
, не используются компиляторами , потому что они медленные , а форма с 2 операндами imul
как imul ecx, edx
быстрее, когда вам не нужно высокая половина результата в EDX / RDX.
Дополнительное чтение:
Это не исчерпывающий список. cmpxchg / cmpxchg16b, xlat, cpuid, rdts c, rdpm c и многие другие имеют неявные операнды, но только некоторые из инструкций, которые регулярно используются компиляторами, делают.
Обратите внимание, что FLAGS является неявный ввод для многих инструкций, таких как adc
и cmov
.
NASM имеет приложение, в котором перечислены все инструкции , но, как правило, ассемблеры оставляют это на усмотрение поставщиков ЦП. Все ассемблеры x86-64 выдают машинный код по одним и тем же инструкциям. Эта исправленная ошибка ветка более старой версии этого do c содержит описания инструкций Engli sh. (Mainline NASM удалил это из-за недостатка места после добавления инструкций SSE; сейчас слишком много возможностей сделать больше, чем просто перечислить на одной плоской странице с AVX2 и особенно с AVX512.)