linux - callq 命令参数的含义是什么?

标签 linux assembly x86-64 disassembly object-files

我知道 callq 是什么指令确实;在 this answer 中有描述.该指令应有一个参数,即被调用函数的地址。

但是,在反汇编目标文件时,我看到以下行显示 callq具有两个值而不是一个参数的指令:

  1e:   e8 00 00 00 00          callq  23 <main+0x19>

我假设 23是返回地址,<main+0x19>是要调用的函数的地址。但是,调用的函数不在地址main+0x19。 .

这两个值是什么意思23main+0x19callq 的反汇编中显示指令?


原始C代码:

#include <stdio.h>

void fun(int a)
{
}

int main()
{
    int a = 1234;
    fun(a);
}

objdump -D main.o main.asm 反汇编代码:

0000000000000000 <fun>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   89 7d fc                mov    %edi,-0x4(%rbp)
   7:   90                      nop
   8:   5d                      pop    %rbp
   9:   c3                      retq   

000000000000000a <main>:
   a:   55                      push   %rbp
   b:   48 89 e5                mov    %rsp,%rbp
   e:   48 83 ec 10             sub    $0x10,%rsp
  12:   c7 45 fc 03 00 00 00    movl   $0x3,-0x4(%rbp)
  19:   8b 45 fc                mov    -0x4(%rbp),%eax
  1c:   89 c7                   mov    %eax,%edi
  1e:   e8 00 00 00 00          callq  23 <main+0x19>
  23:   b8 00 00 00 00          mov    $0x0,%eax
  28:   c9                      leaveq 
  29:   c3                      retq   

最佳答案

callq 指令只有一个操作数,而不是问题中暗示的两个。反汇编器以两种形式显示它,作为地址和作为符号 + 偏移量。

您正在查看一个未链接 目标文件的反汇编。由于被反汇编的文件没有链接,所以显示的目标地址不是 fun 的地址。汇编器将0放入指令的操作数字段,并为链接器创建一个重定位记录,以填充到目标最终地址的偏移量。

调用指令的操作数是一个偏移量,相对于调用后下一条指令的地址。因此,操作数字段中的值 0 会导致反汇编程序将下一条指令的地址显示为调用的目标。在所示的反汇编中,地址为 23。

如果您将 fun 设为静态函数,汇编器可能会填写该函数的真实偏移量,因为它不需要重定位,您将在反汇编中看到它。 (这可能取决于您使用的确切工具和选项。)

如果您反汇编一个链接的可执行文件,反汇编程序将显示调用的真实目标地址。

关于linux - callq 命令参数的含义是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56122039/

相关文章:

optimization - GCC 不使用 inc

assembly - 如何在 NASM 中推送 64 位整数?

linux - 目录脚本中的文件

linux - centos 中的 yum 错误

c++ - 使用来自 asm 的引用参数调用 C++ 成员函数

x86 - 在哪里可以找到 x86 的汇编程序?

assembly - 对齐给定的指令,但将对齐填充放在指令之前以外的其他位置

linux - QThread::start(priority) 与 Linux

c - Linux Makefile.am 错误 "undefined reference to"

linux - breakpad 32 位构建在 64 位 Linux 系统上失败