Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

目标文件格式

复习

  • 生成汇编代码:汇编之后还要经汇编器
  • 程序在内存里的样子:代码区、数据区等
  • 从源代码到可执行文件:编译、汇编、链接的流水线

TL;DR

  • 目标文件是汇编器产出的中间产物,还不是可执行文件
  • 它包含机器码,还包含符号、分段和其他元数据
  • 常见内容:代码段、数据段、符号表、重定位信息
  • 多个目标文件要靠链接合成为可执行文件

正文

  汇编代码经汇编器翻译,得到的不直接是可执行文件,而是一个目标文件(object file)。为什么还要一个中间的“目标文件”,而不是一步生成可执行文件?

因为它还不知道“最终在哪”

  根本原因在于:编译一个文件时,编译器还不知道整个程序最终会怎么摆放。

  比如你的代码里调用了另一个文件里的函数、或者用了一个外部变量。这个函数最终会被放在内存的哪个地址?此刻谁也说不准——那要等所有文件合在一起、统一分配地址之后才知道。

  既然地址未知,目标文件里就要做两件事:

  • 先留个“空位”:那个地址暂时空着
  • 顺便记一笔:这里将来需要填上一个地址

  这笔“哪里需要填地址”的记录,就是重定位信息,是下一章的主角。

目标文件里有什么

  一个典型的目标文件,大致包含:

  • 机器码(代码段)
  • 已初始化的数据(数据段)、未初始化的数据(可简记为一个大小)
  • 符号表:这个文件对外提供了哪些名字,又引用了哪些外部的名字
  • 重定位信息:哪些位置需要链接时填地址

  你会发现,它和我们讲程序在内存里的样子时说的“代码区、数据区”,是能对上的:目标文件其实就是这些内容在磁盘上的“打包形态”。

它是砖,不是房子

  目标文件像是盖房子用的一块:它自身完整,却还不是一座房子。多个目标文件(以及库)要由链接器拼在一起,才成为可执行文件。

  所以,从源码到能运行的程序,路径是:

源代码 →(编译)→ 汇编 →(汇编)→ 目标文件 →(链接)→ 可执行文件

  前面讲编程基础时,我们把“编译、汇编、链接”当成黑箱;现在,我们正站在“汇编之后、链接之前”。下一组,就正式进入链接。

思考题 1

  目标文件里除了机器码,还需要哪些信息?为什么?

思考题 2

  为什么汇编器不直接生成可执行文件,而要先生成目标文件?

小结

知识点

  • 目标文件是汇编器产出的中间产物
  • 它含代码段、数据段、符号表与重定位信息
  • 因为外部地址未知,需要先留空并记录
  • 多个目标文件由链接器合成可执行文件

参考资料

  1. Wikipedia(zh):目标文件:汇编器生成的、等待链接的中间文件
  2. Wikipedia(zh):符号表:目标文件中记录名字与引用的表

思考题答案(仅供参考)

思考题 1

  还需要符号表(记录本文件提供和引用的名字)和重定位信息(记录哪些位置将来需要填入地址),以及各段的内容与布局。因为编译单个文件时外部符号的最终地址未知,必须留待链接时确定。

思考题 2

  因为单个文件编译时还不知道外部符号的地址,也无法与其它文件合并。先生成目标文件、记录好符号与重定位信息,再由链接器统一分配地址、合并各段,才能得到可执行文件。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪