You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

链接前汇编call指令add_two_num+0x9含义及链接阶段作用

未链接目标文件call指令偏移问题解答

问题背景

研究链接前汇编语言的函数调用机制时,基于GCC编译C语言代码开展验证,测试用C函数的逻辑为调用外部函数实现两数相加,将结果写入入参指针指向的变量,源码如下:

void add_two_num(int x, int y, int * dest)
{
  int val;

  val = dummy(x, y);
  *dest = val;
}

将源码编译为未执行链接操作的elf64-x86-64格式目标文件后,使用objdump -d对目标代码反汇编,得到如下汇编结果:

file format elf64-x86-64

0000000000000004 <add_two_num>:
   4:   53                      push   %rbx
   5:   48 89 d3                mov    %rdx,%rbx
   8:   e8 00 00 00 00          call   d <add_two_num+0x9>
   d:   89 03                   mov    %eax,(%rbx)
   f:   5b                      pop    %rbx
  10:   c3                      ret  

待解答的两个核心问题:

  • 反汇编行call d <add_two_num+0x9>中的+0x9代表什么含义?
  • 后续链接阶段该行会被修正为实际函数调用地址,这个偏移值在链接阶段是否具备实际作用?

问题解答

1. +0x9的实际含义

这个值是objdump反汇编时计算生成的临时假目标标记,不存在任何实际代码语义:

  • x86-64架构下,e8开头的近过程调用指令固定长度为5字节:1字节操作码+4字节PC相对跳转偏移。这条call指令的起始地址是0x8,CPU执行完这条指令时,程序计数器(即PC相对跳转的计算基准地址)正好是0x8 + 5 = 0xd,也就是call指令后紧邻的mov指令的地址。
  • 未链接的目标文件中,call指令携带的4字节偏移全为0,是留给链接器填充的占位符。objdump反汇编时按照"基准地址 + 指令内存储的偏移值"规则计算跳转目标,得到的结果就是0xd + 0 = 0xd。这个地址相对于add_two_num函数起始地址0x4的偏移量为9,因此objdump给这个计算出来的假跳转目标标记为<add_two_num+0x9>,并非代码真的要跳转到函数内偏移0x9的位置。

2. 该偏移值在链接阶段的作用

这个显示出来的+0x9标记在链接阶段没有任何实际作用:

  • 首先这个标记只是反汇编工具生成的提示文本,根本不存在于目标文件的二进制内容中,链接器完全感知不到这个值的存在。
  • 链接器处理这条call指令时,只会读取目标文件重定位表中存储的正式信息:待跳转的符号名dummy、重定位类型(x86-64下对应PC相对调用的重定位类型)、待修正的指令位置、跳转偏移计算的基准地址(即call后下一条指令的地址),基于这些信息计算出真实的跳转偏移,替换掉指令中全0的占位符即可。
  • 链接完成后再反汇编,call指令就会显示正确的跳转目标,这个临时的+0x9标记也会随之消失。

内容的提问来源于stack exchange,提问作者arka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 09:51:25