《深入理解计算机系统 第3版》学习笔记——第7章 链接(编译器驱动程序)

编译器驱动程序

        一个C工程源文件必须经过编译才能生成可执行代码。作为学生,我大多时候都是在Windows下一键编译我的程序,所以写了很多代码的我几乎不了解自己的代码是如何编译成可执行程序的。

        编译驱动程序在编译的过程中会依次调用语言预处理器(cpp)、编译器(cc1)、汇编器(as)和链接器(ld),这里主要总结这几个工具的作用。以下图两个C语言文件为例:

                

      这个示例程序由两个源文件组成,main函数初始化了一个整数数组,然后调用sum函数完成数组元素求和。如要用GNU编译系统完成这个程序的编译,我们需要通过在shell中输入下列命令来调用GCC驱动程序:

      

gcc -Og -o prog main.c sum.c
      这样编译器就会把这两个源文件编译成一个名为prog的可执行文件。从main.c和sum.c到prog文件演变的具体步骤如下图所示:

                     

      可以将这个过程中的每一步分开执行,这样可以较为清晰地了解编译器驱动程序运行流畅,并能观察中间文件。

      1.首先调用C预处理器把main.c和sum.c分别翻译成ASCII码的中间文件main.i和sum.i文件。这里主要是处理包含的头文件和宏定义等等预处理操作。执行如下命令:      

cpp main.c main.i
cpp sum.c sum.i

      2.可以看到工程目录里新增了main.i和sum.i两个文件。接下来调用C编译器,将.i文件翻译成汇编语言文件,即.s文件。我对Linux下命令执行不是很了解,导致按照书上执行时没有成功,提示未找到‘cc1’命令。于是我把/usr/lib/gcc/i686-linux-gnu/4.8/目录下的.cc1文件复制到了工程目录中。执行如下命令成功调用了C编译器:      

./cc1 main.i -Og -o main.s
./cc1 sum.i -Og -o sum.s
      3.执行完上述命令之后工程目录中便多了main.s和sum.s两个文件,打开着两个文件可以看到源程序文件内容已经被翻译成了汇编语言。接下来调用汇编器,将main.s和sum.s文件翻译成可重定位目标文件main.o和sum.o文件,调用如下命令:

      

as -o main.o main.s
as -o sum.o sum.s
      4.得到了可重定位目标文件之后,需要将这二者组合起来。这个过程由链接器程序来完成,调用链接器程序命令:

      

ld -o prog -e main main.o sum.o
      上述命令已经把可重定位目标文件通过链接器组合成了一个名为prog的可执行程序,至此就完成了一个简单工程的编译工作。要执行这个可执行程序则需要将其中的代码和数据复制到内存中,并将控制转移到这个程序的开头。只需调用如下命令:

      

./prog

        经过测试发现程序执行出现段错误,猜测可能是链接过程有些问题。待后续学习完链接器相关知识,弄明白链接具体工作方式之后再另外专门写一篇相关文章。

        总结:本小节主要介绍了一个C语言工程中,编译器是如何将C源文件一步一步翻译并且链接成可执行文件的。在平时的学习工作中,我总是使用开发工具中的一键编译和运行,虽然效率高,但是却并不知晓这其中隐含了多少执行细节。学习本节知识让我对程序执行过程有了更深入的了解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值