我有一个由工具生成的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的文档,但找不到详细说明它支持的说明的部分。
我理解它是对函数的调用,但我想知道细节。我在哪里可以找到它们?
答案 0 :(得分:24)
它只是call
。如果您希望能够在Intel / AMD手册中查找说明,请使用Intel-syntax反汇编。
q
操作数大小后缀在技术上适用(它推送64位返回地址并将RIP视为64位寄存器),但是没有办法用指令前缀覆盖它。即calll
和callw
无法在64位模式下编码,因此一些AT& T语法工具将其显示为callq
而不是{ {1}}。这当然也适用于call
。
32种与64位模式的不同工具不同。 (Godbolt)
retq
/ call
。好的。ret
/ callq
和retq
/ 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
,即使pushq
和pushw $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,然后按下符号搜索然后调用一个函数,以便在第一次调用时搜索它。在程序的可重定位表中,它在函数的第一次调用时将调用替换为函数的实际位置。后续调用引用在运行时创建的重定位表。