Fork me on GitHub

[程序员的自我修养--链接、装载与库]笔记(二)

第二章 编译和链接

被隐藏的过程

gcc处理最简单的hello world程序也要分解为4个步骤:

  • 预处理(prepressing)
  • 编译(compilation)
  • 汇编(assembly)
  • 链接(linking)

过程如图所示:

预编译阶段

预编译过程主要处理那些源代码文件中以”#”开头的预编译指令,主要规则如下:

hello.i文件部分内容如下:


编译阶段(后文详解)

//hello.s文件内容
        .file   "hello.c"
        .section        .rodata
.LC0:
        .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
        movl    $.LC0, %edi
        movl    $0, %eax
        call    printf
        movl    $0, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-16)"
        .section        .note.GNU-stack,"",@progbits

汇编阶段


所以,有以下3种命令方式生成目标文件:
as hello.s -o hello.o
gcc -c hello.s -o hello.o
gcc -c hello.c -o hello.o

链接阶段

编译器做了哪些工作


以下面的代码为例分析对应过程:
array[index]=(index+4)*(2)
CompilerExpression.c

词法分析

语法分析

基于上下文无关文法和下推自动机对扫描器产生的记号构造文法树

语义分析



源码级优化产生中间代码

上述语法树中,(2+6)这个表达式可以在编译器就确定下来,因此完全可以用8代替,这就是源码级优化,类似还有其它复杂的优化过程,不在赘述。



t2 = index + 4
t2 = t2 * 8
array[index] = t2

目标代码生成和目标代码优化



链接器的静态链接

好好理解下面的话


------ Happy Ending Meet The Better You ------