01程序编译过程分析,预处理,编译,汇编,链接
前言
我们大多数开发人员在编写完程序之后都会通过相应的IDE执行编译的操作,将所编写的源代码转换成计算机可以识别并执行的文件。这个从源代码转换成可执行文件的过程有相应的IDE帮助我们完成,很多朋友对于这个过程都不太熟悉,今天我们就一起探讨下可执行文件的生成过程,这个过程又叫做程序的编译与链接。
一:hello word由浅入深
对于程序员开发者来说,hello world程序的编写,大家闭上眼睛都能写出来,今天我们就以hello world为例来探讨一下可执行文件的生成过程,废话不多说,下面就是hello word的源码
上面代码的功能就是输出hello,word。然而计算机不可能直接执行hello world.c下面我们用一张图来讲一下hello world.c是如何被被执行。
从上面的图中,我们大致可以看到,hello.c要想变成计算机可以执行的hello(可执行目标文件)需要经过预处理,编译,汇编,链接等步骤,这些步骤主要是干什么的,有各自有什么作用,我们下面一一进行分析。
二:预处理
首先我们先来看一下预处理的执行命令
– $gcc –E hello.c –o hello.i
– $cpp hello.c > hello.i
预处理执行的功能:
- 删除“#define”并展开所定义的宏
- 处理所有条件预编译指令,如“#if”,“#ifdef”, “#endif”等
- 插入头文件到“#include”处,可以递归方式进行处理
- 删除所有的注释“//”和“/* */”
- 添加行号和文件名标识,以便编译时编译器产生调试用的行号信息
- 保留所有#pragma编译指令(编译器需要用)
经过预编译处理后,得到的是预处理文件(如,hello.i) ,它还是一个可读的文本文件 ,但不包含任何宏定义,上面所说的第3条插入头文件到“include”处,可以理解为将头文件里面的内容进行展开,下面用一张图来进行描述
三:编译
编译过程就是将预处理后得到的预处理文件(如 hello.i)进行词法分析、语法分析、语义分析、优化后,生成汇编代码文件。用来进行编译处理的程序称为编译程序(编译器,Compiler)
编译命令
– $gcc –S hello.i –o hello.s
– $gcc –S hello.c –o hello.s
– $/user/lib/gcc/i486-linux-gnu/4.1/cc1 hello.c
上面3条编译指令表明,我们可以通过.i文件输出汇编文件.s同时也可以直接将.c文件编译成.s文件。第3条指令则是通过编译器直接执行,与前两条执行效果一样。gcc命令实际上是具体程序(如ccp、cc1、as等)的包装命令,用户通过gcc命令来使用具体的预处理程序ccp、编译程序cc1和汇编程序as等
经过编译后,得到的汇编代码文件(如 hello.s)还是可读的文本文件,CPU无法理解和执行它,不要着急,我们接下来看下一步汇编命令的执行过程
四:汇编
首先我们先了解下汇编代码文件(由汇编指令构成)称为汇编语言源程序,其实就是上面编译过程结束之后生成的.s文件,这个文件就是汇编代码文件,改文件是有一条条汇编指令构成,汇编的作用就是讲这一条条汇编指令转换成对应的机器执行。
• 汇编程序(汇编器)用来将汇编语言源程序转换为机器指令序列(机器语言程序)
• 汇编指令和机器指令一一对应,前者是后者的符号表示,它们都属于机器级指令,所构成的程序称为机器级代码,汇编的过程比较简单,只需要将相应的汇编指令翻译成对应的机器指令即可,没有什么复杂的变化。
汇编命令
– $gcc –c hello.s –o hello.o
– $gcc –c hello.c –o hello.o
– $as hello.s -o hello.o (as是一个汇编程序)
汇编结果是一个可重定位目标文件(如,hello.o),其中包含的是不可读的二进制代码,必须用相应的工具软件来查看其内容
五:链接
哇,经过了上面一系列的流程,终于到了最后一步,我们的hello world 终于要完成了,下面我们就来看下最后一步链接的处理吧。
预处理、编译和汇编三个阶段针对一个模块(一个*.c文件)进行处理,得到对应的一个可重定位目标文件(一个*.o文件),但是在程序的编写过程中,我们都是多个.c文件的,这样经过上面的预处理,编译汇编的过程之后我们得到的也是多个.o(可重定位目标文件),但是我们在最终执行的时候是只有一个可执行文件的,这个过程就是连接的目的了。
链接过程将多个可重定位目标文件合并以生成可执行目标文件,大家可以看下最初时候的图,在最后一步连接的过程中,我们不只是要hell.o而且还需要printf.o(代码中含有printf函数),链接就是将这连个.o合并为一个生成可执行目标文件
链接命令
– $gcc –static –o myproc main.o test.o
– $ld –static –o myproc main.o test.o
–static 表示静态链接,如果不指定-o选项,则可执行文件名为“a.out”
408计组考研:计算机的层次结构知多少
现代计算机是一个硬件与软件组成的综合体
- 第一级是微程序机器层,这是一个实在的硬件层,它由机器硬件直接执行微指令
- 第二级是传统机器语言层,它是一个实际的机器层,由微程序解释机器指令系统
- 第三级是操作系统层,它由操作系统实现。操作系统程序是由机器指令和广义指令组成的,这些广义指令是为了扩展机器功能而设置的,是由操作系统定义和解释的软件指令,所以这一层也称为混合层
- 第四级是汇编语言层,他为用户提供一种符号化的语言,借此可编写汇编语言源程序
- 第五级是高级语言层,它是面向用户的,是为方便用户编写应用程序而设置的
其实在高级语言层之上,还可以有应用层,它由解决实际问题的程序组成,比如word,chrome等等。
对于某层的使用者来说,它只关心该层即可,而无需关心下一层的实现
- 需要注意的是在许多情况下,计算机的某些功能既可以由硬件实现,也可以由软件来实现,因此硬件和软件没有严格的界限
软件是人们事先编制的具有各类特殊功能的程序,他们通常存放在计算机的主存或外存中,按其功能可以分为以下两类
系统软件是一组保证计算机系统高效,正确运行的基础软件,通常作为系统资源提供给用户使用。系统软件主要有操作系统(OS)、数据库管理系统(DBMS)、语言处理程序,分布式软件系统、网络软件系统、标准库程序、服务型程序等。
应用软件是指用户为解决某个应用领域中的各类问题而编制的程序、如各种科学计算类程序,工程设计类程序,数据统计与处理程序。
注意:汇编程序是由汇编语言编写而成的程序,与编译型程序和解释型程序完全不是一个概念
- 解释程序:它将源语言书写的源程序作为输入,解释一句就提交给计算机执行一句,并不形成目标程序
- 编译程序:把高级语言源程序作为输入,进行翻译转换,产生出的机器语言作为目标程序,然后让计算机去执行这个目标程序,得到计算结果。
对于编译程序来说,它产生目标代码的执行速度要比解释程序的执行速度快,比如循环,解释程序需要不停的重复解释,而编译程序只需要一次即可。
- 机器语言:用二进制“0”和“1”描述不同指令,编程人员需要记忆每一条指令的二进制编码。其优点就是计算机可以直接识别并执行
- 汇编语言:其实质和机器语言是相同的,都是直接对硬件操作,只不过指令采用了英文缩写的标识符,更容易识别和记忆。汇编语言的程序必须经过一个称为汇编程序的系统软件的翻译,将其转化为机器语言,才能在计算机的硬件系统上运行
- 高级语言:需要经过编译程序编译成汇编语言程序,然后经过汇编操作得到机器语言程序。其优点在于方便编程人员写出解决问题的方案和解题过程。
- 计算机体系结构:研究的是机器语言程序所见的计算机系统的属性概念性的结构与功能特性(指令系统、数据类型、寻址技术、I/O机理)。也就是说是如何设计硬件与软件之间的接口,举例:无乘法指令
- 计算机组成原理:研究的是计算机体系结构体现出来的属性,对于程序员来说是“透明的”。也就是说是如何使用硬件实现所定义的接口,举例:如何实现乘法指令
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。