程序员应知系列 - CPU执行原理

任何计算机系统的真正复杂性都存在于处理器中,但是您知道它是如何工作的吗? 我是说它到底是怎么运作的?您编写的代码如何变成可以完成某些工作的东西? 当您知道CPU如何工作时,就知道不是魔术了 - 而是“提取”和“执行”的问题。

到目前为止,我们已经研究了计算机的整体工作原理,尤其是内存原理。内存是一种设备,当给定一个输入时,它会自动产生一个关联的输出 - 读取或自动存储输出。内存原理和内存机制令人着迷,但我们还需要更多的东西,需要一些可以利用内存执行指令的东西 - 我们需要处理器。

处理器是另一个难度级别。

处理器就是计算机

这一断言的有效性确实没有问题。

如果您不相信我,请尝试在Mac上运行为PC编写的程序。

关键在于,具有不同处理器的计算机是不同的–具有相同处理器的计算机只是更快或更慢。

内存管理和缓存的细节可能令人印象深刻,但任何计算机系统的真正复杂性都存在于处理器中,现在是时候更仔细地研究它是如何完成它所做的事情了。

即使你认为你已经知道了,你仍然可能会发现这个解释很有趣。原因是很多书和课程并没有告诉你全部。它们戛然而止,让你觉得处理器很神奇,即使你知道它应该如何工作的大致轮廓。

在其他地方,我们已经发现处理器和内存之间的紧密联系构成了计算机。当处理器将地址放置在地址总线上时,将选择一个特定的存储位置,然后将数据存储在数据总线上,或者将存储的数据放置在数据总线上的位置。

请注意,这不是魔术。没有一个小人儿住在里面通过地址查找特定的内存位置,然后为CPU检索内容。这个动作就像锁上的钥匙一样自动。CPU把地址放在地址总线上,它选择并激活一个特定的内存位置。读/写线设置内存位置的行为,它要么将其内容放在数据总线上,要么“锁存”或存储数据总线上的内容。

一切都是全自动的。

程序计数器

这很可能是计算机的主要工作原理,但是却忽略了处理器对数据的实际“处理”。

毕竟它被称为“处理器”,因此大概不仅仅是存储和检索位模式。我们已经知道如何使用二进制模式来表示数字,并且我们知道如何使用布尔逻辑对数字进行加减运算。

但这只是CPU处理的一部分。当您第一次开始考虑处理器的工作原理时,通常会把重点放在算术上。原因是我们经常错误地将计算机视为“计算机”,但是在大多数情况下,计算机实际上是在做除算术之外的事情。

一旦您开始更仔细地观察,魔术似乎更多地与这块硅片(或其他任何东西制成的CPU)如何执行程序中的命令有关。它究竟如何看待程序中的下一条指令,弄清楚它的含义,然后安排不可变的硬件来执行该指令?软件可能是软的,但硬件是固定的,它不会因为指令的要求而改变。

再有一种趋势是人们倾向于认为一个小人儿坐在那里等待处理器的下一条指令出现,然后执行它所命令的任何事情。当然,这不是它如何发生的,它就像记忆的存储和检索一样是自动的。

处理器执行的“技巧”看似非常复杂,但这全都是基于从简单和非常常规的基础上构建复杂的事物 - 但是,对于计算机而言,这不总是这样的原则吗?

处理器需要的第一件事是用某种方法来跟踪它在程序中到达的位置。这使用了一个独立的内部内存位置,通常称为“程序计数器”或PC(Program Counter) – 注意它不统计程序数量!出于历史原因,处理器内的所有内部存储器位置都称为“寄存器”,表示它们通常比简单的存储器位置功能多一点。例如,PC寄存器有可以执行两种操作。可以将其初始化为设定值,也可以将其递增,即它可以给其中存储的值加1。

提取周期

和程序计数器(PC寄存器)一样,处理器还具有一个指令寄存器,用于存储当前程序指令。系统时钟发生器可提供脉冲来同步整个机器中发生的事情 - 不一定要这样做,但非时钟同步的机器更难以构建,出于同样的原因,也难以描述!!

CPU中发生的事情是,PC寄存器包含下一条指令的地址,并且在第一个时钟脉冲上,该地址被放置在地址总线上,一个读取周期将指令转移到指令寄存器中。请注意,我们已经在使用“小人儿”描述发生的情况。该地址不是通过某些智能干预“放置在总线上”的。 相反,有一个逻辑门响应时钟脉冲,来启用其他逻辑门,以允许PC寄存器的内容设置到地址总线上。

这称为提取周期。

程序员应知系列 - CPU执行原理

PC寄存器指向存放下一条指令的位置

如果要对提取周期进行更详细的描述,则还必须包括等待所有内容落定下来所必需的延迟。所以完整的提取周期可能是这样的:

在时钟脉冲的上升沿,PC寄存器驱动地址总线,指令寄存器设置为读取数据总线上出现的任何内容 - 即下一条指令。但是,这不会立即出现在数据总线上,因为内存需要时间来响应新地址。

在时钟脉冲期间,地址解码器选择被寻址的RAM位置。事实上,读/写线被设置为读意味着内存位置自动将其内容放在数据总线上

在时钟脉冲的下降沿,指令寄存器将锁存数据总线上的所有内容,而PC寄存器将其内容加1。

请注意,提取周期始终相同,并且没有任何变化,即仅使用逻辑门就可以轻松实现这一点。让PC驱动地址总线,等待一切落定,然后使指令寄存器锁存数据总线上的内容 - 非常简单!

一旦将指令加载到指令寄存器中,PC寄存器就会自动加1。这样可以确保在下一个提取周期开始时,“下一条指令”被“取回”,并且确保程序从头执行到尾。

到目前为止一切顺利,但是在指令寄存器中的指令会发生什么呢?

执行周期

目前,在只有一个提取周期的情况下,运行一个程序就等于将每个程序信息依次传输到指令寄存器中,但实际上什么都没做呢!

解决方案是添加“执行周期”。在每个提取周期之后,下一个时钟脉冲将启动执行阶段。解释执行周期的通常方法是说指令先被“解码”,然后再执行。

这种解释的麻烦在于,它再次几乎被神秘化,并且使人想起了住在机器中的某个小人儿的情形,这个小人儿查看指令、然后执行指令。这当然还是无稽之谈!真正发生的事情与运行计算机的其他所有部件一样,都是自动的、常规的和非智能的。

每个指令都由许多片段或字段组成。确切的数量和类型取决于处理器的体系结构,并且可以由硬件设计人员确定,但是通常至少有两个。

第一部分称为“操作码”。这是一个简单的二进制值,用于指定指令将执行的操作。

大多数处理器具有与程序计数器和指令寄存器类似的其他寄存器,这些寄存器通常是指令处理的主要内容。出于历史原因,第一个通用寄存器通常称为A寄存器 - 表示累加器的“ A” - 一个典型的指令是从某个指定的内存位置加载A寄存器。其他通用寄存器通常称为B,C,D等等。

每个指令都有唯一的操作码,这不仅可以识别该指令,而且实际上能够使计算机执行该操作。发生这种情况的方式是,指令寄存器具有与指令操作码的固定位置相对应的部分。

在我们的示例中(如图所示),操作码对应于前四位。操作码中的每个位都连接到称为指令解码器的某种组合逻辑,该组合逻辑使处理器执行与操作码相对应的任何操作。

至此,在大多数有关处理器工作原理的描述中,都掩盖了“如何执行”的主题,但为了消除这个谜团,我们需要更加仔细地研究一下。

操作码

操作码不只是旧的数字;它具有结构。

在我们的示例中,操作码的低两位充当迷你地址,用于选择该操作将要使用哪个寄存器 –

11 A寄存器,

10 B寄存器,

01 C寄存器,

00 D寄存器。

高两位给出了要在所选寄存器上执行的操作 - 例如:

10 = 加载到寄存器,

11 = 与寄存器中已有的值累加

等等。

您会看到指令解码器中没有任何魔术。 将低两位送入一组“与”门,该“与”门向正确的寄存器提供选择信号,即四个可能的之一。

使用“与/或”门对高两位进行类似的解码,以得出使寄存器“锁存”或加载数据总线上任何内容的信号。

程序员应知系列 - CPU执行原理

指令解码器提供信号来选择寄存器并决定它做什么操作

随着处理器变得越来越复杂,有更多的寄存器可供选择,还有更多的操作需要设置。 但是,指令解码器的操作始终是相同的。 它挑选出部分操作码并将其解码为少量控制线,这些控制线会更改在CPU中选择或取消选择的逻辑元素。

随着处理器变得越来越复杂,有更多的寄存器可供选择,也有更多的操作需要设置。然而,指令解码器的操作总是相同的。它从操作码挑出某些部分,并将其解码为少数几条控制线,这些控制线控制选中或者不选中哪些CPU中的逻辑元件。

地址字段

现在你可以看到,执行阶段以一种完全自动的方式加载A寄存器,但是从哪里加载呢?

答案通常是在操作码中的第二个字段被视为地址。在执行周期开始时,操作码的地址部分被放置在地址总线上,这确定了该寄存器是从哪个内存位置加载或存储到的哪个内存位置。

程序员应知系列 - CPU执行原理

地址字段选择要在操作中使用的内存地址

注意,地址总线上放置的内容取决于哪个寄存器是活动的。 在提取周期中,PC寄存器处于活动状态,它驱动地址总线,而指令寄存器则锁存数据总线上的内容。 在执行周期中,指令寄存器处于活动状态,它驱动地址总线,并且某个寄存器锁存数据总线上的内容。

真的很简单。

我们现在要做的就是把它们放在一起。

提取-执行周期

现在我们对执行阶段所发生的事情有了一个完整的描述,甚至可以在一切都落定下来的时候在描述中添加必要的延迟。所有事情发生的时间都是由系统或处理器时钟决定的。具体什么时候发生,会依据处理器的特定类型而有所不同,但是通常使用时钟脉冲的上升沿和下降沿来标记事情发生的时刻。

对于刚刚通过上一次提取,放置在指令寄存器中的寄存器加载指令,接下来将会发生:

  1. 在执行时钟脉冲的上升沿,寄存器选择位被解码,并且寄存器选择线之一被激活。操作码的“动作”部分被解码,寄存器控制线之一(在这种情况下为加载)被激活。指令上的地址部分驱动地址总线。请注意,所有这些操作都是同时发生的,因为动作的每个部分都有单独的逻辑门。
  2. 在时钟脉冲期间,存储器对地址总线进行解码,而已寻址到的内存位置驱动数据总线 - 并在给定时间内落定下来。
  3. 在时钟脉冲的下降沿,选中寄存器锁存数据总线。

并且,当然,在执行周期之后,将进入下一次提取周期,依此类推,直到程序执行完成。

这是计算机的基本原理,也是CPU的工作方式。

您不需要更多的硬件或其他额外的操作原理,即可制造出满足大部分需求的机器。

例如,要求两个数值的加和,您不需要特殊的指令即可将两个存储位置的值加在一起。您所需要的就是加载A寄存器的指令,以及将一个内存位置的值加和到A寄存器的当前值的指令。请注意,除了提取周期和执行周期外,不需要其他类型的时钟周期。加和硬件的实现是为了将数据总线上的值加和到寄存器中,而不是将数据总线的值加载到寄存器中。

重复向A寄存器中添加值的操作,即“累加(Accumulating)”一个和,是A寄存器名称的由来。

使A寄存器成为累加器所需的额外硬件只是一个全加法器,它将数据总线上的值与A寄存器的输出上的值相加。全加法器的输出反馈到A寄存器的输入。

程序员应知系列 - CPU执行原理

如何累加

如果您不想使事情变得复杂,您甚至可以使用相同的硬件配置来实现“加载A”操作,只需在“添加至A”操作期间阻止A寄存器的输出即可。 但是实际上,现代处理器具有许多内部总线,这些内部总线将寄存器连接到算术和逻辑单元(ALU) - 而全加器只是其中的一个比较原始的元件。

问题:一个全加器发展到最后会成为什么?

答案:ALU……

跳转

最后,只是为了向您展示CPU工作可能需要的所有内容,都可以轻松地包含在简单的处理器体系结构中,需要考虑如何实现“跳转到xxxx”指令。

通常,下一条要执行的指令存放在内存中的下一个顺序位置上,但是跳转会使xxxx处的指令成为下一个指令。

如何做到这一点?非常简单!

只需使PC寄存器对应于寄存器地址00(而不是前面建议的通用寄存器D)即可。现在考虑“从地址aaaa加载PC”的作用。它用存储在“ aaaa”中的值加载PC寄存器,因此使它成为下一条指令。没有什么必需的东西,但不难发现如何修改它,使它完全按照指定的方式工作。

但这将我们带到了一有趣的话题,即寻址模式,那是另一个故事了。

为了使计算机能够执行您需要执行的所有操作,还需要添加条件跳转。基本的跳转指令用于固定循环 - 重复的代码段。条件跳转用于实现人类更能理解的条件,就像自然语言一样。将我们的设计扩展成这样非常容易。您需要另一个寄存器,即条件代码寄存器。现在,当加载寄存器后,还需要提供在条件代码寄存器中设置位的逻辑。如果寄存器为零,则设置为零;如果为负,则设置为负;如果为正,则设置为正。现在,您可以修改跳转指令,使其包含可以测试条件位的逻辑。所以现在你有了条件跳转指令,比如jmpeq表示如果等于0跳转,jmpn表示如果为负跳转,等等。您应该能够看到如何实现这一点 - 条件位只需启用或禁用PC寄存器的加载即可。

有了条件跳跃,我们的计算机现在可以做任何事情——它是图灵完备的。

超越提取和执行周期

如果您了解现代处理器,您可能会提出反对意见,认为这不是它们的工作方式。这在一定程度上是正确的。最初的计算机完全按照描述的方式工作,但是随着时间的推移,提取执行周期已进行了调整,以使计算机的运行速度更快。特别地,通常延长提取周期、解码和执行周期,以便在一个时钟脉冲上,一条指令被提取的同时,较早的指令被解码并同时执行。这通常被称为管道,大多数现代机器都在使用它,但这只是对fetch-execute的一个发展。现代处理器是如此发达,以至于您可能看不到它们如何工作的简单性,但从最底层看,它仍然是负责计算的提取执行周期。

2021-05-13 原文

程序员应知系列 - CPU执行原理的相关文章

程序员应知系列CPU执行原理(当处理器将地址放置在地址总线上时将选择一个特定的存储位置)

(当处理器将地址放置在地址总线上时将选择一个特定的存储位置) https://m.toutiao.com/is/eyC48ar/ 任何计算机系统的真正复杂性都存在于处理器中,但是您知道它是如何工作的吗 ...

程序员必备的思维能力:结构化思维

在日常工作中,我们时常会碰到这样的情况,有的人讲一件事情的时候逻辑非常混乱,说了很多事情的罗列,却说不到重点.有的人写代码,本身的业务逻辑并没有多复杂,但呈现出的代码却像一堆线团,混乱不堪,无法理解. ...

对于一个程序员来说,最浪费人生的事情大概...

对于一个程序员来说,最浪费人生的事情大概就是: 1)追捧一些过时的技术.比如 Perl,窗口期已过,就算出个 Perl 7 也无济于事,自己玩还差不多. 2)过于痴迷一些平时不太用得到的技术.比如 H ...

下岗程序员500万卖房炒股!割肉上机再入金龙鱼,股神还是韭菜?

最近在投资平台上有个下岗程序员很火,据其自称610万深圳卖房拿出500万炒股,在割肉上海机场后,五一节后第一天再次出手.这次他吸取了教训,不再单吊一只股,而是同时买了三只股,分别是金龙鱼.中国平安.潍 ...

一篇文章搞懂高级程序员、架构师、技术总监、CTO从薪资到技能的区别

"我希望用一篇文章完全让大家正确的理解从程序员到架构师.技术经理.技术总监.CTO的完整区别以及进阶要领. 只有客观去认识,才会更加合理的找到自己的擅长点,从而更好的发展自己. 上图是典型的 ...

程序员为你揭秘,什么是“千年虫”事件,“2038年问题”又是什么

在即将进入2000年的时候,计算机出现了一个问题,它就是著名的"千年虫"事件. "千年虫"并不是现实生活中我们所见到的虫子,而是计算机系统由于时间紊乱产生的bu ...

【赠书】程序员必备!如何深入理解计算机系统

周末到了,本次给大家赠送3本新书,这次赠送的书籍是<深入理解计算机系统:第3版>. 这是一本什么样的书 这是一本讲解计算机软硬件系统的书,从程序员视角全面剖析其实现细节,使读者深刻理解程序 ...

阿里程序员自述:入职才两个月,我决定离职

先说一下我的基本情况吧.家住杭州的前端程序员,毕业4年多,之前在杭州中小公司.独角兽公司都待过.其实去之前对阿里价值观.氛围都还是比较了解的 (在杭那么多年,而且同为互联网行业,不了解就有鬼了--). ...

成为一名优秀的Java程序员9+难以置信的公式

成为一名优秀的Java程序员 成为一名优秀的Java程序员并不重要,但是首先您应该了解基本的编程语言. 好吧,你知道那太好了.我们应该一步一步地精通Java编程,并应遵循所有说明,改进Java的编程逻 ...