当前位置: 首页 > ops >正文

计算机原理(二)

计算机原理系列

欢迎大家关注「海拉鲁知识大陆」 多交流不迷路

计算机原理(一)

继续上一篇计算机原理(一)深入了解程序执行部分,进一步说说程序在冯诺依曼模型上如何执行。如果没有了解的童鞋可以查看我上一篇文章。

1.程序的执行过程

当 CPU 执行程序的时候:
1.第一步,CPU 读取 PC 指针指向的指令,将它导入指令寄存器。完成读取指令这件事情有 3 个步骤:

  • 步骤 1:CPU 的控制单元操作地址总线指定需要访问的内存地址(简单理解,就是把 PC 指针中的值拷贝到地址总线中)。
  • 步骤 2:CPU 通知内存设备准备数据(内存设备准备好了,就通过数据总线将数据传送给 CPU)。
  • 步骤 3:CPU 收到内存传来的数据后,将这个数据存入指令寄存器。
    完成以上 3 步,CPU 成功读取了 PC 指针指向指令,存入了指令寄存器。

2.然后,CPU 分析指令寄存器中的指令,确定指令的类型和参数。
3.如果是计算类型的指令,那么就交给逻辑运算单元计算;如果是存储类型的指令,那么由控制单元执行。
4.PC 指针自增,并准备获取下一条指令。
图片

2.详解a=11+15的程序执行过程

上面我们了解了基本的程序执行过程,接下来我们来看看如果用冯诺依曼模型执行a=11+15是一个怎样的过程。

当我们写的程序a=11+15是字符串,CPU只能执行指令。所以这里需要用到编译器。编译器的核心能力是翻译,它把一种程序翻译成CPU可执行的语言。比如java语言就是把.java转换成.class文件类加载到JVM通过解释器和即时编译器(JIT Compiler)执行字节码指令(这里大概了解下,后面我会单独讲讲JVM工作原理)。
下面我们来详细阐述a=11+15的大体执行过程:

1.编译器通过分析,发现11和15是数据,因此编译好的程序启动时,会在内存中开辟出一个专门的区域存这样的常数,这个专门用来存储常数的区域,就是数据段,如下:

  • 11 被存储到了地址 0x100;
  • 15 被存储到了地址 0x104;
    图片

2.编译器将a=11+15转换成了 4 条指令,程序启动后,这些指令被导入了一个专门用来存储指令的区域,也就是正文段。如上图所示,这 4 条指令被存储到了 0x200-0x20c 的区域中:

  • 0x200位置的load指令将地址0x100中的数据11导入寄存器R0;
  • 0x204位置的load指令将地址0x104中的数据15导入寄存器R1;
  • 0x208位置的add指令将寄存器R0和R1中的值相加,存入寄存器R2;
  • 0x20c位置的store指令将寄存器R2中的值存回数据区域中的0x1108位置。

3.具体执行的时候,PC指针先指向0x200位置,然后依次执行这4条指令。

3.指令

在上面的例子中,load 指令将内存中的数据导入寄存器,我们写成了 16 进制:0x8c000100,拆分成二进制就大体如下:
图片

  • 最左边的6位,叫作操作码,英文是OpCode,100011代表load指令;
  • 中间的4位0000是寄存器的编号,这里代表寄存器R0;
  • 后面的22位代表要读取的地址,也就是0x100。

所以我们是把操作码、寄存器的编号、要读取的地址合并到了一个32位的指令中。
我们再来求加法运算的 add 指令,16进制表示是0x08048000,换算成二进制就是:
图片

  • 最左边的6位是指令编码,代表指令 add;
  • 紧接着的4位 0000 代表寄存器 R0;
  • 然后再接着的4位 0001 代表寄存器 R1;
  • 再接着的4位 0010 代表寄存器 R2;
  • 最后剩下的14位没有被使用。

构造指令的过程,叫作指令的编码,通常由编译器完成;解析指令的过程,叫作指令的解码,由CPU完成。由此可见CPU内部有一个循环:

  • 首先CPU通过PC指针读取对应内存地址的指令,单词就是Fetch 。
  • CPU对指令进行解码,单词就是Decode。
  • CPU执行指令,单词就是Execution。
  • CPU将结果存回寄存器或者将寄存器存入内存,单词就是Store。
    图片
    上面4个步骤,就是CPU的指令周期。CPU的工作就是一个周期接着一个周期,周而复始。

4.指令的类型

通过上面的例子,不同类型的指令、参数个数、每个参数的位宽,都不一样。而参数可以是以下这三种类型:

  • 寄存器;
  • 内存地址;
  • 数值(一般是整数和浮点)。

当然,无论是寄存器、内存地址还是数值,它们都是数字。
指令从功能角度来划分,大概有以下 5 类:

  • I/O 类型的指令,比如处理和内存间数据交换的指令 store/load 等;再比如将一个内存地址的数据转移到另一个内存地址的 mov
    指令。
  • 计算类型的指令,最多只能处理两个寄存器,比如加减乘除、位运算、比较大小等。
  • 跳转类型的指令,用处就是修改 PC 指针。比如编程中大家经常会遇到需要条件判断+跳转的逻辑,比如if-else,swtich-case、函数调用等。
  • 信号类型的指令,比如发送中断的指令 trap。
  • 闲置 CPU 的指令 nop,一般 CPU 都有这样一条指令,执行后 CPU 会空转一个周期。

指令还有一个分法,就是寻址模式,比如同样是求和指令,可能会有另个版本:

  • 将两个寄存器的值相加的 add 指令。
  • 将一个寄存器和一个整数相加的 addi 指令。
    另外,同样是加载内存中的数据到寄存器的 load 指令也有不同的寻址模式:
  • 比如直接加载一个内存地址中的数据到寄存器的指令la,叫作直接寻址。
  • 直接将一个数值导入寄存器的指令li,叫作寄存器寻址。
  • 将一个寄存器中的数值作为地址,然后再去加载这个地址中数据的指令lw,叫作间接寻址。

因此寻址模式是从指令如何获取数据的角度,对指令的一种分类,目的是给编写指令的人更多选择。

5.指令的执行速度

CPU其实是用石英晶体产生的脉冲转化为时钟信号驱动的,每一次时钟信号高低电平的转换就是一个周期,我们叫时钟周期。CPU的主频,说的就是时钟信号的频率。比如一个1GHz的CPU,说的是时钟信号的频率是1G。这就是我们买电脑熟悉的需要知道CPU的频率参数了,频率越高性能越好了。

这里再说明一下,不是每个时钟周期都可以执行一条指令。多数指令可能不在一个时钟周期完成,通常需要 2 个、4 个、6 个时钟周期。

http://www.xdnf.cn/news/20280.html

相关文章:

  • C++并发编程指南 std::promise 介绍与使用
  • Boost电路:环路仿真
  • 对于单链表相关经典算法题:206. 反转链表及876. 链表的中间结点的解析
  • 6-2-4 解决第一次发送失败
  • Android应用完全重启指南:从任务重置到进程重生
  • 第五十三天(sql注入)
  • FTL(Flash Translation Layer)
  • [从零开始面试算法] (12/100) LeetCode 121. 买卖股票:一次遍历的“后悔药”
  • 高维前缀和
  • Android系统更新系统webview. 2025-09-06
  • gcloud cli 使用 impersonate模拟 服务帐号
  • 2025年财会专业人士职业发展认证路径分析
  • 从“帮写文案”到“管生活”:个人AI工具的边界在哪?
  • Transformer架构(详解)
  • 记一次:mysql的json及json数组使用组合使用
  • 【基础-单选】关于UIAbility的启动模式,下列说法错误的是:
  • Redis 事务与 Lua 脚本:原子操作实战指南
  • LeetCode 2461.长度为K子数组中的最大和
  • 【FastDDS】 Entity Policy 之 标准Qos策略
  • OpenHarmony之USB Manager 架构深度解析
  • 【视网膜分割】AFMIP-Net:一种新型的自适应特征调制和隐式提示网络
  • AI、人工智能础: 实体命名!
  • 郭平《常变与长青》读书笔记(第一章)
  • QT之实现点击按钮启动另一个桌面应用程序
  • 【开题答辩全过程】以 停车场管理系统的设计与实现为例,包含答辩的问题和答案
  • 点晴模切ERP与MES系统整合:模切工厂数字化转型关键
  • 内网后渗透攻击--linux系统(横向移动)
  • Python趣味入门:打印与计算初体验
  • 垃圾收集器分类
  • 「数据获取」《中国电力统计年鉴》(1993-2024)(含中国电力年鉴)