美文网首页c/c++
2章 编译和链接

2章 编译和链接

作者: my_passion | 来源:发表于2022-07-06 11:51 被阅读0次

1. 从源码到可执行件: 4 步

    hello.c
    
    $ gcc hello.c
    $ ./a.out

    gcc 命令 是1层 wrap, 据不同参数 (-E / -S / -c 与 -o)
        调 cc1 (预编译编译器) / as (汇编器) / ld (链接器)
                
                
    (1) 预编译
        $ gcc -E hello.c -o hello.i
        
        5 规则
        ————————————————————————————————————————————————————    
        #define                 |   删 + 宏定义 展开
        ————————————————————————————————————————————————————    
        条件编译指令 #ifdef 等 |   处理
        ————————————————————————————————————————————————————    
        #include 预编译指令      |   递归 (多层包含) 插入 文件
        ————————————————————————————————————————————————————    
        #pragma                 |   保留 -> 给 Compiler 用
        ————————————————————————————————————————————————————    
        注释                  |   删
        ————————————————————————————————————————————————————    

    (2) 编译
    
        $ gcc -S hello.i -o hello.s
        $ ... cc1 hello.c
        
        // 预编译 + 编译
        $ gcc -S hello.c -o hello.s 
        
        6 步
        
            词法分析(扫描) / 语法分析 / 语义分析 / 
            源代码优化 / 代码生成 / 目标代码优化
            
    (3) 汇编
        
        $ gcc -c hello.s -o hello.o
        $ as hello.s -o hello.o
    
        // 预编译 + 编译 + 汇编
        $ gcc -c hello.c -o hello.c
    
    (4) 链接
    
        ld 

2. 编译器 做了什么

    array[index] = (index + 4) * (2 + 6)

    (1) 词法分析
    
        有限状态机 算法
            源码 -> 分割 -> `记号 (Token)`: 关键字 / 标识符 / 字面量 (数字, 字符串) / 特殊符号 ( + = )
        
        工具: lex
    
    (2) 语法分析
        
        上下文无关语法 
            => `语法树`: `表达式 (Expression)` 作 节点
        
        工具: yacc
        
    (3) 静态(编译期可确定)语义(含类型信息)分析
    
        1) 匹配 声明与类型
        2) 类型转换
    
    (4) 源码优化
    
        [1] 2 + 6 编译期可确定 -> 优化 为 8
        [2] 去掉不必要的 变量 t1, t3: 据 三地址码 x = y op z
    
        t1 = 2 + 6;
        t2 = index + 4;
        t3 = t2 * t1;
        array[index] = t3;
            |
            |/
        t2 = index + 4;
        t2 = t2 * 8;
        array[index] = t2;
    
    (5) 生成汇编代码
            
    (6) 优化汇编代码

        1) 位移 替 乘法
        2) 更合适的寻址
        3) 删多余指令

3. 链接器 比 编译器 早出现

(1) 机器指令 + 绝对地址 -> code 可能变动, 每次执行, 靠 coder重定位

    ————————————————————————————————
     指令 addr  |     content
    ————————————————————————————————    
        0       |   0001 0100  第 1 条指令: 跳转指令 + 绝对地址 4
        .       |
        4       |   1000 0111  第 5 条指令: 程序 foo 的开始 
    ————————————————————————————————

(2) 汇编器 + 符号 (Symbol): 让 汇编器 去 重定位

    第1条汇编指令: jmp foo

(3) 模块: 一组 var + func -> 目标文件 .obj
    
    1) 模块间 通信 = 模块间 符号的引用: 函数调用 + 变量访问 
    
    2) 模块间拼合
        `定义/引用 符号的模块: 多/少 了一块区域` -> 两者 `拼接 : 链接`

4 静态链接 —— 模块拼装

重定位: 修正 指令对 other 模块 符号(func/var)地址引用 (两者思路类似)

模块 main.o 调 func.o 中 foo()  
compiler 生成 main.o 时, 不知道 `call foo 指令` 中 `foo 地址`
    1) 先 搁置    
    2) link 时, 链接器 去 foo.o 查 foo 地址 -> 修正到 main.o
gcc 编译 (Build) 过程 分解.jpg 编译过程.jpg 语法分析 之 语法树.jpg 语义分析 之 语法树.jpg 源码优化 之 语法树.jpg 模块间拼合.jpg

相关文章

  • 编译和链接

    编译和链接 预处理 编译 汇编 链接 预处理(prepress) 处理#开头的预编译指令。 #include:包含...

  • 编译和链接

    作为刚毕业没多久的非计算机学院出身的工科生,误打误撞的变成一个程序猿,因基础知识很薄弱,在此记录一些学习的过程。...

  • 编译和链接

    (摘自《程序员的自我修养》) 1. 被隐藏了的过程   当我们使用gcc来编译一个程序时,例如   运行结束后会生...

  • 编译和链接

    摘自《程序员自我修养》 对于平时的应用程序开发,我们很少关注编译和连接过程,因为通常的开发环境都是流行的集成开发环...

  • xcode 编译 系统 深入学习(2)(待续)

    编译(通常我们说的编译包括编译和链接)报错 知识要点: 我们知道编译型语言,源文件必须经过编译(build)和链接...

  • 二、编译和链接

    1. 源代码(hello.c) 2. 预编译过程 $ gcc -E hello.c -o hello.i 预编译过...

  • 二、编译和链接

    1. 编译的四个步骤 预处理(Propressing)编译(Compilation)汇编(Assembly)链接(...

  • 2 编译和链接

    第二章 编译和链接词法分析语法分析语义分析中间语言生成目标代码生成与优化链接器 第二章 编译和链接 平时我们使用的...

  • 编译

    编译和链接 编译过程 预编译 生成.i 文件 不包含任何宏定义,宏被展开 编译 汇编 链接 编译器做了什么 词法分...

  • 第二部分-静态链接

    一、编译和链接 1、构建:IDE一般都将编译和链接的过程一步完成,通常将这种编译和链接合并到一起的过程称为构建; ...

网友评论

    本文标题:2章 编译和链接

    本文链接:https://www.haomeiwen.com/subject/boqybrtx.html