Computer Organization and Architecture
运算方法
双符号位
双符号位表示带符号数时,符号位的组合含义为:
- 00:正,无溢出;
- 01:正溢出(上溢);
- 10:负溢出(下溢);
- 11:负,无溢出
IEEE754
浮点数表示标准:
- 1 位符号位(S):0 表示正数,1 表示负数
- 8 位阶码(E):存储指数的 “偏移值”(偏移量为 127)
- 23 位尾数(M):存储小数部分(隐含一个最高位的 “1”,节省空间)
以11.375为例,步骤如下:
- 将十进制转二进制
$11.375_{10} = 1011.011_2$(整数部分 11→1011,小数部分 0.375=0.25+0.125→011)
- 规格化二进制(转为 $1.xxxxx \times 2^e$ 形式)
$1011.011_2 = 1.011011 \times 2^3$
→ 指数 $e=3$,尾数部分为011011(隐含前面的 “1”)
- 计算阶码(E)
阶码是 “指数 + 偏移量 127”:$E = 3 + 127 = 130_{10} = 10000010_2$
- 拼接结构
- 符号位 S:正数→
0 - 阶码 E:
10000010 - 尾数 M:
011011后面补 0 到 23 位→01101100000000000000000
1 | |
浮点运算方法和浮点运算器
- 阶码(双符号位补码)+ 尾数(双符号位补码)的形式
- 正数:00.1xxxxx
- 负数:11.0xxxxx
- 比较阶码大小并完成对阶(小阶向大阶看齐):对齐小数点,以便进行尾数的加减运算
- 右移:左边空缺的位会用符号位填充(补码运算中,正数填 0,负数填 1)
- 左移:右边空缺的位用 0 填充
- 尾数求和:与定点数加减法方法相同
- 规格化处理
- 舍入处理:规格化后最低有效位丢失,会造成一定误差,要进行舍入处理
- 就近舍入
- 朝0舍入
- 朝+无穷舍入
- 朝-无穷舍入
- 判断溢出(考试的时候记得进行判断)
- 阶码上溢
- 阶码下溢
- 尾数上溢
- 尾数下溢
存储系统
存储器三剑客
-
主存(内存):用来存放计算机运行期间所需要的程序和数据,CPU可以直接随机的进行读/写访问,存取速度快。
-
外存:用来存放暂时不参与运行的程序和数据,以及一些需要永久性保存的信息,容量极大,但存取速度低,CPU不能直接访问,信息必须调入主存后CPU才能使用。
-
CPU和主存之间还有高速缓冲存储器cache存放正在执行的程序段和数据,通常被放在CPU芯片中,存储容量小,价格高
按存取方式分类
-
随机存储器RAM
-
优点:对RAM任意单元的读写时间相同,与物理地址无关(类似数组)
-
缺点:一旦断电,RAM失去存储信息
- 静态SRAM:双稳态触发器,制造cache
- 动态DRAM:mos管和电容,主存
-
-
只读存储器ROM
- 优点:断电之后不会丢失存储信息,适合存储固定程序和数据
- 缺点:一经写入,之后只能读取,不能再次写入,里面的内容固定不变
-
顺序存取存储器:磁带
- 缺点:必须数着存储单元的物理地址顺序,顺次访问(串行访问)(类似链表)必须从前往后遍历才能找到需要访问的单元,存取时间与存取的物理地址相关
-
直接存取存储器DAM:光盘(随机+顺序存取相结合)
- 特点:先通过随机访问,确定一个较小的存储区域,在在这小区域内顺序查找
-
相联存储器:按照内容寻址,将所存的内容的某一部分作为检索项(关键字)去检索
寻址
- 字节编址最小形式单位是一个字节,可以按字节。半字,字寻址
- 字编址最小心是单位是一个字,仅支持,按字寻址
- 字节(Byte):固定标准,1字节 = 8位(bit),全球统一。
- 不同机器字长的换算示例:
- 32位机器:1字 = 4字节(32位),1半字 = 2字节(16位);
- 16位机器:1字 = 2字节(16位),1半字 = 1字节(8位);
- 64位机器(通用):1字 = 8字节(64位),1半字 = 4字节(32位)。
机器字长是 CPU 的硬件属性,指 CPU 一次能处理的二进制数据位数(32 位 / 64 位)就比如我们知道的windows32位/64位系统:具体差异体现在:
- 寻址能力:32 位系统最大支持约 4GB 内存(受限于 32 位地址线寻址上限),64 位系统可支持远超 4GB(理论上达 16EB),多开软件、运行大型程序(如设计软件、游戏)时更不易卡顿。
- 软件兼容性:32 位系统无法运行 64 位软件,64 位系统可兼容运行大部分 32 位软件
- 运算性能:64 位 CPU 一次能处理更多数据,对复杂计算(如视频渲染、编程编译)的效率比 32 位更高,日常简单操作(聊天、浏览网页)差异不明显。
1GB = 1024MB,1MB = 1024KB,1KB = 1024B
- 核心原则:“字” 的长度永远等于机器字长,“半字” 是 “字”长度的一半,均以字节为最小单位换算。
存储速度
- 1 s(秒)= 10³ ms(毫秒)= 1000 ms
- 1 ms(毫秒)= 10³ μs(微秒)= 1000 μs
- 1 μs(微秒)= 10³ ns(纳秒)= 1000 ns
-
访问时间:
- 读出时间$T_A$
- 写入时间$T_W$
-
存储周期:进行一次读写操作所需要的全部时间,就是存储器进行连续读写操作所允许的最短时间间隔
-
存储带宽:表示存储器被连续访问时可以提供的数据传送速率,字节/秒
- 存取时间:存储器从读出或者写入一次信息所需要的平均时间
- 存取周期:连续两次访问存储器之间所必需的最短时间间隔
存储介质
-
磁存储器:存取速度慢,但成本低
-
光存储器:用激光束照射盘面,靠盘面的不同反射率来读出数据,便于携带
-
半导体存储器
RAM工作原理
存放一个二进制的物理器件叫做存储元,地址码相同的多个存储元构成一个存储单元,若干存储单元的集合构成存储体
-
DRAM:用于主存,由mos管和电容组成,当电容存储的电荷数超过阈值(电量),电容所在的存储元表示1
- 写入:给高电压,mos管导通,充电
- 读出:mos管导通,若电容有电,电流流出,通过外接信号放大器检测电容的电压信息,放电后需要再次充电进行恢复(破坏性读出);漏电需
要刷新 ,重新将电荷充满
-
SRAM双稳态触发器(6个mos管):存取速度按快,用于cache
| 特征 | SRAM | DRAM |
|---|---|---|
| 构成 | 双稳态触发器 | 电容 |
| 破坏性读出 | 否 | 是 |
| 再生 | 不需要 | 需要 |
| 易失性 | 是 | 是 |
| 送行列地址 | 同时送 | 行列分开送 |
| 引脚数量 | 较多 | 较少 |
| 速度 | 快 | 慢 |
| 刷新 | 不需要 | 需要 |
| 集成度 | 低 | 高 |
| 功耗 | 高 | 低 |
| 价格 | 高 | 低 |
线选法
$n$个地址引脚定义$2_n$的地址空间,
- 缺点:译码后输出端的线数量过多
重合法
双译码法 :核心原理类似笛卡尔坐标系,通过“行地址+列地址”的地址对唯一确定存储单元,适用于大容量存储场景。若地址引脚总数为$n$,可将其分为行、列两组地址线(每组$n/2$根),此时译码后的输出引脚数量仅需$2×(n/2) + 1$,相较于线选法大幅减少,尤其适配大容量动态存储器件。
- 地址传输技术差异
- DRAM:采用行列地址复用技术。基于重合法原理,分两次先后将行地址、列地址传入译码驱动电路,可使地址线数量减半,有效降低硬件成本。
- SRAM:采用行列地址独立传输技术,无需地址复用。
DRAM的刷新机制
DRAM依靠电容存储电荷来保存数据,存在电荷泄漏问题,需定期刷新:
- 刷新单位:以行为单位进行整体刷新;
- 刷新周期:电荷保持周期为10~64ms,若未在周期内刷新,电容电荷会流失,导致存储数据丢失。
关键问题:刷新操作期间,DRAM无法响应CPU的读写访问,因此CPU访问内存与内存控制器的刷新操作之间会存在内存争用现象。
集中刷新
前面周期都用来进行读写或者保持工作,后面集中进行刷新
- 优点:读写操作期间不受刷新操作的影响,速度较快
- 缺点:存在较长的死区时间,集中在刷新的读写周期内,CPU较长时间不能访问存储器,行数越多,死区时间越长
分散刷新
将存储周期变为$t_c '$变为$t_c+t_r$(变相增长存储周期)对于每个存储周期前半段用来进行读写或者保持操作,后半段用来刷新
- 优点:不存在长时间的“死区”
- 缺点:刷新过于频繁,严重影响系统的速度
异步刷新
将集中刷新和分散刷新的方式相结合,将128次刷新分散在2ms的时间内,每过一段时间,暂停读写,执行 1 次刷新(刷 1 行)
- 优点:死时间的分布更加分散,避免CPU连续等待过久的时间
- 分散刷新是 “读写必带刷新”—— 只要用存储器,就必须同时承担刷新开销,每个周期都慢;
- 异步刷新是 “读写和刷新分离”—— 大部分时间读写都全速,刷新只在间隙插入,仅插空时影响。
动态存储器的刷新按行进行,为了减少刷新周期,可以减少存储矩阵的行数,增加列数
只读存储器ROM
-
掩模式只读存储器MROM:在芯片生产过程中直接写入,写入后任何人都无法改变
- 优点:可靠性高
- 缺点:灵活性差
-
一次可编程只读存储器PROM:允许用户一次性编程写入程序
-
可擦除可编程只读存储器EPROM:用户可以写入还能进行多次修改,不能取代RAM,因为编程次数有限,而且写入时间过长
-
flash存储器:闪存,支持快速擦出和重写,写入前必须先擦除
-
固态硬盘SSD:基于闪存,价格较高
主存容量扩展
- 存储介质:具有两种明显区别且稳定的物理状态(分别表示0和1) 通常使用半导体材料或者磁化材料,
$存储容量=存储字数(单元数)\times存储字长$
$16k(地址线数目)\times8位(数据线数目)$
- 地址线数目 $2^4 \times 2^{10} = 2^{14}$,地址线位数 $n = \log_2(2^{14}) = 14$
- 数据线数目$=8$
位扩展
通过译码器控制扩展后的芯片选通
字扩展
-
线选法:用除片内寻址外的高位地址线连接存储芯片的片选端
- 优点:不需要地址译码器,线路简单
- 缺点:地址空间不连续,不能充分利用系统的存储器的空间
将$16K \times 8bit$扩展为$64K \times 8bit$:
第一片:最低地址:1110 00 0000 0000 0000 最高地址:1110 11 1111 1111 1111
第二片:最低地址:1101 00 0000 0000 0000 最高地址:1101 11 1111 1111 1111
第三片:最低地址:1011 00 0000 0000 0000 最高地址:1011 11 1111 1111 1111
第四片:最低地址:0111 00 0000 0000 0000 最高地址:0111 11 1111 1111 1111
- 译码片选法:用除片内寻址外的高位地址线通过地址译码器产生片选信号
将16Kx8bit扩展为64Kx8bit:
第一片:最低地址:0000 0000 0000 0000 最高地址:0011 1111 1111 1111
第二片:最低地址:0100 0000 0000 0000 最高地址:0111 1111 1111 1111
第三片:最低地址:1000 0000 0000 0000 最高地址:1011 1111 1111 1111
第四片:最低地址:1100 0000 0000 0000 最高地址:1111 1111 1111 1111
- 高位多体交叉访问存储器(串行):高位地址产生片选信号,选择不同的存储模块;低位地址选择存储模块中不同的存储单元
模块地址+块内地址,读出一个数据的平均时间为$T$
| 模块号 | 地址编址序列 | 对应二进制地址的最低两位 |
|---|---|---|
| M₀ | 0,1,2,3,…7 | 00 |
| M₁ | 8,9,10,11,…15 | 01 |
| M₃ | 24,25,26,27,…31 | 11 |
- 低位多体交叉访问存储器(并行):相邻的地址处在不同的存储体中,同一存储体中地址不相邻
块内地址+模块地址,使得多个模块可以同时工作,读出一个数据的平均时间为$\frac{T+(n-1)r}{n}$,极限值为$r$,读取数据的时间大幅缩短。(要求$T>mr$,以实现流水线的功能)
| 模块号 | 地址编址序列 | 对应二进制地址的最低两位 |
|---|---|---|
| M₀ | 0, 4, 8, 12, …, 4i,… | 00 |
| M₁ | 1, 5, 9, 13, …, 4i+1,… | 01 |
| M₂ | 2, 6, 10, 14, …, 4i+2,… | 10 |
主存
磁盘
由磁盘驱动器、磁盘控制器、磁头、盘片线组成 (从外往里数为0,1,2号磁道),磁道被分为很多扇区
由多个盘片构成,每个盘片分成上下两个盘面,每个盘面有多个圆环构成,圆盘上均匀分布磁介质(用来存储0和1)尽管磁道长度不同,但是每个磁道存储的数据量相同,因此从外到内磁道的位密度逐渐变大,顺时针分扇区,扇区间有扇区间隙,多个磁道号相同的磁道,共同构成一个柱面,柱面号即为磁道号,多个盘片绑在一个电机上,旋转时,盘面会同时旋转。
- 道密度:沿磁道半径方向单位长度上的磁道数
- 位密度:磁道单位长度上能记录的二进制代码位数
如果某文件长度超过一个磁道的容量,应将它记录在同一个柱面上:因为不需要重新找道,数据读/写速度快
-
磁道的容量:
- 非格式化(此记录表面可利用的磁化单元数):$柱面数 \times 盘面数 \times 每条磁道的磁化单元数$
- 格式化(按照某种特定格式存储,如含有校验信息):格式化的容量比非格式化的小,$记录面数 \times 柱面数 \times 每道扇区数 \times 每个扇区的容量$
存取时间=寻道时间(磁头到目的磁道)(取平均时间最外到最内到一半)+旋转延迟时间(磁头定位到读写扇区时间)(平均取旋转半周)+传输时间(传输数据所花费的时间)
CPU➡️磁盘控制器➡️磁盘驱动器➡️磁盘
- $总容量 = 有效记录面数 \times 每面磁道数 \times 每道容量$
- $数据传输率 = 每道容量 \times 转速$
- $平均等待时间=\frac{1}{2 \times n}$
磁盘寻址:记录面号(位) + 磁道号(位) + 扇区号(位)
- 确定访问哪个磁盘组(由多个磁盘构成)
- 确定应该访问哪个柱面
- 确定应该访问到盘面
- 确定扇区
-
磁盘阵列(RAID):用独立磁盘构成具有冗余能力的阵列(0~5分别代表不同的架构与功能)
- RAID0:无数据校验,不提供冗余策略,没有容错能力
- RAID1:无差别写入两份磁盘,分为工作磁盘和镜像磁盘,利用率只有50%,两块当一块使用
固态硬盘(SSD)
与U盘无本质差别,只是容量更大,存取性能更好
-
优点:启动快、抗摔性好
-
缺点:一个块的写入次数不能过多,一般不超过10w次,否则会因为默算而无法再次写入;引入磨损均衡:避免数据重复在某个空间写入,以保证各个存储区域磨损程度基本一致
- 动态:写入数据时,自动选择较新的内存块
- 静态:SSD检测并自动进行数据分配,平常的读写操作在较新的闪存块中进行
高速缓冲存储器
- 时间局部性:同一变量/指令短时间内被多次访问/执行
- 空间局部性:指令顺序执行/数组等连续结构存储体在相邻的位置以短时间内被顺次访问
通过在cache设置有效位,来判断CPU的cache中是否有主存有效信息
CPU在cache中的访问过程
先检查cache中有没有要访问的信息
- 若有,直接从cache读取,即cache命中
- 若无,则从主存中把当前访问信息所在的一个主存块复制到cache中
$命中率=\frac{命中次数}{访问总次数}$
- 命中时,CPU直接在cache中存取信息:$T=T_c$
- 缺失时,需要从主存读取一个主存块送到cache:$T=T_m+T_c$
平均访问时间:$T=pT_c+(1-p)(T_m+T_c)$,由于局部性的特点,cache的命中率可以很高
cache行和主存的映射方式
先将主存高位地址的标记与cache进行比较,若相等且有效值为1则命中直接取出信息;若不相等则CPU从主存中读出信息送到cache任意空闲行中,有效位置1,并设置标记
-
全相联映射:主存可以复制到cache任意行中只要有空闲的cache块
主存标记+块内地址- 优点:冲突概率低,空间利用率高,命中率高
- 缺点:标记比较速度较慢,实现成本较高,要按内容寻址的相联存储器
-
直接映射:映射到特定行
主存标记+cache行号+块内地址- $cache行号=主存块号 \mod cache行数$
-
组相联映射:将cache分成多个组,组内有多行,主存可以放在特定组的任意行(组间采用直接映射,组内采用全相联映射)
主存标记+组地址(cache行号/路数)+块内地址
替换策略
-
随机算法(rand):为依据程序访问的局部性原理,导致命中率较低
-
先进先出(FIFO):选择最高调用的cache行进行替换
-
近期最少使用(LRU)
- 命中时,所命中的行计数器清零,比其低的计数器加一,其余不变
- 未命中且还有空闲行时,新装入的行的计数器置0,其余全加1
- 未命中且无空闲行时,计数值最大的信息被替换,新装入的行的计数器置0,其余加1
抖动:集中访问的存储区超过cache的大小时,命中率变得很低
-
最不经常使用(LFU):将一段时间被访问次数最少的cache行换出
不一致性
写给cache时,会导致主存和cache不一致的问题
-
全写法:写操作时,若写命中,则同时写cache和主存:需要额外引入写缓冲,CPU在将数据写入cache时也写入写缓冲,然后由写缓冲将需要写入的数据写回主存
- 缺点:增加访存次数
-
写回法:写命中时,信息写入cache而不写入主存,直到cache被替换出去时,才将数据写回主存,需要给cache增加
脏位(修改位) -
写分配法:写回主存后,把写入过的主存调入cache中
-
非写分配法:写回主存后,不调入cache
| 命中时 | 未命中时 | 需要 | |
|---|---|---|---|
| 方式一 | 全写法 | 非写分配法 | 写缓冲 |
| 方式二 | 写回法 | 写分配法 | 附设脏位 |
cache分离
-
统一cache:刚出现时指令和数据都放在里面
- 优点:设计和实现相对简单
- 缺点:存取数据又要读指令时会发生冲突
-
独立cache:分开为指令cache和数据cache
- 指令cache(顺序执行)比数据cache(跳转访问)有更好的空间局部性
将cache集成在CPU中称为第一级cache:减少对片外总线的访问,加快存取速度;但由于容量较小,CPU和主存之间设置的cache为第二级cache。
- L1和L2全写法
- L2和主存写回法。
指令
指令字长:一条指令所包含的二进制代码的位数,与机器字长美与固定关系,会影响指令时间开销,操作码+地址码
- 单字长指令:访存一次即可完整取出
- 双字长指令:需要访存两次,耗费两个存取周期
- 半字长指令
指令按地址码分类
-
零地址指令:
OP- 不需要操作数:空操作、停机、关中断指令
- 两个操作数在堆栈计算机中(隐含寻址)
-
一地址指令:
OP+A1- 进行
OP操作后放回原地址:加1、减1、求反、求补、移位 - 将结果存入默认地址如累加器中
- 进行
-
二地址指令
OP+A1+A2A1是目的操作数A2是源操作数,将运算结果存入A1
-
三地址指令:
OP+A1+A2+A3(结果) -
四地址指令:
OP+A1+A2+A3(结果)+A4(下址)
指令长度
操作码随着地址码的减少而增加
- 定长指令字结构:所有指令长度相等
- 变长指令字结构:长度应功能而异,地址指令增加用扩展操作码,各个操作码是前缀编码,任何操作码都不是其他编码的前缀(即通过扫描前几个操作码即可判断是什么指令,不会出现重复)
ISA
指令集体系结构定义了计算机系统中的指令的集合以及这些指令的规范,不关心是什么操作系统以及一些较为细节底层的内容,主要包括:
- 指令格式,寻址方式,操作类型
- 操作数类型,操作数的寻址方式
- 寄存器编号、个数、位数
- 指令执行过程的控制方式
寻址
指令寻址
-
顺序寻址:程序计数器(PC)+1,根据PC的内容取指并执行,自动形成下一跳指令的地址
-
跳跃寻址:程序转移类指令
-
直接寻址
-
相对寻址
-
间接寻址
数据寻址
操作码+寻址特征+形式地址,寻址方式+形式地址=有效地址
-
立即寻址:
OP+#+A,只要取出指令也就取出了可以立即使用的操作数- 优点:操作码和操作数同时去除,不必再次访问主存
- 缺点:操作数是指令的一部分,不能被修改
-
直接寻址:形式地址直接给出就是有效地址
- 优点:不需要任何寻址运算,简单便于硬件实现
- 缺点:寻址范围受限
-
寄存器寻址:给出的是通用寄存器的编号(有效地址就是寄存器的编号),寄存器中存放着操作数
- 优点:从寄存器中存取数据比从主存中快,寄存器数量少,地址码字段比主存单元地址字段短,可以缩短指令长度,提高指令执行速度
- 缺点:造价昂贵,无法提供大量存储空间
-
隐含寻址:不直接给出操作数的地址,而是在指令中隐含着操作数地址(隐含在寄存器中)。
- 优点:指令更短
- 缺点:需要添加额外额硬件来实现
-
间接寻址: 在地址为A的主存单元存储了操作数的有效地址,相当于进行跳转(一级、多级寻址通过间址标志位0、1判断是否已经找到有效地址还是需要继续间接选址)
- 优点:扩大了操作数的寻址范围
- 缺点:增加了访问主存的次数
-
寄存器间接寻址:指令中的地址吗给出的是通用寄存器的编号,在指定的寄存器中存放操作数的有效地址
- 只需要一次访存
-
基址寻址:将基址寄存器内容加上形式地址形成有效地址,面向系统,内容由操作熊确定,其值无法改变
- 隐式:专用基址寄存器
- 显示:通用寄存器
-
变址寻址:将变址寄存器内容加上形式地址形成有效地址,变址面向用户,相当于一个可由用户改变的偏移量,而原有效地址是一个首地址
- 优点:扩大寻址范围,循环中修改偏移量便利数组空间
-
相对寻址:由程序计数器(PC)提供脊椎地址,形式地址作为偏移量
- 优点:操作数的地址与指令地址相差一个固定偏移量,便于程序浮动
-
堆栈寻址:
-
扩展变址寻址:
-
基址变址寻址:
| 寻址方式 | 有效地址 | 访存次数 | 备注 |
|---|---|---|---|
| 立即寻址 | A即是操作数 | 0 | 无需寻址即可获得操作数 |
| 直接寻址 | EA=A | 1 | 无需寻址即可获得操作数 |
| 一次间接寻址 | EA=(A) | 2 | 间接寻址次数越多,访存次数越多 |
| 寄存器寻址 | EA=R₁ | 0 | 速度较快且可有效缩短指令字长 |
| 寄存器间接一次寻址 | EA=(R₁) | 1 | 比一次间接寻址快些 |
| 相对寻址 | EA=(PC)+A | 1 | 常用于转移指令 |
| 基址寻址 | EA=(BR)+A | 1 | 常用于多道程序 |
| 变址寻址 | EA=(IX)+A | 1 | 常用于循环程序和数组问题 |
| 前变址方式 | EA=((IX)+A) | 2 | |
| 后变址方式 | EA=(IX)+(A) | 2 | |
| 基址变址寻址 | EA=(BR)+(IX)+A | 1 | 最灵活的一种寻址方式 |
| 软堆栈 | 需要专门的寄存器保存栈顶 | 1 | 成本低、容量大、速度慢 |
| 硬堆栈 | 无需栈顶指针 | 0 | 成本高、容量小、速度快 |
| 隐含寻址 | 简化地址结构 |
x86
寄存器
-
EAX(32)=E(16)+AX(16)
- AX=AH(8)+AL(8)
-
EAX是扩展累加寄存器(accumulator),通常用于存储操作结果。
-
EBX是扩展基地址寄存器(base),可以在内存寻址时存放基地址。(基址寄存器)
-
ECX是扩展计数寄存器(count),是某些指令的计数器。
-
EDX是扩展数据寄存器(data),与EAX经常配合使用。
-
ESI/EDI是扩展源/目标指针寄存器(source index/destination),其中,ESI通常用于存储当前正在处理的源数据(source data)的索引或地址。例如数组访问中使用,以指向数据的来源位置。(变址寄存器)
-
EBP是扩展基址指针寄存器(base pointer),一般用于指示 ESP是扩展堆栈指针寄存器(stack pointer),一般用于指示栈顶。
指令格式
汇编指令:助记符+目的操作数+源操作数
- R[r]表示寄存器r的值
- M[addr]表示内存地址为addr的值
| 操作数类型 | 寻址方式 | 举例 | 值 |
|---|---|---|---|
| 立即数 | 立即数寻址 | 0xff | 255 |
| 寄存器 | 寄存器寻址 | eax | R[eax] |
| 内存 | 直接寻址 | [var] | M[var] |
| 内存 | 寄存器间接寻址 | [eax] | M[R[eax]] |
| 内存 | 基址寻址 | [ebx+4] | M[R[ebx]+4] |
| 内存 | 变址寻址 | [ebx+esi+4] | M[R[ebx]+R[esi]+4] |
| 内存 | 比例变址寻址 | [ebx+eax*4+3] | M[R[ebx]+R[eax]*4+3] |
常用指令
MOV指令
mov 目的操作数, 源操作数;将源操作数复制到目的操作数,源操作数内容不变 (;为注释标识符,用于解释代码,不会对指令执行产生影响)
mov <reg>, <reg>;将一个寄存器的内容移动到另一个寄存器。mov EAX, EBX;将EBX寄存器的内容复制到EAX寄存器
mov <mem>, <reg>;将寄存器的内容移动到内存地址。mov DWORD PTR [ECX], EAX;将EAX寄存器的内容复制到ECX指向的内存地址
mov <reg>, <mem>;将内存内容移动到寄存器。mov EBX, DWORD PTR [EAX];将EAX指向的内存地址的内容复制到EBX寄存器 (PTR操作符放在内存操作数之前指明其位数)BYTE PTR:表示操作数为单字节WORD PTR:表示操作数为字(双字节)DWORD PTR:表示操作数为双字(四字节)
mov <mem>, <con>;将一个常量移动到内存。mov DWORD PTR [EBP+4], 12345;将常量12345存储在EBP加上偏移4的内存地址
mov <reg>, <con>;将一个常量移动到寄存器。mov EDX, 0FFh;将立即数0FFh(即255的十六进制表示)赋值给EDX寄存器
mov指令的两个操作数不能同时是内存
add/sub指令
将目的操作数与源操作数相加减并将结果报存在目的操作数种,源操作数保持不变
add/sub+源操作数+目的操作数
add/sub <reg>,<reg>两个寄存器add/sub <reg>,<mem>寄存器和内存add/sub<reg>,<con>寄存器和内存add/sub <reg>,<con>寄存器和常量add/sub <mem>,<con>内存和常量
inc/dec指令
inc/dec <reg>自增自减
imui指令
- 两个操作数:两数相乘结果报存在第一个操作数中
- 三个操作数,二、三相乘结果保存在第一次操作数中
and/or/xor指令
add/or/xor 目的操作数 源操作数
not指令
not 操作数
neg指令
neg 操作数 取相反数
shl/shr指令
shl/shr 操作数1 操作数2逻辑左移和右移shl eax 1;将eax左移1位置shr ebb,cl;将ebx右移n位
cmp/test指令
只设置条件码而不改变操作数
cmp比较两数大小cmp eax,ebx不改变值,只影响状态标志
test进行逻辑与
无条件转移指令
jmp <label>代码跳转到<label>执行
1 | |
1 | |
调用子程序
1 | |
1 | |
Jcondition指令
结合cmp使用的条件转移指令
| 指令 | 跳转条件 | 跳转描述 |
|---|---|---|
je/jz |
ZF | 相等/零 |
jne/jnz |
ZF | 不相等/非零 |
js |
SF | 负数 |
jns |
SF | 非负数 |
ZF(Zero Flag)零标志SF(Sign Flag)符号位标志
1 | |
转换
if-else语句
1 | |
1 | |
for循环
1 | |
1 | |
AT&T格式
和Intel同用于编写x86汇编程序,只是两种不同的语法风格
| AT&T格式 | Intel格式 |
|---|---|
mov $100,%eax |
mov eax,100 |
mov %eax,&ebx |
mov ebx,eax |
mov %eax,(%ebx) |
mov [ebx],eax |
-
AT&T只能用小写字母,Intel对大小写不敏感
-
AT&T第一个为源操作数,第二个为目的操作数
-
AT&T寄存器需要加前缀
%,立即数需要加前缀$ -
内存寻址时,AT&T用
(),Intel用[] -
复杂寻址时,
disp(base, index,scale)分别表示偏移量、基址寄存器、变址寄存器、比例因子,如8(%edx,%eax,2),表示M[R[edx]+R[eax]*2+8]
CISC && RISC
-
CISC(复杂complex指令集计算机)
- 指令复杂、长度不固定
- 使用频度、执行时间相差大
- x86
-
RISC(精简reduced指令集计算机)
- ARM、MIPS、RISC-V
- 指令简单、长度固定
CPU
指令周期:一条指令从取出到执行完成所需要的时间。指令周期通常用若干个CPU周期来表示,CPU周期又称为机器周期。一个CPU周期有包含若干个时钟周期(T周期、处理操作的基本单位)
| CPU工作周期 | 目的 |
|---|---|
| 取指周期 | 取指令 |
| 间址周期 | 取操作数有效地址(当指令中地址需要间接寻址时) |
| 执行周期 | 取操作数,存操作数(jmp x可跳过) |
| 中断周期 | 保存断电(IO有中断请求时) |
1 | |
数据通路
寄存器之间传送信息的通路
寄存器传递语言RTL
- 用
(r)代表寄存器r的内容 - 用
M(add)代表主存单元addr的内容 - 用
(A)->B或B<-(A)表示数据传送,其中A为源操作数,B为目的操作数 - 程序计数器
(PC)表示其内容
单周期处理器
- 一条指令从头到尾,在1 个时钟周期内完成(CPI=1)。
- 时钟周期的时长,得按 “最复杂指令的执行时间” 来定(要等最慢的步骤做完)。
- 一个时钟周期内,控制器的控制信号不能变。
多周期处理器
- 一条指令拆成多个步骤,每个步骤用 1 个时钟周期(CPI>1)。
- 不同指令可以按 “自身复杂程度” 安排时钟周期数(简单指令用的周期少,复杂的用的多)。
- 时钟周期时长按 “单个步骤(比如一次存储器读写)” 的时间来定,不用迁就最复杂指令。
CPU控制器模型
1. 硬布线控制器
整个过程是纯硬件电路的即时响应, 没有中间的软件 / 微程序层,硬件电路同时接收三类信号:
- 指令译码信号:由指令寄存器中的操作码
OP,经指令译码器翻译得到; - 时序信号:由时序发生器产生的机器周期(如取指 / 执行周期)、节拍信号(周期内的时间片);
- 反馈信号:来自执行单元的标志位(如运算结果是否为零相当于
if语句的条件)、I/O 的状态等。
上述信号输入到硬布线控制器组合逻辑单元,通过预先设计的门电路,直接进行硬件层面的运算。
2. 微程序控制器
- 把机器指令拆成微程序:每条机器指令对应一段 “微程序”(由多个 “微指令” 组成),每个微指令包含若干 “微命令”(对应具体硬件动作)。
- 从控制存储器读微程序:控制存储器(专门存微程序的硬件)根据当前机器指令的操作码,读出对应的微程序。
- 按微指令发控制信号:时序发生器定节奏,按顺序执行微程序里的微指令,每个微指令输出对应的微命令,指挥硬件完成微操作。
取指等公共阶段被封装,实际上只需要实现执行阶段。
流水线
假设有五个功能:
-
吞吐率:单位时间内能完成的指令数,$T_p=\frac{n}{T_{max}\times(n+4)}$
-
CPI:每条指令的时钟周期数,$CPI =\frac{n}{n+4}$
-
流水线加速比:$S_p=\frac{n\times m\times \Delta t}{m\times \Delta t+(n-1)\Delta t}=\frac{n\times m}{m+n-1}$
总线
多个部件之间采用总线连接的方式,可大大降低部件间互联的复杂性,大幅度减少连接的数量
性质
- 分时:在任何时刻只可以有一个部件向总线上发送消息
- 共享:可以有一个或多个部件接收消息
类型分类
-
内部总线:CPU内部连接各寄存器、ALU 运算部件之间的总线
-
系统总线:CPU同其他计算机系统的其他高速功能相互连接的总线
- 数据总线:传输数据、指令、终端类型
- 地址总线:源数据、目的数据所在的主存单元或I/O端口的地址,单向传输总线,反映寻址空间
- 控制总线:传输命令、反馈信号,总线请求/允许、中断请求/回答、存储器读写(命令相对指令更简单)
-
I/O总线
传输方式分类
- 串行总线:一条双向或两条单向,适合长距离通信
- 并行总线:实现多比特位的同时传输
- 缺点:信息位有延迟,数据线之间相互干扰造成传输错误,适合近距离通信
系统总线
-
单总线结构:将CPU、主存、I/O设备挂在一组总线上
- 优点:结构简单、成本低、易于接入新设备
- 缺点:带宽低、负载重、不支持并发传送
-
双总线结构:
- 主存总线:用于在CPU、主存、通道之间传送数据
- I/O总线:在多个外部设备和通道之间传送数据(I/O接口连接,通过I/O通道与主存总线连接交换数据)
- 优点:将低速I/O设备从单总线上分离出来
- 缺点:增加通道硬件设备
-
三总线结构:在双总线的基础上增加了DMA总线形成的
- DMA总线:用于在内存和高速外设之间传送数据
- 优点:提高I/O设备性能,更快响应命令、提高系统吞吐量
- 缺点:任意时刻只能使用一种总线
- DMA总线:用于在内存和高速外设之间传送数据
数据传送方式
- 非突发传送:每个周期内都是先传地址在传数据(每次只传一个数据)($2n$个周期)
- 突发(猝发)性传送方式:传送首地址,然后可以传输多个连续单元的数据($1+n$个周期)
I/O系统
I/O核心寄存器
三者数据都通过数据线传输
- 数据缓冲寄存器(数据端口):暂存 CPU / 内存与外设间的数据,CPU 可读写。
- 状态寄存器(状态端口):记录接口 / 设备状态,CPU 仅能读(获取外设状态)。
- 控制寄存器(控制端口):保存 CPU 对外设的控制命令,CPU 仅能写(向外设发指令)。
I/O端口及其编址
-
统一编址:外部设备地址与内存地址统一编址,通过不同的地址区域来进行划分。不需要设置专门的I/O指令。采用
Load/Store访存指令就可以访问外部设备- 优点:更加灵活方便,共享访存指令的寻址方式和保护机制
- 缺点:占用了主存空间的地址,减少了主存可用容量;译码过程更加复杂,降低寻址速度
1 | |
-
独立编址:I/O映射方式,对主存空间和I/O端口地址分别进行编址,地址范围可以重叠,需要专门的I/O指令来表明访问的是I/O地址空间
- 优点:I/O端口只需要少量地址线,译码更加简单,寻址速度更快;指令更加清晰,便于理解和检查
- 缺点:专门的I/O指令只包含简单的传输操作,降低了程序设计的灵活性,而且CPu需要分别提供专门的读写命令,总线控制逻辑更加复杂;需要专门的硬件保护措施
1 | |
程序查询
1 | |
-
优点:设计简单、硬件少
-
缺点:CPU要花费很多时间来查询和等待
I/O控制方式
程序查询方式
-
独占查询:设备启动后,CPU 全程循环查询外设状态,直到设备就绪。
- CPU 100% 时间用于 I/O 轮询,和外设完全串行工作;
- 实现简单,但CPU 资源浪费严重
-
定时查询:CPU 启动设备后,通过定时中断周期性查询状态,期间可运行其他程序。
- CPU 可以并行运行其他任务,资源利用率比独占查询高
中断方式
不能使用I/O中断的情况:外设数据传输速率远大于CPU速率。即外设刚把缓冲寄存器填满,CPU 还没来得及处理,外设又要传新数据了,旧数据会被新数据覆盖,直接丢失。
DMA方式
Direct Memory Access :让外设和内存直接传数据,不用经过 CPU
- 预处理:CPU 初始化 DMA 控制器,随后继续执行原程序。
- 发请求:I/O 设备就绪后,向 DMA 控制器发 DMA 请求。
- 争总线:DMA 控制器向 CPU 请求总线控制权。
- 传数据:CPU 让出总线,DMA 控制器直接控制 I/O 与内存传输数据。
- 后处理:传输完成,DMA 控制器发中断请求;CPU 收请求后,执行中断服务程序做数据校验等收尾工作。
- 整个数据块传送过程都不需要CPU的参与,CPU只在最初的DMA控制器初始化和最后的DMA结束处理时才介入,用于I/O的开销非常小
DMA和CPU冲突
-
停止访存:当 I/O 设备有 DMA 请求时,DMA 接口让 CPU 暂停访存、交出总线控制权,直到 DMA 传完数据再归还。
- 优点:控制简单,适合高速 I/O 设备成组传数据
- 缺点:DMA 工作时 CPU 基本闲置。
-
周期挪用:因 I/O 访存优先级更高,I/O 会 “挪用” 1 个存取周期传 1 个数据后立刻释放总线(单字传送)。
- CPU 不访存则无冲突;
- CPU 正在访存则等其周期结束再让总线;
- 二者同时访存则 CPU 暂时让权。
- 优点:兼顾 I/O 传送与 CPU、主存效率
- 缺点:每次挪用都要申请、建立和归还总线控制权
- 适合 I/O 请求 “不规律、速度中等” 的设备(比如打印机),按需借用不浪费资源。
-
DMA和CPU交替访存:把 CPU 工作周期分成两个时间片,分别给 CPU 和 DMA 轮流访存(适用于 CPU 周期长于主存存取周期的情况,轮流时间固定)。
- 优点:无需申请 / 归还总线,通过分时控制总线使用权
- 缺点:硬件逻辑复杂
| 对比维度 | 中断方式 | DMA 方式 |
|---|---|---|
| 程序影响 & 资源占用 | 是程序切换,需保护 / 恢复现场,占用 CPU 资源 | 不中断现行程序,无需保护现场,仅预处理 / 后处理占用 CPU |
| 请求响应时机 | 仅在每条指令执行结束时响应 | 可在任意机器周期结束时(取指、间址、执行周期后)响应 |
| CPU 干预情况 | 传输过程需要 CPU 干预 | 传输过程无需 CPU 干预,速率高,适合高速外设成组传输 |
| 请求优先级 | 优先级低于 DMA 请求 | 优先级高于中断请求 |
| 功能范围 | 可处理异常事件 | 仅局限于大批数据传送 |
| 数据传送方式 | 依靠程序传送 | 依靠硬件传送 |
中断优先级
-
响应优先级:当多个中断源同时请求时,CPU 按固定的硬件线路规则,先响应优先级高的中断、后响应优先级低的中断,是 CPU 响应设备中断请求的先后次序。(使用优先编码器实现)
- 大类优先级:不可屏蔽中断 > 内部异常 > 可屏蔽中断
- 内部异常细分:硬件终止(最高)> 指令异常 / 自陷等程序故障
- 传输类中断:DMA 中断请求 > I/O 设备传送的中断请求
- I/O 传送类细分:高速设备 > 低速设备;输入设备 > 输出设备;实时控制设备 > 普通设备
-
处理优先级:CPU 执行某中断服务程序时,可响应更高优先级的中断请求,即中断嵌套
- 通过配置个设备中的中断屏蔽值,可以动态改变处理优先级的次序(不能改变中断响应优先级)
Verilog语言
事实上我们已经有了硬件描述语言ahdl的基础,verilog上手并不困难,因此在这里罗列一些基本的例子,简单阅读后即可了解个大概,然后再对特别的语法部分进行针对性讲解!
- 四位二进制加法计数器
1 | |
always语句
只有满足激活条件才能被执行,其中赋值目标必须是reg型,如果有多条赋值语句则必须使用begin和end包裹(相当于if语句中的{})
- 边沿敏感:
(posedge 信号名)信号上升沿到来(negedge 信号名)信号下降沿到来
- 电平敏感:
(信号名列表)信号列表中的任一个信号有变化
阻塞赋值 vs. 非阻塞赋值
激活前:M1=0,M2=0,Q=0,设A、B同时由0变为1。
1 | |
阻塞赋值的特点是赋值语句执行完,变量的值立刻更新,后面的语句要等前面的 “阻塞” 结束才能执行,像 “排队办事,一个办完下一个来”。
步骤拆解(A、B 变 1 后):
- 第一步:
M1 = A→ A 现在是 1,所以M1立刻变成1; - 第二步:
M2 = B & M1→ B 是 1,M1 已经是 1,所以M2立刻变成1&1=1; - 第三步:
Q = M1 | M2→ M1=1、M2=1,所以Q立刻变成1|1=1;
最终结果:M1=1、M2=1、Q=1。
1 | |
非阻塞赋值的特点是赋值语句先 “暂存操作”,等整个begin-end块里的语句都执行完,再统一更新所有变量的值,像 “先把所有订单记下来,最后一起发货”。
步骤拆解(A、B 变 1 后):
- 第一步:
M1 <= A→ 暂存 “M1 要变成 1”,但现在 M1 还是原来的 0; - 第二步:
M2 <= B & M1→ B 是 1,但 M1 还是 0,所以暂存 “M2 要变成 1&0=0”; - 第三步:
Q <= M1 | M2→ M1=0、M2=0,所以暂存 “Q 要变成 0|0=0”; - 等整个块执行完,统一更新:先把 M1 改成 1,再把 M2 改成 0,最后把 Q 改成 0;
最终结果:M1=1、M2=0、Q=0。
- 设计组合电路时常用阻塞赋值
- 设计时序电路时常用非阻塞赋值
模块例化
- 底层模块
1 | |
- 顶层模块:对底层模块进行实例化,相当于C++的类进行实例化调用(这里叫端口映射)
1 | |
事实上,这里的端口映射使用了两种方法,其实按照函数传参的方法看即可也比较方便,符合阅读习惯
-
命名法:
(.底层端口名1(外界信号名1),.底层端口名2(外界信号名2)) -
顺序法:
(外界信号名1,外界信号名2)
底层模块门原语
这是Verilog语言提供的已经设计好的门,可以直接调用,其中实例名可以忽略,且只能采用顺序法,输出在前,输入在后:and(out,in1,in2)。
真题拟合
CPU的组成:由算术逻辑运算单元、操作控制器组成。
- ALU:算术逻辑运算单元。执行算术运算、逻辑运算并测试
- 操作控制器:协调和指挥整个系统的操作,取指令并执行。
- A和B:运算器前端的数据暂存器,也称运算寄存器,用来暂存参加运算的操作数
- R0~R3:CPU的通用寄存器组,存放操作数。
- IR-指令寄存器器:保存当前正在执行的指令的指令码 Instruction Register
- PC-程序计数器:其保持的总是将要执行的下一条指令的地址,由于大多数指令都是按顺序来执行的,所以修改的过程通常只是简单的对PC加1。
- AR—地址寄存器:用来保存当前CPU所访问的内存单元的地址(指令地址或操作数地址) Address Register
- DR—数据(缓冲)寄存器:用来暂存写入内存单元的数据及从内存单元读出的数据 Data Register
指令周期流程图:
1 | |
$按字编址的寻址单元数 = 总字节数 \div 每字字节数$
- 程序查询方式中,主机需不断轮询设备状态,设备未准备好时主机等待,因此主机与设备是串行工作的;
- 中断、DMA、通道方式下,主机可在设备传输时执行其他任务,属于并行 / 半并行工作
补码比原码 / 反码多表示一个最小负数(8 位补码中,10000000 表示 - 128,而原码 / 反码中10000000无合法数值含义)
隐指令是指令系统中没有的指令,由硬件自动执行
- 静态微程序控制器的微程序存储在 ROM(不可改写)中;
- 动态微程序控制器的微程序可存储在 EPROM(可擦写改写)(速度较慢,无法替代RAM高速读写的需求)中,支持微程序的修改与更新
16 位浮点数需平衡范围(阶码)与精度(尾数):
- 阶码过短(范围太小)
- 尾数过短(精度不足)
流水线的每个时钟周期是统一的固定值,时钟周期必须能覆盖耗时最长的那个过程段
- 多重中断的中断服务程序:
- 保护断点;
- 保护现场;
- 开中断;
- 执行中断服务程序
同步通信和异步通信的主要区别是前者有公共时钟,总线上的所有设备按统一的时序,统一的传输周期进行信息传输,通信双方按约定好的时序联络。后者没有公共时钟,没有固定的传输周期,采用应答方式通信,具体的联络方式有不互锁、半互锁和全互锁三种。不互锁方式通信双方没有相互制约关系;半互锁方式通信双方有简单的制约关系;全互锁方式通信双方有完全的制约关系。其中全互锁通信可靠性最高。
- 顺序存储器:$t_1=mT$
- 交叉存储器:$t_2=T+(m-1)\tau$
祖传大题
- 浮点数运算
- cache 映射,字、位扩展
- 指令格式
- cache 命中率
- 磁盘容量、时间计算
- 程序执行流程框图
| 特性 | 程序查询方式 | 程序中断方式 |
|---|---|---|
| CPU 工作方式 | CPU 主动循环查询设备状态,直到设备准备好 | 设备准备好后主动向 CPU 发送中断请求,CPU 在执行完当前指令后响应 |
| CPU 利用率 | 低(查询期间 CPU 无法做其他工作) | 高(CPU 可在设备准备期间执行其他任务) |
| 响应延迟 | 大(可能需要等待一个完整的查询周期) | 小(设备准备好后立即触发中断,无额外等待) |
| 实时性 | 差(无法及时响应设备的紧急请求) | 好(可优先响应高优先级中断) |