什么是callq指令?

use*_*607 28 x86 assembly x86-64 att

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

movq %rsp, %rbp  
leaq str(%rip), %rdi
callq puts
movl $0, %eax
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Pet*_*des 31

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

q操作数大小的后缀并在技术上应用(它推64位的返回地址和对待RIP作为64位寄存器),但也没有办法与指令前缀来覆盖它.即calll,callw并且不能在64位模式下编码,所以一些AT&T语法工具显示它callq而不是令人讨厌call.这当然也适用retq于此.

32位与64位模式的不同工具不同.(Godbolt)

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

    虽然另一方面,64位模式下大多数指令的默认操作数大小(没有REX.W前缀)仍然是32.但是add $1, (%rdi)需要一个操作数大小的后缀; 如果没有任何暗示,汇编程序将不会为您选择32位.OTOH,push隐式pushq,即使pushw $1pushq $1均为encodeable(并且在实践中可使用的)在64位模式.


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

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

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

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