美文网首页
C语言的编译和执行过程

C语言的编译和执行过程

作者: 李明燮 | 来源:发表于2020-11-03 09:40 被阅读0次

    没有系统的学过C语言,为了了解java编译流程。
    先简单的略过了一下C语言的编译过程。

    C语言在Linux系统下编译是有4个过程

    1. 预处理Pre-processing
    2. 编译Compilation
    3. 汇编Assemble
    4. 链接Linking

    如下图所示每个过程会生成不同的文件。
    这些文件会被RAM读取loading后,在系统中运行。

    图片备用地址

    C语言的编译过程

    1.预处理Pre-processing

    简单的说预处理就是处理#开头的命令。

    • 删除注释: 去掉没必要的注释。
    • 宏定义指令: 如#difine, #undef。(替换这些值)
    • 头文件包含指令: 如#include。(直接插入include的代码)
    • 条件编译指令: 如#ifdef,#ifndef,#else,#elif,#endif等。
    • 特殊符号: 如在源程序中出现的#line标识将被解释为当前行号。

    下面简单的写代码看一下过程。

    #include <stdio.h>
    #define A 10
    #define B 20
    int main(){
            int a=A;
            int b=B;
            int c=a+b;
            printf("%d + %d = %d\n",a,b,c);
    }
    

    创建first.i文件

    $ gcc -E first.c -o first.i
    

    查看一下first.i内容

    $ cat first.i
    # 1 "first.c"
    # 1 "<built-in>" 1
    ... ...
    int main(){
            int a=10;
            int b=20;
            int c=a+b;
            printf("%d + %d = %d\n",a,b,c);
    }
    

    可以看出A的值被替换了, stdio.h的内容也插入进来了。


    2.编译Compilation

    做完预处理后,Compiler会做编译成Assemble。
    编译的过程可以分3个阶段。Front-end,Middle-end,Back-end。
    Source code -> (GENERIC -> GIMPLE) -> (SSA -> RTL) -> Assembly)

    图片备用地址

    编译的整个过程
    2.1 Front-end

    第一阶段会执行以下内容。

    • 词法分析: 把C语言代码分成最小单位(token)。
    • 语法分析: 用token创建Parse Tree检查语法错误。
    • 语义分析: 之后检查整体语义有没有问题。比如用错变量,数据类型不一致等等...
    • 中间代码生成: 生成Compile Tree。
    2.2 Middle-end

    这个阶段会把Compile Tree转换成SSA(Static Single Assignment)形态,
    基于SSA做一些跟目标语言和结构无关的优化。
    (例如,内联,常数传播,尾调用消除,冗余消除等,不会受限于CPU结构共同做的优化)。
    基于SSA的优化还可以分局部优化,全局优化和循环优化。
    最终生成高级语言和汇编的中间态的RTL(Register Transfer Language)。

    2.3 Back-end

    RTL通过RTL Optimizer再一次同时进行跟目标语言和结构无关的优化 + 相关的优化。
    这次优化根据所在的结构和环境进一步做一些有效的优化。
    这样最终生成汇编Assemble。

    下面看看实际过程。

    $ gcc -S first.i -o first.s
    

    查看一下first.s内容

    $ cat first.s
        .section    __TEXT,__text,regular,pure_instructions
        .macosx_version_min 10, 13
        .globl  _main                   ## -- Begin function main
        .p2align    4, 0x90
    _main:                                  ## @main
        .cfi_startproc
    ## %bb.0:
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset %rbp, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register %rbp
        subq    $16, %rsp
        leaq    L_.str(%rip), %rdi
        movl    $10, -4(%rbp)
        movl    $20, -8(%rbp)
        movl    -4(%rbp), %eax
        addl    -8(%rbp), %eax
        movl    %eax, -12(%rbp)
        movl    -4(%rbp), %esi
        movl    -8(%rbp), %edx
        movl    -12(%rbp), %ecx
        movb    $0, %al
        callq   _printf
        xorl    %ecx, %ecx
        movl    %eax, -16(%rbp)         ## 4-byte Spill
        movl    %ecx, %eax
        addq    $16, %rsp
        popq    %rbp
        retq
        .cfi_endproc
                                            ## -- End function
        .section    __TEXT,__cstring,cstring_literals
    L_.str:                                 ## @.str
        .asciz  "%d + %d = %d\n"
    
    
    .subsections_via_symbols
    

    不知道里面写的是什么内容...ㅠㅠ


    3.汇编Assemble

    编译完的代码,通过汇编过程编译成机器语言。
    汇编的主要目的是把目标对象 ***.o
    转换成有Instruction和Data的 ELF Binary format结构。

    下面看看实际过程。

    $ gcc -c first.s -o first.o
    

    查看一下first.o内容

    $ cat first.o
    ���� �� �__text__TEXTC ��__cstring__TEXTCc__compact_unwind__LDX x�__eh_frame__TEXTx@�
                                                                                         h$
    �
     PUH��H��H�=4�E�
    �E��E�E�E�u�U�M��1ɉE��H��]�%d + %d = %d
    CzRx
    2- �$h�������CA�C
      _main_printf%
    

    用hexdump命令查看会是什么内容?

    $ hexdump -C first.o
    00000000  cf fa ed fe 07 00 00 01  03 00 00 00 01 00 00 00  |................|
    00000010  04 00 00 00 00 02 00 00  00 20 00 00 00 00 00 00  |......... ......|
    00000020  19 00 00 00 88 01 00 00  00 00 00 00 00 00 00 00  |................|
    00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    00000040  b8 00 00 00 00 00 00 00  20 02 00 00 00 00 00 00  |........ .......|
    00000050  b8 00 00 00 00 00 00 00  07 00 00 00 07 00 00 00  |................|
    00000060  04 00 00 00 00 00 00 00  5f 5f 74 65 78 74 00 00  |........__text..|
    00000070  00 00 00 00 00 00 00 00  5f 5f 54 45 58 54 00 00  |........__TEXT..|
    00000080  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    00000090  43 00 00 00 00 00 00 00  20 02 00 00 04 00 00 00  |C....... .......|
    000000a0  d8 02 00 00 02 00 00 00  00 04 00 80 00 00 00 00  |................|
    000000b0  00 00 00 00 00 00 00 00  5f 5f 63 73 74 72 69 6e  |........__cstrin|
    000000c0  67 00 00 00 00 00 00 00  5f 5f 54 45 58 54 00 00  |g.......__TEXT..|
    000000d0  00 00 00 00 00 00 00 00  43 00 00 00 00 00 00 00  |........C.......|
    000000e0  0e 00 00 00 00 00 00 00  63 02 00 00 00 00 00 00  |........c.......|
    000000f0  00 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  |................|
    00000100  00 00 00 00 00 00 00 00  5f 5f 63 6f 6d 70 61 63  |........__compac|
    00000110  74 5f 75 6e 77 69 6e 64  5f 5f 4c 44 00 00 00 00  |t_unwind__LD....|
    00000120  00 00 00 00 00 00 00 00  58 00 00 00 00 00 00 00  |........X.......|
    00000130  20 00 00 00 00 00 00 00  78 02 00 00 03 00 00 00  | .......x.......|
    00000140  e8 02 00 00 01 00 00 00  00 00 00 02 00 00 00 00  |................|
    00000150  00 00 00 00 00 00 00 00  5f 5f 65 68 5f 66 72 61  |........__eh_fra|
    00000160  6d 65 00 00 00 00 00 00  5f 5f 54 45 58 54 00 00  |me......__TEXT..|
    00000170  00 00 00 00 00 00 00 00  78 00 00 00 00 00 00 00  |........x.......|
    00000180  40 00 00 00 00 00 00 00  98 02 00 00 03 00 00 00  |@...............|
    00000190  00 00 00 00 00 00 00 00  0b 00 00 68 00 00 00 00  |...........h....|
    000001a0  00 00 00 00 00 00 00 00  24 00 00 00 10 00 00 00  |........$.......|
    000001b0  00 0d 0a 00 00 00 00 00  02 00 00 00 18 00 00 00  |................|
    000001c0  f0 02 00 00 02 00 00 00  10 03 00 00 10 00 00 00  |................|
    000001d0  0b 00 00 00 50 00 00 00  00 00 00 00 00 00 00 00  |....P...........|
    000001e0  00 00 00 00 01 00 00 00  01 00 00 00 01 00 00 00  |................|
    000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    *
    00000220  55 48 89 e5 48 83 ec 10  48 8d 3d 34 00 00 00 c7  |UH..H...H.=4....|
    00000230  45 fc 0a 00 00 00 c7 45  f8 14 00 00 00 8b 45 fc  |E......E......E.|
    00000240  03 45 f8 89 45 f4 8b 75  fc 8b 55 f8 8b 4d f4 b0  |.E..E..u..U..M..|
    00000250  00 e8 00 00 00 00 31 c9  89 45 f0 89 c8 48 83 c4  |......1..E...H..|
    00000260  10 5d c3 25 64 20 2b 20  25 64 20 3d 20 25 64 0a  |.].%d + %d = %d.|
    00000270  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    00000280  43 00 00 00 00 00 00 01  00 00 00 00 00 00 00 00  |C...............|
    00000290  00 00 00 00 00 00 00 00  14 00 00 00 00 00 00 00  |................|
    000002a0  01 7a 52 00 01 78 10 01  10 0c 07 08 90 01 00 00  |.zR..x..........|
    000002b0  24 00 00 00 1c 00 00 00  68 ff ff ff ff ff ff ff  |$.......h.......|
    000002c0  43 00 00 00 00 00 00 00  00 41 0e 10 86 02 43 0d  |C........A....C.|
    000002d0  06 00 00 00 00 00 00 00  32 00 00 00 01 00 00 2d  |........2......-|
    000002e0  0b 00 00 00 02 00 00 15  00 00 00 00 01 00 00 06  |................|
    000002f0  01 00 00 00 0f 01 00 00  00 00 00 00 00 00 00 00  |................|
    00000300  07 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
    00000310  00 5f 6d 61 69 6e 00 5f  70 72 69 6e 74 66 00 00  |._main._printf..|
    00000320
    

    嘿嘿,更看不懂...ㅠㅠ
    只能推测出这是机器能看懂的机器语言吧?


    4.链接Linking

    通过汇编过程生成的机器语言在这个过程,链接(link)那些分别生成的包和程序。
    printf()函数或 scanf()函数是已经有了已编号好标准的包。
    不需要再次编译,在这次过程会跟程序链接(link)。

    看看实际执行结果

    $ gcc first.o -o first
    

    最终结果的执行。

    $ ./first
    10 + 20 = 30
    

    总结

    C语言编译时会经过预处理,编译,汇编,链接4个过程
    预处理时会将处理含有#符号的代码(注释,命令语以及特殊符号)
    编译时会检查语法以及做一些优化
    汇编时把代码转成机器可以看懂的机器语言
    链接时把相关的包和程序链接起来,生成可执行文件。


    欢迎大家的意见和交流

    email: li_mingxie@163.com

    相关文章

      网友评论

          本文标题:C语言的编译和执行过程

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