程序运行过程概览(转+修订)

转自:https://roobtyan.blog.csdn.net/article/details/80338802

for more detailed demonstration of program execution and roles of each component, see https://blog.csdn.net/maxzcl/article/details/114822868

大家都知道,操作系统、计算机组成原理、数据结构与算法、计算机网络、被称作计算机四大基础课。不但是计算机专业考研的四门专业课,而且是每一个程序员必须掌握的内容。其实大家能够看到,为什么绝大多数企业都不想招培训班出来的“程序员”,其中有一个非常重要的原因就是他们的计算机基础知识过于薄弱,也就是上面说到的四门课程。
最近发现,研究计算机组成原理其实是非常有意思的一件事情。为什么这样说呢?不知道你有没有想过,当你写完一个程序之后(以c语言程序为例子),源代码通过编译器编译成汇编语言,然后汇编语言再通过解释,成为机器语言,经过黑盒子(你不知道的方式),得到你想要的结果。你只是看到了程序输出的最终结果,却不知道为什么能够得到你想要的最终结果,对吧。
那么,你有没有想过,一个程序究竟是如何跑起来的呢,究竟在计算机的最底层经过了怎样的执行过程呢?这就是我的这篇博文想要展示给大家的。

概述

我们知道,计算机是由软件和硬件共同组成的。没有硬件,软件就没有用武之地;没有软件,硬件就只能是一堆废铁。
而软件又分为两类:

  • 系统软件
  • 应用软件

其实这是从宏观上的封装和层次划分,对相关的内容没有了解的开发者理解起来可能会有些难度,不过这不是我们今天的重点。
我尝试着从程序员的视角来给大家分析一下,一个程序的完整运行过程。

计算机如何才能执行程序?

还是接着从序言的部分说起。
我们所用的语言,不论是C语言、Java还是其他的什么语言,都是属于高级语言。而高级语言编写的程序,计算机肯定是不能直接执行的,因为计算机只能识别0和1。为了能够让计算机执行高级语言编写的程序,需要经过下面的这些步骤:

这里写图片描述

the assembler (platform based) converts the assembly code to machine bytes.

首先,高级语言程序通过编译器编译,成为汇编语言;然后这个汇编程序再经过一个不知道的步骤成为机器语言。
究竟是经过了什么样的过程,汇编语言才会变成机器语言呢?这需要一个东西介入。

The following statements are incorrect and was not updated after being pointed out to the author somewhat 2yrs ago, hence:
就是我们刚才提到的系统软件,泛泛的讲就是操作系统。==> no, it's the assembler
操作系统是负责和底层的硬件进行交互的,==> correct, OS is an application developed based on the CPU/Comp Architecture to coordinate other higher level applications

也就是说,这个把汇编语言变成机器语言的东西,只能是操作系统。==> wrong, faulty logic

the OS encapsulates the underlying hardware structure, but it has nothing to do with assembly to machine bytes conversion. ==> that's done by the assembler, mostly independent of the OS, except when dealing with OS variance in terms of underlying representation of data.

for more about CPU instruction set and OS see: https://blog.csdn.net/zhongjin616/article/details/18765301

in short:

CPU architecture implements instruction set;

assembler compiles OS into machine bytes to execute instruction set to operate the CPU.

如果你下过jdk,如果你够细心,你会发现有arm、i586、x64等类型。这是为什么呢?就是因为计算机硬件或者说芯片是不基于不同的指令集的,==> true

那么相同的汇编程序,经过操作系统,转换成对应的机器语言肯定也是不同的。顺便说一下,我们今天的主题是机器语言在底层硬件的流转。

经过这里,我们成功得到了机器语言。当操作系统将汇编程序解释成对应的指令集的机器语言之后,就要看硬件部分究竟是如何处理机器语言的了。
我们前面说的指令系统,就是解释执行机器语言的,这样看来,机器语言实际上就是微指令。
总的来讲,指令系统也好,微指令系统也好,其功能就是来控制硬件执行的。所以,在指令系统得到了机器语言(微指令)后,对硬件进行的相关操作,才是能使我们程序运行的根本原因。
到这里,我们知道了

  • 只有机器语言计算机才能够识别并执行
  • 相同的汇编语言程序在不同指令集平台下生成的机器语言是不同的
  • 机器语言就是微指令
  • 微指令系统的作用就是指挥计算机的各部分工作

好了,只有知道了这些内容,我们才能进行后续的东西。

现代计算机的结构

刚才说了,微指令系统是指导计算机硬件运行的。那么,这些计算机硬件都包括什么呢?
众所周知,现代计算机是在冯若依曼体系计算机的基础之上发展起来的,在开始我们的讲述之前,了解下冯若依曼计算机的结构还是很有必要的。

for detailed explanation, see: 冯.诺依曼计算机结构要点

for more compact explanation: see 冯诺依曼结构概述

这里写图片描述

(graph info:  冯若依曼结构计算机工作原理及层次结构分析 www.cnblogs.com)

  • 运算器:进行算数逻辑运算
  • 存储器:存放数据以及程序
  • 控制器:控制程序、数据、运算处理结果
  • 输入设备:将指令转换成机器可识别的机器语言
  • 输出设备:将指令转换成人可以识别的内容

可以看到,冯诺依曼结构的计算机是以运算器为核心的,而现在的计算机则是以存储器为核心的。这其中的原因暂不表述,有兴趣的可以查阅相关资料。
虽然现代计算机是以存储器为中心的,但是还是基于冯若依曼体系的。冯若依曼体系计算机的特点现代计算机都有。
现代计算机的结构是这样的:(纯手画,略丑,见谅)

这里写图片描述

主机中由主存储器和CPU组成,再有就是外部的IO设备,现代的计算机结构虽然和冯诺依曼结构有些不太一样,但是仍是基于冯诺依曼结构的。
注意:这里面有一个非常重要的内容,那就是指令的格式。
刚才说了,指令其实就是机器语言,那么,一条机器语言的格式究竟是什么样子呢?是这样的:机器语言或者说指令,分为两个部分,一部分是操作码,另外一部分是数据地址。
比如说,我现在要做的操作是将0000111011地址的数据存到存储器之中,那么操作就是这样的:

这里写图片描述

前面的是指令码,后面的是地址码。我们发现,在这种情况下,地址码和指令码都是二进制的数据,处于同样的地位,这也是冯若依曼体系计算机的一大特点。
好了,了解了以上内容,我们马上就能看到一个程序究竟是如何跑起来的了。

计算机的工作过程

我们上面看到了现代计算机的体系结构:存储器、算数逻辑(运算器)、控制单元(控制器),当然还有IO设备。
现在,我们知道了微指令(机器语言)就是在这些部件之中游走,完成程序的操作,但是具体是如何游走的,或者说微指令系统是如何执行机器语言的,我们仍然不知道。
就我们目前掌握的内容来看,只能了解到这个层次了,若要是想再进一步,我们对更底层的东西还是要再进行分解。

存储器

下图是存储器的基本结构:

这里写图片描述

看了这张图你可能会-有很多的疑问,比如说存储体是个什么东西?其实,再细分的东西,这篇博客就暂不作介绍了,因为并不影响我们的阅读,如果你感兴趣的话,欢迎持续关注我的博客,我会把漫谈计算机组成原理作为一个系列的文章,来仔细为大家讲述计算机组成的奥秘。
对于存储体,你只需要知道这就是个存储的部件即可,可以存放数据。
MAR:存储器地址寄存器;MDR:存储器数据寄存器。
所谓的寄存器,就是临时存放的意思。所以,上面两个就是临时存放地址和数据的地方。至于为什么这么叫,再最后一部分你会非常明白的,这里我就先不做介绍,你只需要知道有这么个东西就行了。

运算器

这是运算器的结构图。

这里写图片描述
我们知道,运算器就是做逻辑运算的,比如说加减乘除等运算,简而言之就是做数据处理的。
图中显示的什么累加寄存器、乘商寄存器等这些东西,不必让这些名词困扰你。我来简单说一下,累加寄存器就是差与和存放的地方。那么你就会问,为啥有差、和却叫累加寄存器呢?那是因为在计算机中是没有减法的,如果有,那就是加上一个负数而已,只能是这样。至于乘商寄存器肯定就是放乘积和商的地方了。
至于X,这货叫操作数寄存器。比如说X+3。X是放到ACC中的,这个后面的加数就是放在X这个寄存器中,等待着操作的进行。

控制器

控制器的作用:解释指令,保证指令有序执行。
控制器的结构如下:

这里写图片描述

刚才我们讲,再冯诺依曼体系中,指令和数据是以同等的地位存在于系统之中的,也就都是二进制。你也看到了一条指令的格式。地址码指向的是IO设备的地址,而控制码呢?计算机是如何知道这条指令要执行的是加法操作还是乘法操作呢?实际上,操作码就是存放在CU控制单元之中的。指令寄存器会对CU控制单元发出请求,得到的就是具体的操作。
PC的作用又是什么呢?它的作用实际上是执行完当前指令后,自动加一。也就指向了下一个地址,那里又存放着一条指令,然后继续这个过程。

主机完成指令的过程

好了,终于走到了最后一部分。
在前面的几个过程中,你了解到了现代计算机的每一个部件的组成以及具体功能,在知道了这些内容后,下面的东西理解起来是会很简单的。在最后的这一部分,我会举出两个具体的例子,让你知道程序代码最终形成的机器语言究竟是如何运行的。

取数指令

描述:简单的讲,就是把一个数取出,存到ACC(一般加法操作时,ACC就是作为被加数)中的具体过程。先来看下面的这张图,最好结合着我下面的介绍看。

这里写图片描述

  • 1.程序计数器+1,开始指向下一个地址。
  • 2.存储器地址寄存器中存放着下一个地址,根据这个地址(地址寄存器的名字来历),指向存储体中的指令数据。
  • 3.从存储体得到数据,存入数据寄存器(数据寄存器的名字就是这么来的)
  • 4.得到指令,格式为指令码+操作码(当前操作就是:取数操作-地址),指令写入IR指令寄存器中。
  • 5.指令寄存器询问CU控制单元当前是何种操作,得到取指令操作的回复
  • 6.指令中的数据地址存入地址寄存器
  • 7.通过地址寄存器得到存储体中当前地址存储的数据
  • 8.得到的数据存入数据寄存器中
  • 9.数据寄存器中的数据写入ACC,完成整个操作
  • 10.PC程序计数器+1,开始新一轮的判断。

有了这个,相信你已经对整个操作过程有了很深刻的理解,下面我们再来一个例子,加深理解。

ax^2+bx+c程序运行过程(程序代码已经成为了机器语言)

  • 1.程序由IO设备送至计算机
  • 2.PC+1,得到程序首地址
  • 3.程序开始启动
  • 4.取数指令:PC–>MAR–>存储体–>MDR–>IR(指令寄存器)
  • 5.分析指令:取出指令寄存器中的操作码,送入CU控制单元进行分析,得到指令意义
  • 6.执行指令:取出IR中的地址码–>MAR—>存储体–>MDR–>ACC
  • 7.PC+1=PC,得到新的地址
  • 8.取数指令:PC–>MAR–>存储体–>MDR–>IR(指令寄存器)
  • 9.分析指令:取出指令寄存器中的操作码,送入CU控制单元进行分析,得到指令意义
  • 10.执行指令:取出IR中的地址码–>MAR—>存储体–>MDR–>X

……
最终出现结果
程序执行完毕
好了,进行到这里,我们的漫谈计算机组成原理的第一篇文章就算是结束了。如果大家发现我的博客存在问题,或者大家有什么疑问的地方,欢迎私信我,欢迎志同道合的伙伴联系我!邮箱:roobtyan@aliyun.com
————————————————
版权声明:本文为CSDN博主「Roobtyan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yanmiao0715/article/details/80338802

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值