程序员自我修养2:编译过程

2020-10-09  本文已影响0人  梦工厂

编译过程分为6步:扫描(词法分析)、语法分析、语义分析、源代码优化、代码生成、目标代码优化。

示例代码:array[index] = (index + 4) * (2 + 6)

  1. 词法分析
    源代码被输入到扫描器,运用类似有限状态机的算法将代码的字符序列分割成一系列的记号,Token包括:关键字、标识符、字面量(数字、字符串)和特殊符号(加减)。
    扫描器在识别记号的同时,也会将标识符放到符号表,数字字符串常量放到文字表等以备后用。
    工具:lex;
  1. 语法分析
    语法分析器将对扫描器产生的记号进行语法分析,生成以表达式为节点的语法树。
    相关方法:上下文无关文法、下推自动机;
    工具:yacc;
  1. 语义分析
    语义分析器完成语句的语义分析,例如两个指针做乘法在语法上是合法的,但没有意义;

    • 静态语义:编译阶段可以确定的语义,包括声明和类型的匹配,类型的转换;
    • 动态语义:运行阶段才能确定的语义,比如将0作为除数;

    经过语义分析阶段后,整个语法树的表达式都被标示了类型,有些会插入隐式转换所需的转换节点。

  1. 中间代码生成(源代码优化)
    源代码优化器会在源代码级别进行优化,例如(2+6)这个表达式可以优化为8;
    直接在语法树上进行优化比较困难,源代码优化器会将整个语法树转换为中间代码,它是语法树的顺序表示。
    中间代码类似目标代码,但是它跟机器平台无关,不含数据尺寸、变量地址和寄存器的名字。将编译器分为了前端和后段,前端负责产生机器无关的中间代码,后端负责将中间代码转换成目标机器代码。
     t2 = index + 4
     t2 = t2 * 8
     array[index] = t2
    
  2. 目标代码的生成
    代码生成器负责将中间代码转换成机器代码,过程依赖于目标机器,不同的机器不同字长、寄存器、数据类型;
  1. 目标代码的优化
    目标代码优化器对上述的目标代码进行优化,比如选择合适的寻址方式,使用位移来代替乘法运算、删除多余的指令等;

此时index和array的地址还没确定,如果符号的定义和源代码在同一个编译单元,编译器可以为他们分配空间来确定地址,如果定义在其他的模块,需要等到链接时才能确定最终运行时的绝对地址;

上一篇下一篇

猜你喜欢

热点阅读