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

为何GCC会在函数开头插入callq指令?附代码编译反汇编示例

为什么GCC会在函数开头插入callq指令?

咱们先看看你提供的代码和反汇编结果,再一步步拆解背后的原因:

代码示例

int foo(void);
int __attribute__((noinline)) xxx(int a) { return a+3; }
int my_main(void) {
    int pos;
    pos = foo();
    if (pos) return 1;
    return xxx(3);
}

编译命令

gcc -O3 -g -c main.c

关键反汇编结果

Disassembly of section .text:
0000000000000000 <xxx>:
  0:   8d 47 03                lea    0x3(%rdi),%eax
  3:   c3                      retq
0000000000000010 <my_main>:
 10:   48 83 ec 08             sub    $0x8,%rsp
 14:   e8 00 00 00 00          callq  19 <my_main+0x9>

这个callq其实是GCC为外部未定义函数foo()生成的PLT(过程链接表)占位调用,核心逻辑如下:

  • foo只做了声明但没有实现,属于外部符号,在编译阶段GCC根本不知道它的实际内存地址。
  • 你看到的e8 00 00 00 00是临时占位的机器码,反汇编显示的callq 19 <my_main+0x9>只是当前指令地址(0x14)加上指令长度(5字节)得到的临时偏移,并不是最终要调用的真实地址。
  • 等到链接阶段(不管是静态链接还是动态链接),链接器会把这个占位的偏移修正为指向PLT中对应foo的条目,程序运行时PLT会负责动态解析foo的实际地址并完成调用。

简单来说,这个callq就是对应代码里pos = foo();这行调用,只是因为foo是外部函数,编译阶段只能先生成占位的调用指令,等链接时再补全真实地址。

如果foo是在同一个编译单元里定义的,或者链接时静态链接了包含foo的目标文件,GCC会直接生成指向foo的直接调用指令,就不会出现这种占位的callq了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:43:17