编译与反汇编过程

编译过程四个阶段:

  1. 预处理(Preprocessing):

    • 宏替换:预处理器根据 #define 指令替换宏名为宏定义的内容。
    • 文件包含:预处理器处理 #include 指令,插入被包含文件的内容。
    • 条件编译:预处理器根据 #if#ifdef 等条件指令决定哪些代码应该被编译,哪些应该被忽略。
    • 注释移除:预处理器删除代码中的注释,使得它们不会被编译器处理。
    • 输出:经过预处理后的文件通常具有 .i 后缀,内容是纯 C 代码,已处理所有宏和包含文件。
  2. 编译(Compilation):

    • 语法检查:编译器分析源代码,检查其语法是否正确。
    • 生成中间代码:编译器将源代码转换为中间表示(IR,Intermediate Representation),这种表示形式独立于目标机器。
    • 代码优化:编译器优化中间代码,使其更高效,例如消除冗余代码、进行常量折叠等。
    • 生成汇编代码:编译器将优化后的中间代码转换为汇编代码,这些代码是针对特定架构的指令集编写的。
    • 输出:汇编代码通常存储在 .s 文件中。
  3. 汇编(Assembly):

    • 翻译成机器码:汇编器将汇编代码翻译为机器码,也就是处理器可以直接执行的二进制指令。
    • 生成目标文件:汇编器生成的目标文件是一个包含二进制代码和数据的文件,这些文件通常带有 .o.obj 扩展名。
    • 输出:目标文件包含了可执行代码的片段,但还不能独立执行,因为它们可能依赖于其他代码或库。
  4. 链接(Linking):

    • 符号解析:链接器将不同目标文件中的符号(如函数名、变量名)解析为具体的内存地址。
    • 库链接:链接器将程序需要的库函数(如标准库函数)链接到最终的可执行文件中。
    • 重定位:链接器调整目标文件中代码和数据的内存地址,以确保它们在最终的可执行文件中位于正确的位置。
    • 生成二进制文件:最终生成的二进制文件通常采用 ELF(Executable and Linkable Format)格式,在 UNIX 系统中使用广泛。

ELF 文件包含的主要部分:

  1. .text 段

    • 存放程序的机器指令,也称为代码段。CPU 从这里读取指令并执行。
  2. .data 段

    • 存放已初始化的全局变量。这些变量在程序启动时会加载到内存中,并保留在程序运行期间。
  3. .bss 段

    • 存放未初始化的全局变量。这些变量在加载时被初始化为零,不占用文件空间,但在程序运行时会占用内存。
  4. 符号表

    • 存放程序中的函数名、变量名等符号信息。符号表在调试或链接过程中使用,但不包含在最终的可执行文件中。
  5. 重定位信息

    • 在程序链接过程中,链接器使用重定位信息将符号地址调整到正确的内存位置。

反汇编 ELF 文件

ELF 文件包含二进制数据和指令,无法直接作为文本文件查看。因此,需要使用反汇编工具将其中的机器码转换回汇编代码,这种过程称为反汇编。

使用 objdump -D 进行反汇编

objdump 是一个用于显示二进制文件信息的工具,可以用来反汇编 ELF 文件。

objdump -D hello

这个命令将 hello 可执行文件中的所有段(包括 .text 段)反汇编并输出为人类可读的汇编代码。

  • -D 选项:表示反汇编整个文件中的所有代码段,而不仅仅是 .text 段。
  • 输出说明
    • 地址:每条汇编指令对应的内存地址。
    • 机器码:汇编指令对应的二进制机器码。
    • 汇编指令:与机器码对应的汇编语言指令。

具体链接: objdump命令介绍-CSDN博客

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值