• 第19课


    第19课 - 编译过程简介

    1. 初识编译器

    我们通常所说的编译器其实是一个广义的概念,其实它里面包含了多个子模块,编译的过程由这些子模块协作完成。

        

    编译器的工作过程

        

        

    2. 编译器做了什么?

    2.1 预处理

    预处理由预处理器完成,预处理指令示例:gcc -E file.c -o file.i

    (1)处理所有的注释,以空格代替

    (2)将所有的 #define 删除,并且展开所有的宏定义

    (3)处理条件编译指令 #if#ifdef#elif#else#endif

    (4)处理 #include,展看被包含的文件

    (5)保留编译器需要使用的 #pragma 指令

    // 19-1.h

    1 /*
    2     This is a header file.
    3 */
    4 
    5 char* p = "Hello World!";
    6 
    7 int i = 0;

    // 19-1.c

     1 #include "19-1.h"
     2 
     3 // Begin to define macro
     4 
     5 #define GREETING "Hello world!"
     6 #define INC(x) x++
     7 
     8 // End
     9 
    10 int main()
    11 {   
    12     p = GREETING;  
    13   
    14     INC(i);   
    15 
    16     return 0;
    17 }

    gcc -E 19-1.c -o 19-1.i 的预处理结果

    # 1 "19-1.c"
    # 1 "<built-in>"
    # 1 "<command-line>"
    # 1 "/usr/include/stdc-predef.h" 1 3 4
    # 1 "<command-line>" 2
    # 1 "19-1.c"
    # 1 "19-1.h" 1
    
    
    char* p = "Hello World!";
    
    int i = 0;
    # 2 "19-1.c" 2
    # 11 "19-1.c"
    int main()
    {
        p = "Hello world!";
    
        i++;
    
        return 0;
    }

    2.2 编译

    编译由编译器(狭义)完成,编译指令示例:gcc -S file.i -o file.s

    (1)对预处理文件进行词法分析语法分析语义分析

    • 词法分析:分析关键字、标识符、立即数等是否合法
    • 语法分析:分析表达式是否遵循词法规则
    • 语义分析:在语法分析的基础上进一步分析表达式是否合法

    (2)分析结束后进行代码优化生成相应的汇编代码文件

    gcc -S 19-1.i -o 19-1.s 的预处理结果

        .file    "19-1.c"
        .globl    p
        .section    .rodata
    .LC0:
        .string    "Hello World!"
        .data
        .align 8
        .type    p, @object
        .size    p, 8
    p:
        .quad    .LC0
        .globl    i
        .bss
        .align 4
        .type    i, @object
        .size    i, 4
    i:
        .zero    4
        .section    .rodata
    .LC1:
        .string    "Hello world!"
        .text
        .globl    main
        .type    main, @function
    main:
    .LFB0:
        .cfi_startproc
        pushq    %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movq    $.LC1, p(%rip)
        movl    i(%rip), %eax
        addl    $1, %eax
        movl    %eax, i(%rip)
        movl    $0, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE0:
        .size    main, .-main
        .ident    "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4"
        .section    .note.GNU-stack,"",@progbits

    2.3 汇编

    汇编由汇编器完成,汇编指令示例:gcc -c file.s -o file.o    file.o是二进制文件

    (1)汇编器将汇编代码转变为机器的可执行指令

    (2)每条汇编语句几乎都对应一条机器指令

    2.4 链接

    通过连接器生成最终的可执行文件,链接器具体是如何工作的,我将在下一篇文章中讲解。

  • 相关阅读:
    ab命令做压测测试
    用js两张图片合并成一张图片
    Web全景图的原理及实现
    深入理解Java中的IO
    Spring AOP详解
    spring @Transactional注解参数详解
    优化MyBatis配置文件中的配置
    使用MyBatis对表执行CRUD操作
    @requestBody注解的使用
    url 拼接的一个模块furl
  • 原文地址:https://www.cnblogs.com/shiwenjie/p/11853932.html
Copyright © 2020-2023  润新知