第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 链接

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

 

posted @ 2019-11-13 22:53  Hengs  阅读(304)  评论(0编辑  收藏  举报