用自己的话解释代码运行的底层逻辑

用自己的话解释代码运行的底层逻辑

前言

保老师说,学东西一定要形成自己的体系。大概这样用起来的时候才得心应手。我看回第一次课的PPT,有一页简单的C++代码,保老师当时为了展示他格物致知的理念,给我们解释了代码的底层逻辑。
image-20230202223448761
现在一个学期过去了,我学了计算机原理和数字电路,但是看回这页代码似乎还是不能解释其运行的底层原理。从中可见我学习的不足,还没学到成体系的水平。不过,我相信自己确实是有一点知识储备的,所以应该可以比较粗略简单地将其用自己的话解释一下。下面就作一个小尝试。

总体的观察

这整个过程是系统的,复杂的,所以有必要先进行一定的观察和猜想,从而构建模糊的框架和大致的方向。

首先,要搞清楚运行代码的计算机意味着什么。我想计算机是人类最高智慧的结晶,不是一种自然的产物。也就是说,计算机也是人构建出来的,它本来不在自然界中存在。但是在长期的发展中,计算机也逐渐有了固定的形态和样式,并积累了大量的技术,所以我们现在才得以学习计算机原理,并且用这种人构造出来的机制去完成一些事情。所以,我将要做的是用某种人们普遍认可的机制去解释这个代码运行并产生结果的过程。可惜我的见识很短,而且现在也没有充足的时间给我去研究大量资料,因此只考虑我所知道的两种计算机模式(我是在《逻辑的引擎》这本书中了解到的):图灵式的和冯诺依曼式的。更可惜的是,我对图灵式的计算机几乎一无所知,客观来说这种计算机并没有流行开来,大概只在实验室存在过,所以下面我将采用在计算机原理课程中接触到的冯诺依曼式的计算机来解释这段代码,更确切的说法是采用现代化的冯诺依曼式的计算机。

而且我也不会具体到其在某种型号的计算机上这段代码的运行机制,而是着重于一般性的原理,因为以目前的能力我只能解释到这样的抽象层次了。但是无论我采取怎样的抽象层次,计算机的结构层次是不变的,如下图:
image-20230203101548595
上面的那段代码是用C语言写的,它属于高级语言,对应上图最顶层。计算机是不能直接理解执行高级语言的,即底层机器并不能理解并执行C语言,而是要从上往下一层一层地按次序执行。当然实际上这只是总体上的看法,仔细看的话会复杂很多,比如你要给计算机一个开始运行信号,计算机才会着手执行代码,然而这个信号一般是输入给操作系统,然后操作系统又会用机器语言对硬件指挥,让硬件开始读取上面那段C语言代码。这样做好了预备工作,才正式从高级语言开始往下执行。所以从某种角度来看,这并不是一个严格从最顶层出发从上到下按次序执行的过程。不过这种对计算机系统划分层次结构有助于理清结构逻辑脉络,方便人从宏观上设计和理解计算机系统的运行机制,它是计算机发展史上最重要的思维之一。实际上我已经有点底气不够,因为我对计算机的汇编原理和操作系统几乎一无所知,到下学期我才开始学习操作系统。所以对汇编语言和操作系统的层次我会简略一点,甚至是跳过。

直接对C语言的代码进行观察,就可以发现其冯诺依曼的影子。上面的代码已经包含了程序和数据,都是用“相等地位”的语句来表示。而它们实际也是以同等地位存储在存储器里面的01串。

预备工作

我们默认代码本身就已经在存储器里面。不过存储器是十分模糊的概念,计算机中有各种各样的存储器。在这里,我默认代码是存储在辅存中的01串。

而且假设前面已经给了开始信号,而不管它是用户用键盘输入的,还是前面运行的程序触发的。在这里,开始信号本身就是“高级语言”,或者说它将触发一段预备工作的程序,除此之外,它还应包含基本的信息:将要运行的程序的存储位置。我们不妨假设信号是这样的:开始编译并运行在xxx位置的C语言代码。

有了开始信号,操作系统将指挥硬件执行一系列程序:将辅存的代码片段复制到主存,运用编译程序将主存中的C代码翻译成汇编语言,再将汇编语言翻译成机器语言,底层硬件将用微指令解释机器语言,并执行一系列机器语言。

如果想具体理解,我们就要想到底层的一切都是01串。虽然甚至还没开始编译,但是预备工作在软件层面就已经复杂得让我头皮发麻。我就忽略操作系统是如何触发一系列程序并产生机器语言的。

我们先来看复制操作,辅存到主存的复制是跨硬件的复制,要先对主存的状况有了解,然后才能确定复制的位置和时间。当确认了主存能正常工作,而且已经做好“写准备”,就可以通过总线传输数据。由于这时候只是复制,机器并不知道这些01串是什么,所以还要确定什么时候结束。在这里我就应经十分空虚,因为现在似乎遇到了两种方式,第一种是先把整个代码的01串复制到主存,然后才开展下一步,这样需要知道这段代码在开头和结尾的位置;第二种是把对应一个字符的01串复制到主存,已经可以对这个01串进一步送到CPU来解析它,也就是一边复制一边已经着手开始其他程序的执行,这样不需要知道这段代码在结尾的位置,因为当解析到结束的信号,就可以停止了。为了更加明晰,我在这里采用第一种方式。复制过程也需要复杂的程序,因为不但需要协调各个硬件,而且面临有限的参差不齐的时空资源:总线的位宽是有限的,传输速度是有限的,辅存的读速度和主存的写速度是不一致的等等。除此之外,还有物理层面和存储方式的考虑:比如虽然01在物理本质上都是高电平低电平,但是辅存和主存在物理结构上是有差异的,可能用不同的物理介质来存储,有着不同的电压。比如存储阵列的排布不一样,即使是顺序存储,也要确定是以怎样的顺序。这些交给辅存和主存内部的芯片去完成,然后交给主板的芯片去安排。从总体上看,辅存会多次接收地址信号,多次发送数据,然后主存也会多次接收地址信号,多次接收数据。

用自己的话解释代码运行的底层逻辑
http://thinkerhui.site/2024/02/03/用自己的话解释代码运行的底层逻辑/
作者
thinkerhui
发布于
2024年2月3日
许可协议