计算系统基础知识点复习整理

整理者:ErinwithBMQ

# 第六章

  1. 原码反码补码计算:正数的三个码都一样;负数的反码补码才和原码不一样,反码直接取反,补码取反加 1

  2. 负数二进制位数扩展是在前面加 1

  3. 32 位 IEEE 标准浮点数:第 31 位为符号, 23~30 位(共 8 位)为指数(转化为无符号整数,然后减 127,即为 2 的多少次方), 0~22 位(共 23 位)为尾数,即 1.…… 后面的省略号部分。如果想正常表示一个数,符号位既不能最大(为 255,所有位都是 1),也不能最小(0)。

  4. 非规格化浮点数(指数位全为 0):2 的次方:1 - 127 =-126;隐藏位为 0,即为 0.……。用这个方式可以表示小于 2^-126 的数字

  5. 64 位 IEEE 标准浮点数:第 63 位为符号, 52~62 位(共 11 位)为指数(减 1023); 0~51 (共 52 位)为尾数。

  6. 将十进制小数转换为 IEEE 标准浮点数

(1)先将小数写成普通二进制(如果是负数,写其绝对值,在后面转化为浮点数时将最高位设成 1 即可)。

(2)将普通二进制转化为规格化二进制,如 00101101.1101 -> 1.011011101 * 2^5

(3)将规格化二进制转化为 32 位 IEEE 标准浮点数。

  1. 1.11111111111111111111111(二进制)约等于 2

# 第七章

  1. 与运算 A・B,或运算 A+B (・可省去)

  2. 德摩根定律及其他定律

image1.png

分配律,吸收律,德摩根定律,其他恒等式重要。其实除了德摩根,其他三个都能通过上面基本的推出来

  1. 按位取反:与 11111111 作按位异或运算

  2. C 语言中的位运算符:& 与运算,| 或运算,~ 非运算,^ 异或运算,<<左移,>> 右移

  3. 算数 / 逻辑左移、逻辑右移都是用 0 填充;算数右移,正数用 0 填充,负数用 1 填充

  4. 运算符优先级:~ 非运算 >>>/<<左移右移>& 与 >^ 异或 >| 或

  5. NMOS 晶体管漏极接正极 VDD,源极接负极 VSS;PMOS 与其相反。NMOS 接入正电压导通,PMOS 接入负电压导通。PMOS 管的栅极会加个圆

  6. 一般都是栅极输入漏极输出,源极接电源正极或接地

非门:上下 PMOS 与 NMOS 管相连

或非门:顶部两个 PMOS 管串联,下面两个 NMOS 管并联

或门:在或非门输出前再加一个非门

与非门:顶部两个 PMOS 管并联,下面两个 NMOS 管串联

与门:在与非门输出前再加一个非门

符号表示:

image2.jpeg

  1. 译码器:输入少,输出多。n 个输入,2^n 个输出。如 2-4 线译码器,3-8 线译码器,只有一个输出有效

  2. 多路选择器:n 条选择线, 2^n 个输入。由选择信号 S 决定哪个输入连接到输出。上面 2^n 个与门,下面一个或门。与门前非门情况不同(主要区分在这)

  3. 加法器:(1)半加器:两个输入,两个输出(S 表示和,C 表示进位),分别是一个异或门和一个与门。符号是求和号加 CO

(2)全加器:三个输入,两个输出(S 表示和,C 表示进位)。上面两个异或门,AB 异或完的结果与 C 再异或;下面两个与非门,AB 与非,AB 异或结果与 C 与非,二者再与非一次。符号是求和号加 CO 加 CI

  1. 数值比较器:

image3.png

左边两个是非门

  1. 用与或非表示异或与与或:

image4.jpeg

  1. R-S 锁存器:由两个与非门(或者或非门)组成。工作原理是设置 R、S 来控制电路状态。

R:复位引脚 S:置位引脚。有两个输出 a、b(重点看 a)

image5.png

S:1 R:1 :保持状态(保持现有 a 的值)

S:1 R:0 :“复位 / 置 0” 状态(将 a 变为 0)

S:0 R:1 :“置位 / 置 1” 状态(将 a 变为 1)

S:0 R:0 :错误

如果是两个或非门:SR 都为 0 时保存 a,都为 1 时错误。其他相同。

  1. 门控 D 锁存器:输入控制门电路(两个与非门)+ R-S 锁存器。

两个输入:WE 与 D

WE = 1 时,输出(a) = D;WE = 0,S = R = 1,输出状态不变(保持 a 的值)

image6.png

  1. 主从 D 触发器:由两个门锁 D 锁存器构成

  2. 时序逻辑电路:找有几个状态,以及到各个状态的条件

# 第八章 冯・洛依曼模型

  1. 冯・洛依曼模型

  2. 组成部分

image7.png

处理单元与控制单元是 CPU 的主要组成部分

  1. 存储器(RAM):包括基本存储原件、寄存器与主存储器,其中寄存器读取速度最快。

寻址能力:存储在每一个单元中信息的位数。

2^32×8 位:一共有 2^32 个存储单元(地址空间,唯一可识别的单元总数),每个存储单元可以存 8 位(寻址能力,8 位为字节可寻址)。总量 4GB

SRAM:静态随机访问存储器,供电状态下能一直保存;DRAM:动态随机访问存储器,需要不断刷新,而且关机会丢失数据。

・访问其存储器的一个单元需要 n 位 / 使用 n 位地址:地址空间为 2^n

・8 位为 1 字节;4 字节为 1 字长(DLX 指令集)

  1. 4×2 位存储器实例

image8.jpeg

(1)4×2 位:存储空间为 4(4 个单元),寻址能力为 2 位(一个单元里有 2 位数据)

(2)注意谁是地址线,谁是字线

(3)有一个译码器和两个多路选择器

(4)

A:地址,选择存入 / 输出哪个地址的内容

WE:1 为存储数据,0 为读取数据

D:输入 Q:输出

  1. 处理单元

  2. 算术与逻辑处理单元 ALU:ALU 一次正常处理的信息量大小通常被称为计算机的字长,每一次被处理的元素被称为一个。每一个指令集结构都有自己的字长。DLX 是 32 位(4 个字节)

  3. 寄存器堆 / 文件 Reg:功能是临时存取数据,因为其读取速度很快;每个寄存器都包含一个字。

  4. 控制单元 PC

  5. 功能:指挥信息的处理;跟踪指令的执行

  6. PC:程序计数器 / 指令指针。控制单元中容纳下一条指令所在地址的寄存器。功能是跟踪要处理的下一条指令。

  7. 输入 / 输出设备:外围设备

  8. DLX 示例

  9. 总线结构,多时钟周期

  10. 寄存器(32 位):寄存器堆 / 文件,程序计数器 PC,指令寄存器 IR

  11. 多路选择器:有 DRMUX,AMUX,BMUX

  12. 总线:由 32 根线和相关电子元件组成。允许传输 32 位信息,一次只可传输一个值

  13. 存储器:MAR,主存地址寄存器,保存目的位置或数据来源位置的地址;MDR,主存数据寄存器,保存被写入地址或地址单元读入的数据(都是 32 位,一个字长)。

  14. 存储器是 2^32 个存储单元,字节可寻址。

简单来说就是,MAR 存地址,MDR 存地址中对应的数据(要么是以其地址开头连续四个单元的数据,要么是 8 位扩展成 32 位)。如果要写入数据,那就是将 MDR 中的数据写入 MAR 存的地址对应的存储单元里

  1. 处理单元: ALU 与寄存器堆。有 32 个整数寄存器,32 个浮点寄存器(DLX 子集没有这个)

  2. 控制单元:①有限状态机,一个输入是 CLK,说明每个时钟周期持续的时间。②指令寄存器 IR,保存正在处理的指令,同时也是有限状态机的一个输入。③程序计数器 PC,记录下一条要被执行的指令所在的地址

  3. 实心箭头:数据元素;空心箭头:控制信号

  4. 输入 / 输出设备:键盘:数据寄存器 KBDR,状态寄存器 KBSR;显示器:显示寄存器 DDR,状态寄存器 DSR。详见第十二章

# 第九章 指令集结构

  1. 指令集结构

  2. 指令集结构 ISA:操作码+操作数。

操作码:让计算机执行的操作。DLX 中分为算数 / 逻辑运算指令,数据传送指令,控制指令,浮点指令四种(按功能分)。

操作数:数据类型;DLX 中的寻址方式 —— 基址+偏移量

  1. DLX 指令操作类型:共 64 种指令类型,由 [31:26] 位定义(6 位),其中又分为 R 类型、I 类型、J 类型,总共有 91 条指令。

  2. R 类型指令:[31:26] 位为 000000,[5:0] 位定义了函数,共 64 中可能的函数

  3. 算数 / 逻辑运算指令:对整数进行处理;共有 37 个算术逻辑运算指令;除 LHI 加载高位立即数指令外,其他都是进行的二元运算,即两个源操作数和一个目标操作数

第一个源操作数:来自 32 个整数寄存器,[25:21] 位对应寄存器,SR1。如 R1 即为 00001,R5 即为 00011。

第二个源操作数:I 类型(立即数类型):[15:0] 位直接读取立即数(补码);R 类型:[20:16] 位对应寄存器,SR2。

目标操作数:I 类型:[20:16] 对应寄存器,DR;R 类型:[15:11] 位对应寄存器,DR。(SR1、SR2、DR 可以相同)

ADDI:使用立即数的相加指令。将 SR1 内数值与立即数相加存入 DR 中

SUBI:使用立即数的相减指令。将 SR1 内数值与立即数相减存入 DR 中

ANDI:使用立即数的与运算指令。将 SR1 内数值与立即数进行与运算存入 DR 中

ORI:或运算

XORI:异或运算

SLEI:设置是否小于等于操作。若 SR1 中数值小于等于立即数,则 DR 设为 1,否则为 0

SLTI:设置是否小于操作。若 SR1 中数值小于立即数,则 DR 设为 1,否则为 0

SEQI:设置是否相等条件操作

SRAI:算术右移立即数操作。将 SR1 中数值立即右移立即数对应的位数存入 DR。注意负数是补 1。可用来表示一些除法如除 2 除 4 等

SRLI:逻辑右移立即数,道理同上,不过负数补 0

SLLI:左移立即数。用来表示乘法

LHI:加载高位立即数指令。没有 SR1(全为 0),只有 DR。将立即数左移 16 位后加载至 DR 中。如立即数原来为 x1234(本来就只有 16 位),左移 16 位变为 x12340000 加载至 DR 中。(DR 是 32 位的)

  1. R 类型操作指令:将上面的立即数全部变为 SR2 内存的数值,去掉 I(如 ADD、SUB)

除 LHI 指令,其他运算指令均有 I 类型和 R 类型

  1. 数据传送指令:基址寄存器 + 偏移量

LW:字加载指令。将 SR1 内数值加上立即数得到一个地址,将以该地址为起始地址的连续四个单元内的数值(一个字)加载至 DR 中。

LB:字节加载指令。将 SR1 内数值加上立即数得到一个地址,将以该地址内的数值(一个字节)加载至 DR 中。前面不足的位数补全(负数应该还是用 1 补吧?)

SW:字存储指令。将 SR1 内数值加上立即数得到一个地址,将 DR 中的数值(一个字)存储到以该地址为起始地址的连续四个单元中。

SB:字节存储指令。将 SR1 内数值加上立即数得到一个地址,将 DR 中的最低八位(一个字节)存储到以该地址对应的单元中。

  1. R0:绝对地址。里面的数值只能全是 0,不可以改变

  2. 边界对齐:LW、SW 指令里基址+偏移量的地址必须是 4 的倍数(因为加载存储的是字)

另外,地址用十六进制表示,立即数是二进制,加的时候注意一下

  1. 运算指令与数据传送指令每次使 PC+4. 因为一条指令占用 4 个存储单元(一个存储单元 8 位,一条指令 32 位)

  2. 控制指令:改变被执行的指令的顺序

①条件分支:仅使用 SR1。分为 BEQZ(等于 0 时分支)和 BNEZ(不等于 0 时分支)

取指令阶段:PC+4(这时 PC 已经是下一条指令的地址了)

译码 / 取寄存器:接着计算 PC(已经加过 4)+ 立即数,得出目标指令地址

完成分支阶段:BEQZ:若 SR1 为 0,则将上一步得到地址加载至 PC;若 SR1 不为 0,PC 不变,正常进入下一条指令。(BNEZ 与其相反)

②无条件跳转指令:JR 指令与 J 指令

JR:DR、立即数全为 0,仅使用 SR1。将 SR1 内的数值加载到 PC

J:[25:0] 的数值+4+PC-> PC

③TRAP 指令:改变 PC,是它指向属于操作系统的某部分的存储地址,作用是让操作系统执行一些任务 —— 调用服务例程。(见后面章节)

  1. DLX 指令处理

image9.png

存储器:地址空间 2^32(即 4G)个单元。地址标识符是 32 位二进制,或 8 位十六进制。寻址能力是 8 位。访问字只需访问其起始地址,但需要是 4 的倍数,即边界对齐

  1. 高位优先,字的高位字节放在内存的低地址端。

  2. 寄存器:每一个寄存器中的存储位数是 32 位的字。有 32 个通用寄存器,5 位编码识别。其中,R0 内必须是 0. 还有 32 个浮点寄存器,标记为 F0、F1…… 单精度浮点数一个寄存器,双精度浮点数两个寄存器。

  3. 指令处理:多时钟周期

  4. DLX 指令执行阶段:①取指令 ②译码 / 取寄存器 ③执行 / 有效地址 / 完成分支 ④访问内存 ⑤存储结果。每条指令需要进行其中的 3-5 个阶段

  5. DLX 的有限状态机:每一步都是由控制单元的有限状态机控制,一个周期接一个周期地控制整个程序执行。以时钟周期为单位持续运行指令,停止时钟(运行锁清 0),则停止指令的运行。

  6. DLX 运行示例

  7. 取指令阶段:①PC -> MAR;ALU 中进行 PC+4 的计算 ②PC+4 -> PC;M [MAR] -> MDR ③MDR -> IR

  8. 译码 / 取寄存器阶段:①使用指令的操作码,进行译码,控制指令执行 ②根据指令取寄存器,获得源操作数传给 ALU 的寄存器 A 和寄存器 B③在 ALU 中计算 PC+IR [15:0] 符号扩展的和,将结果存储在 ALUOut 寄存器中(可能该结果没有用,但是还会进行)

  9. 执行 / 有效地址 / 完成分支:三种选择(选择其一):①执行算数 / 逻辑运算,结果存储在 ALUOut 中 ②计算有效地址,结果存储在 ALUOut 中 ③完成分支跳转

  10. 访问内存:(如果要访问内存的话)ALUOut -> MAR;M [MAR](该地址开头四个单元的数据) -> MDR

  11. 存储结果:将结果写到目标(应该是 DR)中

# 第十章 机器程序语言设计

  1. 机器程序语言设计

  2. I 类型指令和 R 类型指令分别的特点:I 类型可以访问内存,但速度较慢;R 类型是寄存器之间的操作,不能访问内存,速度较快

  3. 三种基本结构:顺序、选择、循环

・选择中 J 指令的立即数:子任务 1 的指令数目乘 4

・循环中 J 指令是返回生成条件指令

# 第十一章 汇编语言

  1. 汇编语言

  2. 汇编语言四个部分:标记 操作码 操作数;注释。其中,标记与注释可选。不区分大小写。注释前要加;

  3. 标记:以字母、下划线或 $ 开头,中间可包含下划线、字母或数字,以冒号结尾;操作码作为保留字,不能用做标记。标记用作立即数代表的是这条指令的地址

  4. 操作码:如 ADD,ADDI…… 指令操作码的符号名

  5. 操作数:寄存器则写 R0、R1…… 立即数前面加 #表示十进制,x 表示十六进制,b 表示二进制,如 #10,x16 等。与机器语言不同,汇编指令中 DR 在前面,SR1 在后面

  6. 运算指令

I 类型汇编指令格式:OPCODE DR, SR1, Imm16 立即数也可以是标记

R 类型汇编指令格式:OPCODE DR, SR1, SR2

  1. LHI:LHI DR, Imm16 立即数可以是标记,此时是将标记对应地址的高 16 位值赋给 DR,如地址是 x30001A00,则赋值 x30000000

  2. 数据传送指令:

LW/LB DR, Imm16(SR1)

SW/SB Imm16(SR1), DR

立即数可以使用标记

  1. 控制指令:

BEQZ/BNEZ:OPCODE SR1, LABEL 最后是标记,即目标地址。此时不需要再计算 PC+4 + 立即数。而是符合要求就直接跳转到标记地址

J:J LABEL 直接跳转到标记地址

JR:JR SR1

TRAP:TRAP Imm

  1. 伪操作:以。作为第一个字符

数据区:

①.dataaddress : 将下面的数据放在数据区的某一个地方(address 为其起始地址)

注意,该地址必须是 4 的倍数。

如果不是 4 的倍数:.alignn : 将下面的数据加载到以 n 个 0 结尾的地址里

②.wordword1, word2, ... : 将字 1,字 2,…… 存储在连续的存储单元中

③.bytebyte1, byte2, ... : 将字节 1,字节 2,…… 存储在连续的存储单元中

④.ascii “string1”,“string2”, ... : 将字符串 1,字符串 2,…… 存储在存储器中。.asciiz 与其相似,不同是 .asciiz 会在字符串结尾再存储一个 0.(相当于 C 语言中的 \0)

⑤.spacesize: 预留空间,留出 size 个字节

代码区:

① .textaddress : 将指令放在存储器的某个地方。不是 4 的倍数时也要用.align

②.globallabel : 全局标记,让该标记在其他文件中也可以使用

  1. 汇编过程:“两趟” 扫描:第一趟,标识出符号(标记)对应的二进制地址,建立符号表;第二趟,把汇编指令翻译成机器指令。此时使用地址计数器 LC(它与程序计数器 PC 的不同:LC 是当前地址,PC 是下一条指令的地址)

  2. 立即数是标记的 ADDI 指令,如果地址无法用 16 位的立即数表示,解决方法:翻译成两条指令。

如,addi R1, R0, numbers,numbers 为 x3000000C,将其拆分成两条语句翻译:

LHI R1, x3000

ADDI R1, R0, x000C

注意接下来是 LC+8 而不是 + 4。

立即数是标记的 SW 指令:如 SW sum (R0), R3 ,sum 是 x30000034

翻译成两条指令:LHI R5 x3000 SW x0034 (R5), R3 (使用临时寄存器 R5

LC+8 -> LC

翻译成多条指令后,符号表也需要调整

  1. 寄存器分配规则

image10.png

变量多于寄存器数目时,就要使用存储器。—— 第十四章,栈的存储结构

# 第十二章 输入输出

  1. 输入和输出

  2. ** 键盘和显示器:** 面向流的设备,一个字符一个字符地按顺序读写

  3. 键盘设备寄存器:32 位。KBDR 键盘数据寄存器:只有 [7:0] 用来存放数据(一个字节),其他都是 0;KBSR 键盘状态寄存器:[0] 位,就绪位

  4. ** 显示器设备寄存器:**32 位。DDR 键盘数据寄存器:只有 [7:0] 用来存放数据(一个字节),其他都是 0;DSR 键盘状态寄存器:[0] 位,就绪位

  5. ** 内存映射的 I/O:** 采用内存映射的方式表示 I/O 设备。比如,xFFFF0000——xFFFF0003,不再是存储器里的某个数据的地址,而是代表 KBSR 的地址

  6. R.W=0:加载信号;R.W=1:存储信号(?)

  7. 异步的处理与同步机制:需要状态寄存器。KBSR [0] 为 1 时,键盘不能用;当读取完上一个输入的字符时,KBSR [0] 清 0,允许读入下一个字符。KBSR [0] 为 0 时,代表没有新的字符输入,不进行后面的读取操作。

每当显示器完成了一个字符的显示,就将 DSR [0] 设为 1,允许进行下一个字符的显示;每当处理器正在向显示器写字符时,将 DSR [0] 设为 0,不进行新的显示字符的操作。

  1. 轮询机制:周期性检查状态位。缺点是浪费时间。—— 中断机制的出现

# 第十三章 自陷例程和中断

  1. 自陷例程和中断

  2. 自陷 (TRAP) 指令 —— 系统调用,通过调用操作系统来完成任务

image11.png

  1. TRAP 机制 1—— 服务例程:操作系统的一部分,代表用户执行的一组程序。DLX 有 256 个服务例程。

image12.png

几个常见的:

  1. **TRAP 机制 2——TRAP 向量表:包括了 256 个服务例程的起始地址(实际是代码区的起始地址)** 的表,每个起始地址占用四个存储单元(32 位)。这张表被存储在存储单元的 x0000 0000 到 x0000 03FF 中。

・数据区与代码区:数据区的起始地址在代码区起始地址之前的 x100 个单元

  1. TRAP 机制 3——TRAP 指令:调用操作系统代表用户程序执行某一服务例程,完成后把控制权还给用户程序。根据 TRAP 向量,相应服务例程首地址 -> PC,并且要记得提供返回路径。

TRAP 指令处理:①取指令:PC + 4 -> PC。②译码③计算有效地址:TRAP 向量(26 位)扩展成 32 位,再左移 2 位(乘以 4)④TRAP 向量(计算后) -> MAR,M [MAR] -> MDR。

⑤写回:PC -> R31(提供返回路径),MDR -> PC(开始服务例程)

在 TRAP 服务例程中,最后一条指令是 JR R31,使得控制返回用户程序的正确位置

  1. 寄存器的保存与恢复:①被调用者保存:在服务例程内部的一开始进行保存 ②调用者保存:在调用服务例程前进行保存,一般出现在服务例程内部调用另一个服务例程之前,而且保护的一般是 R31(调用服务例程时会将 R31 改掉)

原则是哪个程序知道哪些寄存器被接下来的操作所破坏,处理问题的就应该是哪一个程序。

  1. 停机服务例程(TRAP x00):MCR [0]:机器控制寄存器,有内存映射地址。要将其清 0

  2. 中断驱动的 I/O:I/O 设备能够强制程序中止,让处理器执行 I/O 设备的请求;请求完成后让停止的程序继续进行。

  3. 中断信号(INT)的产生:满足两个条件:①KBSR,DSR 的就绪位为 1,表示需要服务

②中断允许位(IE),大多数设备中是设备状态寄存器的一部分。设为 1 或 0,取决于是否给其权利去请求服务。

中断请求信号(IRQ)就绪位与 IE 的逻辑与;各个设备发出的 IRQ 经过或门,产生 INT 信号

  1. 原因寄存器(CAUSE):如果某个设备发出 IRQ 信号,就会将原因寄存器的相应位设为 1。作用是记录哪些设备发出 IRQ 信号。CAUSE [15:8] 是中断未决位。

  2. 状态寄存器(SR):SR [0] 表示中断允许位(IE),如果 SR [0] 为 0,那么所有 I/O 设备都不能中断处理器(所有设备的 IE 位都能被 SR [0] 同时改写),在这种情况下只能采用轮询访问 I/O 设备;如果 SR [0] 为 1,那么允许所有 I/O 设备中断处理器。CAUSE 和 SR 都是 DLX 的特殊寄存器,只能在特权模式下(操作系统)访问。

  3. 测试 INT 信号:将指令执行的最后一步改为:写回,并检测 INT 信号。如果 INT 信号为 0,则正常进行下一条指令;若为 1,则保存并改变程序状态,之后将 PC 加载为 x80001000,进行中断服务例程。

・EPC:用于保存中断发生时 PC 中的值

・SR [0]:进入中断服务例程时,为避免来自其他设备的中断信号的干扰,需要将其清 0。所以 SR [0] 也需要保存起来

・SR [1]:表示正在运行的程序处于特权(设为 0)还是非特权(设为 1)模式。当进入中断服务例程时,SR [1] 改为 0. 所以 SR [1] 也需要保存

・中断发生时,SR [2] 保存 SR [0] 的值,SR [3] 保存 SR [1] 的值。

  1. 中断优先级:有 6 个硬件优先级,PL0,PL1,...PL5,数字越高,优先级越高;速度越高的 I/O 设备,优先级越高。最低的优先级下允许所有中断,最高的优先级下屏蔽所有中断。

・DLX 的中断优先级采用 SR [15:8](中断掩码位)表示,与 CAUSE [15:8] 一一对应,从左至右优先级依次降低。CAUSE 中的未决中断要等到相应的屏蔽位为 1 时,才能引起处理器的处理。

  1. 中断服务例程:

①第一项任务:将 CAUSE [15:8] 与 SR [15:8] 进行逻辑与运算,看发生了哪些允许的中断。如果多于一个,则选择优先级高的

②服务该中断

③从中断返回:首先清空 CAUSE 寄存器;接着使用 RFE 指令,将 PC 恢复为 EPC 内的值,SR [0] 恢复为 SR [2] 内的值,SR [1] 恢复为 SR [3] 内的值。

  1. 中断嵌套:

例如,在中断服务例程中进行键盘处理例程时,如果允许被比键盘优先级高的设备所中断,那么在读取 KBDR 之前,要先执行:

①保存 SR,EPC 的值

②将 SR [15:12] 设为 1,SR [11:8] 设为 0,即屏蔽比当前设备优先级低的中断(键盘优先级为 1),允许优先级高的设备的中断。

③将 SR [0] 改为 1,即允许中断

因为改变了 SR [15:8] 和 SR [0] 的值,所以在结束键盘服务例程之前,要先将 SR [0] 设为 0,再将 SR 与 EPC 还原。(使用栈结构存储程序状态)

  1. C 语言中的 I/O:scanf: “% d”,“% lf”,从标准输入流的第一个非空白字符(抛弃掉之前的空白,无论这个找到的非空白是否为数字)开始,找到多位数字(至少一位),以 “非数字” 结束(不抛弃,仍然留在输入流中)。

# 第十四章 子例程

  1. 子例程

  2. ** 调用 / 返回机制:** 计算子例程的起始地址,加载到 PC,并保存返回地址。结束后,使用返回地址加载 PC。与 TRAP 指令相似,R31 被加载返回地址,最后一条指令是 JR R31.

  3. ** 与 TRAP 指令的区别:**TRAP 指令服务例程包括操作系统资源,由系统程序员编写;子例程由相同程序员或其他人编写

  4. JAL 与 JALR 指令(调用子例程指令):

①JAL: J 指令相同,不过多了一步返回地址 -> R31

汇编格式: JAL LABEL

②JALR:与 JR 指令相同,不过多了一步返回地址 -> R31

汇编格式: JALR SR1

  1. 同样要有寄存器的保存与恢复,与服务例程类似。通常使用被调用者保存。注意 R31 的保存

  2. ** 使用子例程,必须知道:** 地址、功能(不需要知道具体实现)、传给子例程的值。返回值。(类似 C 语言函数)

  3. .extern 伪操作:.extern SQRT 告诉编译器标记 SQRT 是由其他程序片段(即模块)提供的。要求 SQRT 标记在库例程中被标记为.global SQRT,即可以被其他程序片段所使用。

  4. :一种抽象数据类型,后进先出。PUSH:压栈,POP:出栈

  5. 在存储器中实现栈:由一组存储单元和 “栈指针”(寄存器 R29)组成。栈指针即为栈的栈顶,最后压入的元素的存储单元地址。

・每次压栈,栈指针减 4;每次出栈,栈指针加 4

image13.png

image14.png

・返回值不需要压栈;临时寄存器不需要压栈。具体看计算阶乘的例子

  1. 为变量分配存储空间:当寄存器数量不足时,最常用的保存在寄存器里,不常用的放到存储器里。

  2. 存储器组织:

image15.png

全局数据区:全局变量

帧指针:R30,栈的基址,理解为当前栈的栈底。也可称作框架指针,动态链接

# 第十五章 函数

  1. 函数

  2. C 语言中,任何调用者的局部变量对于被调用函数都是不可见的。

  3. C 语言的编译过程:预处理、编译、链接

・预处理:寻找以 “#” 开头的预处理指令。与 DLX 的伪操作相似

・编译:产生机器代码

・链接:将目标文件与库的目标文件等等链接,生成可执行映像

image16.png

  1. 寄存器分配约定:

image17.png

  1. 是否允许递归:即函数是否允许调用它本身。C 语言允许。编译器为每一次函数调用分配一个活动记录。每一次函数调用都会在存储器中为其局部数值获得它自己的空间,返回时活动记录将被回收。通过 “** 运行时栈”** 实现活动记录的分配。

  2. 函数调用机制:

①调用函数使用参数寄存器保存变元(应该就是传给被调用函数的值)。如果大于 4 个,将其分配到运行时栈。(在函数调用前完成)

②被调用函数完成活动记录的分配:将一些寄存器的值保存到运行时栈中 —— 寄存器的保存;如果局部变量寄存器不足,将局部变量压入运行时栈。

③被调用函数执行任务

④被调用函数完成工作时,活动记录从栈中弹出,并且控制返回到调用函数

⑤调用函数的控制返回后,执行代码取回被调用函数的返回值

  1. 函数调用结束时的出栈:要按顺序,后进先出:弹出变元(如果函数内部还调用了其他函数),弹出局部变量,恢复保存的寄存器,恢复动态链接(R30),恢复返回地址(R31),最后 JR R31。控制返回后,再取得返回值

  2. 如无必要,可以不保存 R31,可以不使用 R30

# 第十六章 指针和数组

  1. 指针和数组

  2. 数组:在存储器中连续存储。在 [] 中提供下标,即偏移量。同样是基址 + 偏移量的表示方式。数组的名字即为数组的基址,但数组名不能被重新赋值。

・注意数组越界

  1. 二维数组:一行一行地存储。a [n] 代表着第 n 行的首地址

int p [4][4]:p 类型为 *int (p)[4] ,指向一维数组的指针,或者也可以说是指向指针的指针

p+i: 第 i 行地址,但实际与下面那个意思不一样

*(p+i) <=> p[i],第 i 行首地址(第一个数据的地址)

*((p+i)+j) <=> p[i][j]

・DLX 通路:

image18.png

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

北沐清 微信支付

微信支付

北沐清 支付宝

支付宝