Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1425240
  • 博文数量: 842
  • 博客积分: 12411
  • 博客等级: 上将
  • 技术积分: 5772
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-14 14:43
文章分类

全部博文(842)

文章存档

2013年(157)

2012年(685)

分类: C/C++

2012-06-26 11:40:28



当我们进行编译的时候,要使用一系列的工具,我们称之为工具链。
其中包括:
预处理器CPP
编译器gcc/g++
汇编器as
连接器ld

一个C/C++程序编译过程包括下面几个阶段:
1.预处理         预处理器cpp将对源文件中的宏进行展开。
2.编译 gcc将c文件编译成汇编文件。
3.汇编 汇编器as将汇编文件编译成机器码。
4.连接 链接器ld将目标文件和外部符号进行连接,得到一个可执行二进制文件。

下面以一个很简单的hello.c来探讨这个过程。
#include

#define BUFSIZE 1024

int main(int argc, char *argv[])
{
char hello[BUFSIZE] = "Hello my friend!";
printf("%s\n", hello);

return 0;
}

1.预处理(预处理器 cpp):
        gcc会首先调用CPP进行预处理:
[butbueatiful@xt myhello]$ cpp hello.c > hello.i
[butbueatiful@xt myhello]$ gcc -E hello.c > hello.i

        我们用vi hello.i查看hello.i的内容如下:
......
int main(int argc, char *argv[])
{
 char hello[1024] = "Hello my friend!";
 printf("%s\n", hello);

 return 0;
}
        我们可以看到,文件中宏定义BUFSIZE出现的位置被1024替换掉了,其它的内容保持不变。

2.gcc将c文件编译成汇编文件(编译器 gcc):
        接下来gcc会执行
[butbueatiful@xt myhello]$ gcc -S hello.i #得到汇编文件hello.s

3.as将汇编文件编译成机器码(汇编器 as):
        [butbueatiful@xt myhello]$ as hello.s -o hello.o
        得到输出文件为hello.o
        hello.o中为目标机器上的二进制文件
        用nm查看文件中的符号:
[butbueatiful@xt myhello]$ nm -a hello.o
        输出如下:
00000000 b .bss
00000000 n .comment
00000000 d .data
00000000 n .note.GNU-stack
00000000 t .text
00000000 a hello.c
00000000 T main
 U puts

        既然已经是二进制目标文件了,能不能执行呢?
[butbueatiful@xt myhello]$ chmod +x hello.o
[butbueatiful@xt myhello]$ ./hello.o
-bash: ./hello.o: cannot execute binary file
        其实这时puts前面的U表示这个符号的地址还没有定下来,T表示这个符号属于代码段。ld连接的时候会为这些带U的符号确定地址。

4.链接(链接器 ld):
        连接需要指定库的位置。通常程序中会有很多的外部符号,因此需要指定的位置就会很多。
        不过,我们只需要调用gcc即可,ld会自己去找这些库的位置。
        [butbueatiful@xt myhello]$ gcc hello.o -o hello #得到可执行文件hello
阅读(1011) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~