计算机程序的运行

计算机工作的本质就是程序的运行”

程序是一组计算机能识别和执行的指令,为使计算机按预定要求工作,首先要编制程序,无论是最早的操作系统还是现代操作系统,程序的运行都是计算机工作的本质。早期计算机是单任务执行,由程序员直接编写操作系统可以识别的机器语言,到现在可以实现多道程序并行,并且程序的开发由更利于程序员理解的高级语言编写,源程序在经过一系列翻译过程,变成计算机理解的机器语言,再执行。整个程序执行的过程,需要CPU、内存、程序代码、设备等配合,才能实现程序要表达的功能。

编程语言

编程语言是用来定义计算机程序的形式语言,用来向计算机发出指令。它是一种被标准化的交流技巧,用来向计算机发出指令。一种计算机语言让程序员能够准确地定义计算机所需要使用的数据,并精确地定义在不同情况下所应当采取的行动。

编程语言的描述一般可以分为语法及语义。语法是说明编程语言中,哪些符号或文字的组合方式是正确的,语义则是对于编程的解释。

编程语言俗称“计算机语言”,种类非常的多,总的来说可以分成机器语言、汇编语言、高级语言三大类。

机器语言

机器语言是机器能直接识别的程序语言或指令代码,勿需经过翻译,是电脑的CPU可直接解读的数据。不同的计算机都有各自的机器语言,即指令系统。从使用的角度看,机器语言是最低级的语言。

机器语言是用二进制代码表示的计算机能直接识别和执行的一种机器指令的集合。它是计算机的设计者通过计算机的硬件结构赋予计算机的操作功能。

一条指令就是机器语言的一个语句,它是一组有意义的二进制代码,指令的基本格式如,操作码字段和地址码字段,其中操作码指明了指令的操作性质及功能,地址码则给出了操作数或操作数的地址。

用机器语言编写程序,编程人员要首先熟记所用计算机的全部指令代码和代码的涵义。手编程序时,程序员得自己处理每条指令和每一数据的存储分配和输入输出,还得记住编程过程中每步所使用的工作单元处在何种状态。这是一件十分繁琐的工作。编写程序花费的时间往往是实际运行时间的几十倍或几百倍。而且,编出的程序全是些0和1的指令代码,直观性差,还容易出错。除了计算机生产厂家的专业人员外,绝大多数的程序员已经不再去学习机器语言了。

汇编语言

早期的程序设计均使用机器语言,但是这种即难辨识又难以记忆的机器语言给行业发展带来了障碍。汇编语言应运而生。

汇编语言是一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。在汇编语言中,用助记符代替机器指令的操作码,用地址符号或标号代替指令或操作数的地址。在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令。普遍地说,特定的汇编语言和特定的机器语言指令集是一一对应的,不同平台之间不可直接移植。

汇编语言实际上就是用简短的英文缩写来表示机器语言中的相应指令。由汇编器和链接器处理后,汇编语言就被翻译为机器语言,可由机器来执行。虽然只做了简单的抽象,这已经大大提高了程序的可读性。

汇编语言的另一个特点就是它所操作的对象不是具体的数据,而是寄存器或者存储器,也就是说它是直接和寄存器和存储器打交道,这也是为什么汇编语言的执行速度要比其它语言快,但同时这也使编程更加复杂,因为既然数据是存放在寄存器或存储器中,那么必然就存在着寻址方式,也就是用什么方法找到所需要的数据。

在今天的实际应用中,汇编语言通常被应用在底层,硬件操作和高要求的程序优化的场合。如驱动程序、嵌入式操作系统等。不过,这是市场化的软件行业决定的,如果用汇编语言编写程序,要比高级语言花上几倍甚至几十倍的时间,不如使用高级语言来编写,只要最终结果不比汇编语言编写的差太多,就能抢先一步完成。

迄今为止,还没有程序员敢断定汇编语言是不需要学的,同时,汇编语言是面向机器的程序设计语言,设计精湛的汇编程序员,部分已经脱离软件开发,挤身于工业电子编程中。对于功能相对小巧但硬件对语言设计要求苛刻的行业,如4位单片机,由于其容量及运算,此行业的电子工程师一般负责从开发设计电路及软件控制,主要开发语言就是汇编,C语言只占极少部分。

高级语言

在编程语言经历了机器语言,汇编语言等更新之后,人们发现了限制程序推广的关键因素——程序的可移植性。需要设计一个能够不依赖于计算机硬件,能够在不同机器上运行的程序。这样可以免去很多编程的重复过程,提高效率,同时这种语言又要接近于数学语言或人的自然语言。这样就诞生了高级语言,高级语言主要是相对于机器语言、汇编语言而言的,它是较接近自然语言和数学公式的编程,基本脱离了机器的硬件系统,用人们更易理解的方式编写程序。

高级编程语言作为一种通用的编程语言,它的语言结构和计算机本身的硬件以及指令系统无关,它的可阅读性更强,能够方便的表达程序的功能,更好的描述使用的算法。同时,它更 容易被初学者所掌握,很容易学习。而且容易学习掌握。但是高级编程语言因为是一种编译语言,所以他的运行速度比汇编程序要低,同时因为高级语言比较冗长,所以代码的执行速度也要慢一些。

高级编程语言,作为用户层面的编程工具,用户并不需要去了解硬件的结构,而是去用逻辑的语言去实现想要的目标,但是因为高级编程语言的架构高于汇编,所以不能编写直接访问硬件资源的系统程序,因此,高级编程语言必须要调用汇编语言编写的程序来访问硬件地址。

高级语言并不是特指的某一种具体的语言,而是包括很多编程语言,如流行的java,c,c++,go,python等等,这些语言的语法、命令格式都不相同。使用高级语言编写的程序称之为源程序。

运行程序

为了使计算机程序得以运行,计算机需要加载代码,同时也要加载数据,然后由处理器执行指令。整个过程可以总结为编译、链接、装载、执行。如下图展示了C语言程序的运行过程。

编译

编译过程又可以被分为两个阶段:编译、汇编。

编译是指编译器读取字符流的源程序,对其进行词法与语法的分析,将高级语言指令转换为功能等效的汇编代码。

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

链接

链接的主要内容是将各个模块之间相互引用的部分处理好,使得各个模块之间能够正确地衔接。链接又分为静态链接和动态链接:

静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大;

动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。

装载

程序在经过链接后,得到了可执行文件,下一步就需要将可执行程序加载到内存中。

由于现代操作系统均采用分页的方式来管理内存,所以操作系统只需要读取可执行文件的文件头,之后建立起可执行文件到虚拟内存的映射关系,而不需要真正的将程序载入内存。

运行

加载器将可执行目标文件中的代码和数据从磁盘复制到内存中,然后通过跳转到程序的第一条指令或入口点来运行程序。在程序的运行过程中,CPU发现有些内存页在物理内存中并不存在并因此触发缺页异常,此时CPU将控制权限转交给操作系统的异常处理函数,操作系统负责将此内存页的数据从磁盘上读取到物理内存中。数据读取完毕之后,操作系统让CPU jmp到触发了缺页异常的那条指令处继续执行,此时指令执行就不会再有缺页异常了。

《Java内存管理-程序运行过程》 aflyun,公众号:Java编程技术乐园Java内存管理-程序运行过程(一)


  1. https://blog.csdn.net/kidthephantomthiefI/article/details/77163685
  2. https://tech.meituan.com/2015/01/22/linker.html
  3. http://www.ruanyifeng.com/blog/2014/11/compiler.html
  4. https://www.nosuchfield.com/2018/11/23/Program-compilation-linking-loading-and-running/

原文发布于微信公众号 - BanzClub(banz-club)

原文发表时间:2019-06-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券