什么叫编译?


经常看到文件编译,编译到底是干嘛?

1、什么是编译?

对于同一个语句,有高级语言、低级语言、机器语言的方式来表示。

C语言:

a=b+1;

汇编语言:

mov -0xc(%ebp),%eax
add $0x1,%eax
mov %eax,-0x8(%ebp)

机器语言:

8b 45 f4
83 c0 01
89 45 f8

因为机器是只能做数字计算的,能够让机器去运算的,数字的语言就是机器语言。除此之外的所有计算机语言都是非机器语言。为了让机器可理解,相对于机器语言的高级语言都需要一个转换,从高级、机器不可理解,转换为机器可理解的机器语言,这样的一个转换过程就叫做 编译(Compile),由 编译器(Compiler)来完成。

由 C 转换为 汇编语言 这一过程是由 汇编器(Assembler)来执行的。

C 和 汇编语言 转换为 机器语言 都是由 编译器 来完成的。

 

2、将C语言编译为机器语言的整个过程

 

 

在Linux下,使用gcc编译器:

1、预编译hello.c文件:

gcc -E -o hello.i hello.c

执行成功后,会生成一个新的hello.i 的文件,可以用编辑器(Vim)查看它的内容,这个文件就是经过预编译后的内容。

预编译又称为预处理,是做些代码文本的替换工作。预编译可以处理#开头的指令,比如拷贝#include包含的文件代码,#define的宏定义的替换,条件编译等。

预处理的过程主要处理包括以下过程:

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

处理所有的条件预编译指令,比如 #if  #ifdef  #elif  #else  #endif等;

处理#include预编译指令,将被包含的文件插入到该预编译指令的位置;

删除所有注释 "//" 和 "/**/";

添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号;

保留所有的#pragma编译器指令,因为编译器需要使用它们;

 

通常使用以下命令来处理预处理:

gcc -E hello.c -o hello.i

  参数-E表示只进行预处理,或者也可以使用以下指令完成预处理过程:

cpp hello.c > hello.i  /* cpp - The C Preprocessor*/

  直接cat hello.i 你就可以看到预处理后的代码。

 

2、纯粹的进行编译:

gcc -S -o hello.s hello.i

把.i文件写为hello.c也行,就是跳过手动预编译,直接完成预编译和编译两个过程。这时会得到一个hello.s文件,打开看一下,里面是编译好的适用于当前体系结构的汇编代码。

编译过程就是把预处理完的文件进行一系列的词法分析、语法分析、语义分析及优化后生成相应的汇编代码。

gcc -S hello.i -o hello.s

  或者:

/usr/lib/gcc/i486-linux-gnu/4.4/cc1 hello.c

  注:现在版本的gcc把预处理和编译两个步骤合成一个步骤,用cc1工具来完成。gcc其实是后台程序的一些包装,根据不同参数去调用其他的实际处理程序,比如:预编译编译程序cc1、汇编器as、连接器ld。可以看到编译后的汇编代码(hello.s)如下:

  .file   "hello.c"
    .section    .rodata
.LC0:
    .string "Hello, world."
    .text
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    movl    $.LC0, (%esp)
    call    puts
    movl    $0, %eax
    leave
    ret
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits

  

3、把汇编代码进行汇编可执行:

gcc -c -o hello.o hello.s

把.s文件换成.c也行,就是自动完成预编译、编译和汇编三个过程。现在得到一个hello.o文件,这是一个二进制文件,但不是最后的可执行二进制文件,因为它还缺少最后一步链接处理。

汇编器是将汇编代码转变成机器可以执行的命令,每一个汇编语句几乎都对应一条机器指令。汇编相对于编译过程比较简单,根据汇编指令和机器指令的对照表一一翻译即可。

gcc -c hello.c -o hello.o

或者:

as hello.s -o hello.co

  由于hello.o的内容为机器码,不能以普通文本形式查看(vi打开看到的是乱码)。

 

4、链接

最后对.o文件进行链接,这里就一个.o文件所以简单,经常是需要有多个.o文件需要链接。链接执行:

gcc -o hello hello.o

如果把最后的.o文件写成.c,那就和最开始我们用hello.c编译时示范的那样了。实际上那样是完成了预编译、编译、汇编和链接一连串的过程。

通过调用链接器ld来链接程序运行需要的一大堆目标文件,以及所依赖的其它库文件,最后生成可执行文件。

ld -static crt1.o crti.o crtbeginT.o hello.o -start-group -lgcc -lgcc_eh -lc-end-group crtend.o crtn.o (省略了文件的路径名)

  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM