抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

计算机组成原理

电子管计算机 -> 晶体管计算机 -> 集成电路计算机 -> 超大规模集成电路计算机

未来: 生物计算机, 量子计算机(量子力学)

微型计算机发展

摩尔定律: 集成电路的性能, 每18-24个月就会提升一倍.

计算机的体系与结构

冯诺依曼模型

将程序指令和数据一起存储的计算机设计概念结构.

  • 必须有一个存储器
  • 必须有一个控制器
  • 必须有一个运算器
  • 必须有输入设备
  • 必须有输出设备

CPU和存储器的速率之间的问题无法调和.

冯诺依曼瓶颈: CPU经常空转等待数据传输.

现代计算机结构

构成计算机的元素

  • 状态
  • 输入
    • 时钟作为一种标准输入
    • 另一种最好可以读取人类的想法
  • 状态转换函数F((将输入和当前状态转换为下一个状态))
  • 输出

状态描述

  • 数字即可–一切皆可用数字表示
    • ASCII
    • 商品
  • 一个数字不够(需要数组)

状态转换函数

一个表格就可以, 接收到的输入I变成新的状态S

输入\状态

实际上可以用0和1表示

输入\状态 0 1
0 1 1
1 0 1

状态转换表

思考:鼠标在1024*768的屏幕上有786432种位置, 因此对应了786432种状态。如果用表格来描述需要很大的一个空间。如何优化?

方案:用程序描述状态转换表

  • 每次鼠标位置更新, 都调用一段程序去计算需要显示的位置
  • 程序需要预先在机器中安装好
  • 需要有执行程序的工具(一个计算器)

输入

  • 时间是最重要的输入
    • 晶振(不是输入设备)
  • 可以通过设备读取外界信息
    • 鼠标、键盘、手柄
    • 头盔
    • 脑电波

输出

从计算机中读取状态

  • 找根线连接芯片的引脚
  • 打印机
  • 显示器

计算机的层次与编程语言

硬件逻辑层 -> 微程序机器层 -> 传统机器层 -> 操作系统层 -> 汇编语言层 -> 高级语言层 -> 应用层

  • 一个机器指令对应一个微程序
  • 一个微程序对应一组微指令

操作系统是软件和硬件层的适配层.

计算机的计算单位

容量单位

硬盘商一般使用十进制标记容量.

CPU速度

  • 一般体现为CPU的时钟频率
  • 单位一般是赫兹(Hz)
  • 主流CPU的时钟频率都在2GHz以上

赫兹: 秒分之一. 每秒中的周期性变动重复次数的计量.

CPU通过高低电平表示0和1. 所以频率指CPU高低电平每秒变换的次数.

计算机字符与编码集

ASCII 码.

GB2312. GBK.

Unicode: 兼容全球的字符集, 统一码, 万国码, 单一码.

Unicode 定义了世界通用的符号集*, UTF-*实现编码**.

计算机速度单位

TFlop/s.

1TFlop/s = 每秒一万亿次浮点计算.

1024G=1T

计算机的总线

解决不同设备之间的通信问题.

USB: Universal Serial Bus, 通用串行总线. 连接标准, 统一外围设备.

PCI总线, ISA总线, Thunderbolt总线

片内总线

高集成度芯片内部的信息传输线.

芯片内部的总线, 寄存器与寄存器之间. 寄存器与控制器, 运算器之间.

系统总线

三种.

  • 数据总线: 双向传输各个部件的数据信息. 数据总线的位数(总线宽度)是数据总线的重要参数. (一般与CPU位数相同)如果是32位, 一次可以运输4字节的数据; 64位则是8字节.
  • 地址总线: 用于传输数据的地址.
    • 地址总线位数=n, 寻址范围: 0~2^n^.
    • 指定源数据或目的数据在内存中的地址.
    • 地址总线的位数与存储单元有关.
  • 控制总线
    • 发出各种控制信号的传输线.
    • 控制信号经由控制总线从一个组件发送到另外一个组件.
    • 控制总线可以监视不同组件之间的状态(就绪/未就绪)

总线仲裁: 解决不同设备使用这个总线优先顺序的设备(仲裁控制器). 解决总线使用权的冲突问题.

总线仲裁方法

  • 链式查询
    • 电路复杂度低, 仲裁方式简单
    • 优先级低的设备难以获得总线使用权限
  • 计时器定时查询
    • 仲裁控制器对设备编号并使用计数器累计计数
    • 接收到仲裁信号后, 往所有设备发出计数值
    • 计数值与设备编号一致则获得总线使用权
  • 独立请求
    • 每个设备均有总线独立连接仲裁器
    • 设备单独向仲裁器发送请求和接收请求
    • 当同时收到多个请求信号, 仲裁有权按优先级分配使用权

链式查询

定时器定时查询

计算机输入输出设备

输入输出接口的通用设计

  • 数据线
    • 单向/双向IO设备与主机传输数据
  • 状态线
    • IO设备向主机报告的信号线
    • 查询设备是否已经正常连接就绪
    • 设备是否被占用了
  • 命令线
    • CPU向设备发送命令的信号线
    • 发送读写/启动/停信号止
  • 设备选择线
    • 主机选择IO设备进行操作的信号线
    • 对连在总线上的设备进行选择

CPU与IO设备的通信

  • 程序中断
  • DMA(Direct Memory Access, 直接存储器访问)

中断和中断向量

  • 当外围IO设备就绪时, 向CPU发出中断信号(事件)
  • CPU有专门的电路响应中断信号
  • 当收到中断信号后, 就会停止当前工作, 保存当前执行状态, 转去处理IO设备的事件

提供低速设备通知CPU的一种异步的方式.

中断让CPU可以高速运转的同时兼顾低速设备的响应.

中断过程
  • OS加载时, 写入中断向量表(IVT, 内存中的一块区域)
  • 产生中断请求, 发送给CPU(鼠标, 键盘, 软件都可能发生中断)
  • 查询中断向量表(Interrupt Vector Table)确定中断向量(Interrupt Vector)
  • 根据中断向量定位中断响应程序(ISR)
  • OS接管中断
中断请求

Interrupt Request

  • 硬件设备发给主板(打印机, 键盘, 鼠标, 磁盘等)
  • 硬件中断: CPU异常(除以0), 时钟信号等
  • 软件中断: 发出(异常, 切换到内核态等)
中断向量表
  • 一般是内存中的一块区域, 存储了中断类型中断响应程序(程序执行片段的地址)的对应关系. 每一行叫做一个中断向量.

单步中断: 调试用.

中断是可编程的.

sleep 也要中断的, 需要时钟.

中断可以节省资源. 例如在等待打印机准备就绪的时候, 可以进行中断去干其它事情, 等准备完成才进行打印(异步).

中断的意义
  • 提供工作效率(polling问题)

  • 故障恢复(异常处理, 紧急事件等)

  • 32bit的机器上中响应路径(ISR)只有4byte, 如何实现复杂的程序?

    • 存的是一个地址, 有点像函数调用.
  • 按键程序中断响应路径到操作系统再到应用, 哪个按键被按了是怎么区分的?

    • 键盘会在内存中存有一份映射, 中断相当于通知.
  • 中断响应后, 如何恢复到中断执行前的状态?

    • 在中断前会把之前所在的PC指针下一行存在栈中, 在执行完后, 清栈后, 上一条就是返回地址了
  • 出错后, 为什么要直接跳到错误的处理位置?

    • 错误发生后, 错误对应的处理者不是一对一的关系. 降低耦合程度, 不关心的程序可以不监听这个中断. 这种消息的模型, 也是现在软件架构的主流方向.

DMA

  • DMA 直接连接主存与IO设备
  • DMA 工作时不需要CPU的参与

硬盘和外置显卡都有DMA.

计算机存储器

随机存取存储器–RAM(Random Access Memory), 随机读写数据可以在几乎相同的时间内完成, 与数据的物理位置无关.

内存寻址: 32位的机器, 每次都操作4个字节, 而64位的操作8个字节. 所以32位系统最大支持4GB内存.

串行存储器, 与位置相关, 按顺序查找

只读存储器(ROM), bios就是一种

存储器的层次结构 – Memory Hierarchy

  • 缓存, 速度快, 位格高
  • 主存, 适中
  • 辅存, 慢

实现: 在 CPU 和主存直接增加一层速度快的Cache

缓存: 解决主存速度不够的问题.

局部性原理: 指 CPU 访问存储器时, 无论是存取指令还是存取数据, 所访问的存储单元都趋于聚集在一个较少的连续区域中.

例如: 程序经常访问的内存, 把这内存置换至缓存即可.

主存之外增加辅助存储器.

辅存: 主存是为了解决主存容量不足的问题.

整体结构

cycle: 一个CPU的周期. CPU由晶振驱动, 晶振一上一下就产生一个周期. 纳米级别的.

一个数据如果频繁被读取, 会缓存在L1,L2或L3.

主存储器

主存储器–内存.

RAM通过电容存储数据的, 必须隔一段时间就刷新一次.

如果掉电, 那么一段时间后就会丢失所有数据.

32位系统: 地址总线32位, 所以最大寻址是 2^32^ = 4 x 2^30^ = 4GB

64位系统: 地址总线64位, 所以最大寻址是 2^64^ = 2^34^ x 2^30^ = 2^34^GB

辅存存储器

机械硬盘

  • 磁道(Track) 一个环
  • 柱面(Cylinder) 多个环形成空心的圆柱体
  • 扇区(Sector)
  • 簇(Cluster), 虚拟概念, 如果是4kb的话, 就8个扇区(512byte). 主要是因为扇区太小了, 很多数据跨扇区, 所以抽象出更大的一个区域出来.
  • 表面是可磁化的硬磁性特性材料

  • 移动磁头径向运动读取磁道信息

  • 先来先服务算法

    • 排队读取(简单粗暴)
  • 最短寻道时间优先

    • 磁头离磁道最近的先读取
  • 扫描算法(电梯算法)

    • 和电梯的算法一致, 所以也叫电梯算法
    • 每次只往一个方向移动
    • 到达需要服务的尽头再反方向移动(4-3-2-1-1-5)
    • 不公平
  • 循环扫描算法

    • 只能往一个方向移动. 从内到外或者从外到内
    • 4-5-1-1-2-3
    • 相对更公平

固态硬盘

使用集成电路读数据进行永久存储.

  • 控制器, 寻址用
  • 存储芯片, 一般是闪存

高速缓存

工作原理

  • 字: 是指存放在一个存储单元中的二进制代码组合
  • 字块: 存储在连续的存储单元中而被看作是一个单元的一组字

所以选址就包括两部分了, 一个是字块的位置, 一个是字的位置.

命中率: 访问主存次数 / 访问Cache次数 + 访问主存次数

访问效率 也能衡量高速缓存的性能.

所以要高的命中率和访问效率, 就需要良好的缓存替换策略.

置换策略

  • 随机算法
  • 先进先出算法
    • 看作是一个队列
    • 先替换最先进入的字块
  • 最不经常使用算法(LFU)
    • 优先淘汰最不经常使用的字块
    • 需要额外空间记录字块的使用频率
  • 最近最少使用算法(LRU)
    • 优先淘汰掉一段时间内没有使用的字块
    • 一般使用双向链表实现
    • 把当前访问节点置于链表前面(保证链表头部节点是最近使用的)

计算机指令系统

  • 计算机通过指针指挥计算机工作.
  • CPU被时钟驱动, 不断地读取PC指针指向的指令, 并增加PC指针, 从内存中读取指令并执行(周而复始).
  • 不同CPU架构使用不同的指令, 都符合图灵规范. 目前使用最广泛的是RISC(Reduced instruction set computer, 精简指令集), 这个指令集的位宽都一致.

机器指令组成: 操作码+地址码

可分为三地址指令, 二地址指令一地址指令(自增)

零地址指令, 无地址码, 空操作, 停机操作, 中断返回操作等.

指令操作类型

  • 数据传输(load/store 指令, 从内存中读/写入内存)
    • 寄存器之间, 寄存器与存储单元之间, 存储单元之间
    • 数据读写, 交换地址数据, 清零置一等操作
    • load类: lw(加载一个字), lb(加载一个byte), lh(加载半个byte)
    • store类: sw, sb, sh
  • 算术逻辑
    • 操作数之间加减乘除(指令后有个 u 是 unsigned 的意思)
      • 立即寻址: addi, subi, divi, multi 等…
      • 寄存器寻址: add, sub, div, mult 等….
    • 操作数之间与或非( and/or/xor 等)
  • 移位操作
    • 左移, 右移
    • 完成数据在算术逻辑单元的必要操作
  • 控制指令
    • 等待指令
    • 停机指令
    • 空操作指令
    • 中断指令
    • 比较与分支
      • beq(等于), bne(不等于), slt(set if less than)
    • 跳转
      • jump j 1000 (相对选址)
      • jump register jr $31 (寄存器间接选址)
      • jump and link jal 1000 (多合一, 函数实现)

地址指令的寻址模式

Addressing Model

  • 指令集的一部分, 决定指令有几个操作符, 地址如何计算
  • opcode 代表指令的类型; opcode 也决定寻址模式.

分类

  • 指令选址
    • 顺序寻址
    • 跳跃寻址
  • 数据选址
    • 立即选址, 直接获得操作数, 无需访问存储器. 但是地址的位数限制了操作数的表示范围.
    • 直接选址, 直接给出操作数在主存的地址, 无需计算操作数的地址. 缺点同上.
    • 间接选址, 指令给出的地址是操作数地址的地址(指向主存, 主存中存的是操作数的地址), 需要一次或多次获取操作数. 缺点是速度较慢.

寄存器寻址. 寄存器从内存地址读取数据.

立即数选址. 操作符中有值, 数值部分占据了部分, 所以会有大小的限制.

偏移量寻址. 根据基地址和偏移量进行选址. &sp是base寄存器.

PC相对寻址

MIPS-32指令实例

MIPS-32是 RISC 的. opcode 是操作符的意思.

target 左移两位.

rs(register source): 源寄存器, rt(register target): 目标寄存器, rd(register destination): 目的寄存器

funct=0x20 是说使用 add 操作.

从内存地址读取数据到寄存器的指令.

助记符, 也称作汇编语言.

计算机的控制器

控制器是协调和控制计算机运行的.

程序计数器

  • 存储下一条指令的地址
  • 循环不断从程序计数器中拿出指令
  • 指令拿出是, 指向下一条指令

时序发生器

  • 电器工程领域, 用于发送时序脉冲
  • CPU 依据不同的时序脉冲有节奏地进行工作

指令译码器

  • 指令译码器是控制器地主要部件之一
  • 计算机指令由操作码和地址码组成的
  • 翻译操作码对应的操作以及控制传输地址码对应的数据

指令寄存器(Register)

  • 可以是控制器的主要部件

  • 从主存或高速缓存取计算机指令

  • 主存地址寄存器: 保存当前CPU正要访问的内存单元的地址

  • 主存数据寄存器: 保存当前CPU正要读或写的主存数据

  • 通用寄存器: 用于暂时存放或传输数据或指令; 可保存 ALU 运算的中间结果; 容量比一般专用寄存器要大

计算机的运算器

用于进行数据运算加工的.

数据缓冲器

  • 用来暂时存放 输入/输出 外设发 送过来/送出去 的数据

ALU

  • 算术逻辑单元, 是运算器的主要组成
  • 常见的位运算(左右移, 与或非)
  • 算术运算(加减乘除)

内存到CPU还要经过缓存(L1, L2, L3)才到寄存器.

划分2个空间, 一个数据空间地址, 一个指令空间地址.

指令占的字节数根据系统有关系, 通常32位占4个字节, 64位8个字节.

寄存器

状态字寄存器

  • 存放运算状态(条件码, 进位, 溢出, 结果正负等)
  • 存放运算控制信息(调试跟踪标记位, 允许中断位等)

通用寄存器

  • 用于暂时存放或传送数据或指令
  • 可保存ALU的运算中间结果
  • 容量比一般专用寄存器大

运算过程

5000 * 0.2 的计算过程

地址 1000 的数据 load 进 寄存器. CPU 都是用寄存器中的值进行计算的.

程序指针(PC) – 指向指令空间中要指向的指令, 一步一步往下执行

计算机指令的执行过程

CPU指令集分类

机器循环

CPU周期. CPU 有时钟, 晶振来驱动的.

晶振 产生波, 有波峰有波谷. 指令操作的周期一般是固定的.

PC++是指移动到下一个指令, +的是一个指令宽度, RISC的每一个位宽都是一样的, 在32位系统通常是+4.

指令周期

execute – 计算 store – 存储, 控制

指令执行过程

取指令 -> 分析指令 -> 执行指令 -> 程序指针++

  1. 把指令和数据缓存起来.
  2. 程序计数器只知道执行指令的地址, 需要通过 总线 从指令缓冲获取执行指令.
  3. 取出的指令通过 总线 来到 指令寄存器, 指令寄存器缓存指令内容.
  4. 把指令内容发送给 指令译码器, 这时候 程序计数器+1.
  5. 指令译码器解析之后, 通过总线发出 控制信号 给 运算器.
  6. 运算器中的 寄存器 转载数据.
  7. 通过 ALU 进行计算, 记录运算状态.
  8. 最后把结果放在数据缓存器.

数据缓存也叫做数据空间, 指令缓存也叫做指令空间.

因为这个过程, 控制器运算器不是一起工作了, 导致了一个问题, CPU 综合利用率不高(串行).

所以提出了 CPU的流水线设计

计算机的计算

计算机的进制

计算机用二进制, 但是二进制表达太长了, 所以使用十六进制缩短表达.

八进制和十六进制满足2的n次方的要求.

二进制转换成十进制

十进制转成二进制

小数二进制转换十进制

小数十进制转换二进制

原码, 补码, 反码

原码表示法

  • 使用0表示正数, 1表示负数
  • 规定符号位位于第一位

计算机使用原码进行计算很复杂, 特别是两个操作数符号不一致的时候

  • 判断两个操作数绝对值大小
  • 使用绝对值大的值减去绝对值小的数
  • 符号值要以大的为准

二进制的补码表示法. n表示寄存器的位数, 其实是x的位数

大于0, 补码等于原码

例如: n=4, x=-7的补码

负数为原码的反码加一.

  • 使用正数代替负数的方法
  • 使用加法操作代替减法操作, 从而消除减法

补码计算过程中还是使用了减法.

反码

目的是找出原码和补码之间的规律, 消除转换过程中的减法.

小数的补码

定点数和浮点数

定点数

小数点固定在某个位置的数.

一个数如果不是纯小数或纯整数, 就要 乘以比例因子以满足定点数保存格式

左移或右移

浮点数

浮点数在计算机里是通过整数来表示.

  • 计算机处理的很大程度上不是纯小数或纯整数
  • 数据范围很大, 定点数难以表达

举个例子

  • 十进制0.1表示1/10, 二进制里0.1代表1/2, 0.01代表1/4.
  • 所以十进制的 0.375(3/8) 在二进制中表示 0.011= 1/4 + 1/8.

-1^0^(1.1)^1^ = 1.1 = 1.5

科学计数法: 尾数, 基数, 阶码

尾数必须是纯小数.

浮点数表示范围

浮点数的上溢, 下溢

单精度浮点数: 使用4字节, 32位来表示的浮点数(float)

双精度浮点数: 使用8字节, 64位来表示的浮点数(double)

浮点数规格化

  • 尾数规定使用纯小数
  • 尾数最高位必须是1

对比

  • 当定点数与浮点数位数相同时, 浮点数表示的范围更大
  • 当浮点数位数为规格化数时, 浮点数的精度更高.
  • 浮点数的运算包含阶码和尾数, 浮点数的运算更为复杂

浮点数在数的表示范围, 精度, 溢出处理, 编程等方面都优于定点数.

定点数在运算规则, 运算速度, 硬件成本方面优于浮点数.

定点数的加减法

定点数加法

数值位与符号位一同运算, 并将符号位产生的进位自然丢掉.

例子

溢出, 如果两个操作数的位数少于结构, 就会发生溢出现象.

判断溢出

  • 双符号位判断法
    • 单符号位表示变成双符号位: 0=>00, 1=>11
    • 双符号位产生的进位丢弃
    • 结果的双符号位不同则表示溢出

定点数减法

浮点数的加减法

对阶 -> 尾数求和 -> 尾数规格化 -> 舍入 -> 溢出判断

对阶的目的是使得两个浮点数阶码一致, 使得尾数可以进行运算.

尾数右移使阶码对齐.

尾数求和

  • 使用补码进行运算
  • 减法运算转换为加法运算: A - B = A + (-B)

尾数规格化

  • 一般情况下都是左移
  • 双符号不一致下需要右移(定点运算的溢出情况)

舍入

  • 0舍1入 法(二进制的四舍五入)

因为舍去的是1, 所以要+1. 如果舍去的是0就不需要加.

可能会出现溢出现象.

溢出判断

  • 定点运算双符号位不一致为溢出
  • 浮点运算双符号位不一致不算溢出
  • 浮点数运算主要是通过阶码的双符号位判断是否溢出

阶码符号位一致就没有溢出.

整体流程

计算机组成原理实践

汇编

使用汇编实现递归函数.

实现思路

函数就是先跳到一个标签再跳回来.

函数传参–栈. $sp寄存器, 也称为栈指针.

压栈逻辑, 实现函数传参. 栈是往小的方向减少的. 出栈是++. 往上地址越大.

实现函数返回. 注意要在函数体之前把函数的返回位置压栈. 压栈就伴随栈指针–. 出栈++.

栈: 图解

  • lw $r0 8(&sp) 取出参数 栈指针+8
  • lw &t1 4($sp)
  • jr $t1 t1存了函数调用的位置, 所以跳回去

实现返回值. 先初始化一个返回值, 把返回值进行压栈.

压栈了3个参数.

上一级压栈下一个参数. 也就是说函数的控制权有一个交叠的关系.

评论