编译

作者: 奋斗的蝼蚁 | 来源:发表于2020-05-31 16:15 被阅读0次

    编译和链接

    编译过程

    预编译

    生成.i 文件 不包含任何宏定义,宏被展开

    编译

    汇编

    链接

    编译器做了什么

    词法分析

    有限状态机算法可以将源代码的字符序列分割成一系列的记号。

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

    词法分析一般包括:关键词、标识符、字面量(包含数字、字符串)和特殊符号(加号、等号)

    语法分析

    对词法分析的记号进行语法分析,产生语法树,树的节点是表达式。语法层面的分析,并不了解这个语句是否真正有意义。

                      assignExpression
    
       SubscriptExpression[]           MultipicativeExpression *
     
    Identifier          Identifier       Additive               Additive
    Expression         Expression        Expression(+)        Expression(+)
    array               index
                                    Identifier  Number    Number       Number
                                     Index         4       2             6
    
    

    语义分析

    语法分析仅仅是完成了对表达式的语法层面的分析,但是它并不了解这个语句是否真正有意义

    静态语义

    编译期可以确定的语义,包括声明和类型的匹配,类型的转换。比如当一个浮点型的表达式赋给一个整形的表达式时,其中隐含了一个浮点型到整形的转换的过程,语义分析过程中需要完成这个步骤,

    动态语义

    运行期可以确定的语义,程序运行期出现的语义相关的问题。
    经过语义分析阶段以后,整个语法树的表达式都被标识了类型,如果有些类型需要做隐式转换,语义分析程序会在语法树中插入相应的转换节点,

    image

    中间语言生成

    在源代码级别有一个优化过程,源代码优化器会在源代码级别进行优化,(2 + 6)这个表达式可以被优化,因为它的值在编译器就可以被确定。

    目标代码生成与优化

    movl index, %ecx;  value of index to ecx
    addl $4, %ecx  ; ecx = ecx + 4
    mull $8m %ecx  ; ecx = ecx * 8
    movl index %eax ; value of index to eax
    movl %ecx,array(,eax,4) ; array[index] = ecx
    
    

    最后目标代码优化器对上述的目标代码进行优化,比如选择合适的寻址方式、使用位移来代替乘法运算、删除多余的指令等。上面的例子中,乘法由一条相对复杂的基址比例变址寻址的lea 指令完成,随后由一条mov 指令完成最后的赋值操作,这条mov指令的寻址方式与lea是一样的。

    movl  index, %edx
    leal 32(,%edx, 8), %eax
    movl %eax,array(,%edx, 4)
    
    

    模块拼装 - 静态链接

    人们把每个源代码模块独立编译,然后按照需要将他们“组装”起来,这个组装模块的过程就是链接,链接的主要内容就是吧各个模块之间相互引用的部分处理好,使的各个模块之间能够正确的衔接。链接器的工作就是把一些指令对其他符号地址的引用加以修正。链接过程主要包括了地址和空间分配、符号决议和重定位等这些步骤。

    目标文件

    每个模块的源代码文件经过编译器编译成目标文件,目标文件和库一起链接形成最终可执行文件

    相关文章

      网友评论

          本文标题:编译

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