什么是callq指令?

时间:2017-10-15 08:00:54

标签: assembly x86 x86-64 att

我有一个由工具生成的x86_64架构的gnu汇编程序代码,并且有以下指令:

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

我找不到关于" callq"的实际文档。指令。

我查看了http://support.amd.com/TechDocs/24594.pdf这是" AMD64架构程序员手册第3卷:通用和系统指令"但是他们只描述了CALL近距离指示。

我查看了gnu汇编程序https://sourceware.org/binutils/docs/as/index.html的文档,但找不到详细说明它支持的说明的部分。

我理解它是对函数的调用,但我想知道细节。我在哪里可以找到它们?

2 个答案:

答案 0 :(得分:24)

它只是call。如果您希望能够在Intel / AMD手册中查找说明,请使用Intel-syntax反汇编。

q操作数大小后缀在技术上适用(它推送64位返回地址并将RIP视为64位寄存器),但是没有办法用指令前缀覆盖它。即calllcallw无法在64位模式下编码,因此一些AT& T语法工具将其显示为callq而不是{ {1}}。这当然也适用于call

32种与64位模式的不同工具不同。 (Godbolt

  • gcc -S:始终retq / call。好的。
  • clang -S:ret / callqretq / calll。至少它一直很烦人。
  • objdump -d:retl / callq(显式64位)和retq / call(隐式为32位)。不一致和有点愚蠢,因为64位没有操作数大小的选择,但32位没有。 (但不是有用的选择:ret将EIP截断为16位。)

    虽然另一方面,64位模式下大多数指令的默认操作数大小(没有REX.W前缀)仍为32.但callw需要一个操作数 - 大小后缀;如果没有任何暗示,汇编程序不会为你选择32位。 OTOH,add $1, (%rdi)隐含push,即使pushqpushw $1在64位模式下都可编码(and usable in practice)。

来自英特尔的指令集参考手册(上面链接):

  

对于近绝对值,绝对偏移量在通用寄存器或存储单元(r / m16,r / m32或r / m64)中间接指定。     operand-size属性确定目标操作数的大小(16,32或64位)。 在64位模式下,近呼叫(以及所有近分支)的操作数大小强制为64位

     

for rel32 ...与绝对偏移量一样,操作数大小属性确定目标操作数的大小(16,32或64位)。 在64位模式下,目标操作数将始终为64位,因为操作数大小被强制为64位用于近分支。

在32位模式下,您可以编码将EIP截断为16位的16位pushq $1或使用绝对16位地址的call rel16。但正如手册所说,操作数大小在64位模式下是固定的。

答案 1 :(得分:0)

callq是指共享库/动态库中的可重定位调用。想法是推0,然后按下符号搜索然后调用一个函数,以便在第一次调用时搜索它。在程序的可重定位表中,它在函数的第一次调用时将调用替换为函数的实际位置。后续调用引用在运行时创建的重定位表。