Что такое инструкция callq?

У меня есть некоторый код ассемблера gnu для архитектуры x86_64, генерируемой инструментом, и есть следующие инструкции:

movq %rsp, %rbp  
leaq str(%rip), %rdi
callq puts
movl , %eax

Я не могу найти актуальную документацию по инструкции "callq".

Я посмотрел на http://support.amd.com/TechDocs/24594.pdf который является "amd64 Architecture Programmer's Manual Volume 3: Общие и системные инструкции", но они описывают только ближние и дальние инструкции вызова.

Я посмотрел на документация для GNU assembler https://sourceware.org/binutils/docs/as/index.html но не удалось найти раздел с подробными инструкциями, которые он поддерживает.

Я понимаю, что это вызов функции, но я хотел бы знать подробности. Где я могу их найти?

2 ответов


это просто call. Используйте разборку синтаксиса Intel, если вы хотите иметь возможность просматривать инструкции в руководствах Intel/AMD.

на q технически применяется суффикс размера операнда (он толкает 64-разрядный обратный адрес и обрабатывает RIP как 64-разрядный регистр), но нет способа переопределить его префиксами инструкций. т. е. calll и callw не encodeable в 64-битном режиме, так что это просто раздражает, что некоторые в&инструменты синтаксис t показывают его как из call. Это конечно относится к retq как хорошо.

различные инструменты различны в 32 против 64-разрядного режима. ( Godbolt)

  • gcc-S: всегда call/ret. Милый.
  • clang-S: callq/retq и calll/retl. По крайней мере, это постоянно раздражает.
  • objdump-d:callq/retq (явные 64-bit) и call/ret (неявно для 32-разрядной версии). Непоследовательно и глупо, потому что 64-бит не имеет выбора размера операнда, но 32-бит делает это. (Не полезное выбор, хотя: callw усекает EIP до 16 бит.)

    хотя, с другой стороны, размер операнда по умолчанию (без Рекса.W префикс) для большинство инструкции в 64-битном режиме по-прежнему 32. Но!--18--> нужен суффикс размера операнда; ассемблер не выберет 32-бит для вас, если ничего не подразумевает. OTOH,push неявно pushq, хотя pushw и pushq несколько как encodeable (и может использоваться на практике) в 64-разрядном режиме.


из руководства по эксплуатации Intel (см. выше):

для ближайшего абсолютного вызова абсолютное смещение указывается косвенно в регистре общего назначения или в ячейке памяти (r/m16, r/m32 или r/m64). Атрибут operand-size определяет размер целевого операнда (16, 32 или 64 бита). в 64-разрядном режиме размер операнда для ближнего вызова (и всех ближних ветвей) принудительно 64-бит.

для rel32 ... Как и в случае абсолютных смещений, атрибут размера операнда определяет размер целевого операнда (16, 32 или 64 бита). в 64-битном режиме целевой операнд всегда будет 64-битным, потому что размер операнда вынужден 64-бит для ближних ветвей.

в 32-битном режиме, вы можете кодировать 16-битный call rel16 это усекает EIP до 16 бит, или call r/m16 что использует абсолютный 16-битный адрес. Но, как говорится в руководстве, размер операнда фиксируется в 64-битном режиме.


callq относится к перемещаемому вызову в общих библиотеках / динамических библиотеках. Идея-push 0, затем нажмите символ поиска, затем вызовите функцию, чтобы найти ее при первом вызове. В перемещаемой таблице программы он заменяет вызов на фактическое местоположение функции при первом вызове функции. Последующие вызовы относятся к таблице перемещения, созданной во время выполнения.