本章有大题要考。(常见的有:浮点数尾数基值/ROM表/哈夫曼码)
在学习这一章节之前,我觉得有必要了解下以下知识:
在CPU中存放操作数有三种存储单元:堆栈,累加器,通用寄存器。
我们的指令都围绕着操作数转的,所以分为堆栈指令系统,累加器指令系统,通用寄存器指令系统,但目前堆栈和累加器这两种指令系统已经被淘汰了,当前都是通用寄存器指令系统。
那么在通用寄存器指令系统中,也有细分为两种:RR(寄存器-寄存器),RM(寄存器-存储器)。而当前只有RR型成为主流,为什么我们需要尽量把操作数放在寄存器呢?
首先寄存器肯定比存储器要快,其次能够使用更少的地址位数就能访问到操作属,可以减少指令长度。我们之后所学习到的指令系统都是RR型的。
以上信息不再书本中,但对于理解后续的概念会有一些帮助。
在存储器里面,有:字节,半字,单字,双字,我们如何去兼容这些单位呢?在真实的存储中,我们选择下图的B方案,这是一个你到底是想浪费时间还是浪费空间的矛盾问题。(当然浪费空间更好啦)
补充下计算机专业的常识:在计算机中,字节(Byte)是最基本的存储单位,通常由8个二进制位(bit)组成。一个字节可以存储一个字符或者一个二进制数据。
- 字节(byte)是由两个字节组成,即16个二进制位。
- 半字(Half Word)是由两个字节组成,即16个二进制位。
- 单字(Word)通常是由四个字节组成,即32个二进制位。
- 双字(Double Word)通常是由八个字节组成,即64个二进制位。
这是通常的情况;随着技术的发展,字代表的实际二进制位数也会相应地变化。
2.1 数据表示
2.1.1 数据表示与数据结构
数据结构要通过软件映像变换成机器所具有的各种数据表示实现,数据表示是数据结构的实现。
数据表示和数据结构之间的关系及引入高级数据表示的基本原则:
(1) 数据表示反映了各种数据元素或信息单元之间的结构关系,数据结构要通过软件映像变换成机器所具有的各种数据表示来实现。不同的数据表示可为数据结构的实现提供不同的支持,表现在实现效率和方便性上不同。数据结构和数据表示是软件和硬件的交界面。
(2) 引人高级数据表示的基本原则:
一是看系统效率是否有显著提高,包括实现时间和存储空间是否有显著减少;
二是看引入这种数据表示的通用性和利用率是否提高。
2.1.2 高级数据表示
自定义数据表示
自定义数据表示包括标识符数据表示和数据描述符两类。
(1)标志符和数据描述符的差别(课后习题 2-2,p32~36,简答题) 标志符是和每个数据相连的,共同存储在一个存储单元中,描述单个数据的类型特征;
数据描述符是与数据分开存放,用于描述所要访问的数据是整块的还是单个的,访问该数据块或数据元素所要的地址以及其他信息。
2.1.3 引入数据的表示原则
2.1.4 浮点尾数基值大小和下溢处理方法的选择
(1)浮点尾数基值的选择
- 当阶位 p 一定时,尾数采取什么进制都会影响到数的可表示范围、精度及数轴上分布的离散程度。
- 采用尾基为 的浮点数表示的特性
- 数轴上的分布
在相同的机器字长和尾数位数的情况下,浮点尾数基值取小,可使浮点数在数轴上的分布变密。
- 可表示的精度
浮点尾数基值增大,可表示的精度下降。
- 运算中的精度损失
浮点尾数基值增大,运算中的精度损失减小。
(2)尾基(浮点尾数基值) r_m 的影响。(p42)
越大,可表示数范围越大,可表示数的个数越多,数在数轴上的分布越稀疏,可表示的精度越低,运算中的精度损失越小,运算速度越快。
(3)浮点数尾数的下溢处理方法。(p44)
① 截断法:实现简单,不增加硬件,不需要处理时间。
② 舍入法:最大误差 0.5,统计平均误差趋于 0。
③ 恒置 “1” 法:平均误差趋于 0,最大误差最大。
④ 查表舍入法:平均误差可调节到 0,是最好的方法。
【扩展知识】浮点数的阶值和尾基分别指的是什么?
在浮点数表示中,通常用科学计数法表示实数,包括两个部分:尾数(Mantissa)和阶码(Exponent)。这是浮点数的基本结构。
尾数(Mantissa):也被称为尾基。尾数是一个数的小数部分,包括数值的有效部分。在浮点数表示中,它通常用二进制表示,代表实际的数字。尾数描述了一个数的精度和大小。在科学计数法中,尾数通常位于底数部分。
阶码(Exponent):阶码是一个数的指数部分,用来表示这个数的大小范围或阶值。它描述了数的数量级或指数。在浮点数表示中,阶码通常以二进制形式表示,用来指示小数点的移动次数,即对数的指数部分。
这两部分一起构成了浮点数,以科学计数法的形式表示一个数,例如:
(s) 是符号位,表示正数或负数。 (M) 是尾数,也叫尾基,表示实际数值。 (E) 是阶码,也就是阶值,表示数量级或指数。
所以,尾基(尾数)代表了实际的数值部分,而阶值(阶码)则代表了这个数值的指数部分,决定了数值在科学计数法中的位置。 这种表示方式使得计算机能够表示非常大或非常小的数字,并且能够保持一定的精度,同时适应广泛的数值范围。
2.2 寻址方式
寻址方式的终极目标,是能够表达出:
EA是有效地址。怎样把EA表示出来,可能因为位数不够的问题,我们要层次嵌套地表示出来。下面列举几种,首先先商定一些符号的使用:Reg[…]表示寄存器里的内容,Mem[…]表示存储器的内容。
- 寄存器寻址:
add r1,r2
- 立即数寻址:
add r1,6
- 偏移寻址:
add r1,120[r2]
- 寄存器间接寻址:
add r1,[r2]
- 直接寻址:
add r1,(1000)
- 存储器间接寻址:
add r1,@[r2]
在对编译器进行调查,发现:偏移寻址和立即数寻址是用的最频繁的。
2.2.1 寻址方式的三种面向
计算机面向主存、寄存器、堆栈寻址。
指令中常用下列寻址方式来得到操作数:立即寻址、间接寻址、直接寻址、寄存器寻址、自相对寻址。请分别说明这些寻址方式的原理,并对它们在如下四个方面进行比较:(课后习题 2-8)
① 可表示操作数的范围大小;
② 除取指外,为获得操作数所需访主存的最少次数;
③ 为指明该操作数所占用指令中的信息位数多少;
④ 寻址复杂性程度。
- 立即寻址 立即操作数的寻址原理是,操作数以常数形式直接存放在指令中操作码的后面。一旦指令被取出,操作数也被取得,立即可以使用。 ① 立即操作数由于受机器指令字长的限制,可表示数的范围小,一般为 8 位或 16 位的二进制常数。 ② 指令取出后,为获得操作数不需要再访存,即访存 0 次。 ③ 操作数所占用指令中的信息位数是立即数在可表示最大值范围时所要占用的二进位位数。 ④ 寻址的复杂性程度相对低。
- 间接寻址 间接寻址可以有寄存器间接寻址和存储器间接寻址两种。其寻址原理是,在指令的操作数地址字段上只给出存放操作数在内存中物理地址的寄存器号或存储单元地址。先由指令操作数地址字段,从寄存器或存储单元中取出数在存储器中的地址。再按此地址访存,才能间接取得所要的操作数。 ① 间接寻址访问到的操作数范围大,可以是主存中能访问到可表示数值范围最大的数。 ② 除取指外,获得所需操作数所需访问主存的最少次数,对于寄存器间接寻址为一次,对于存储器间接寻址为两次。 ③ 为指明该操作数所占用指令中的信息位数,对于寄存器间接寻址来说,只是为寄存器标号所占用的二进位位数,这种位数一般很短;而对于存储器间接寻址来说,需占访存逻辑地址所需的全部位数。 ④ 间接寻址的复杂性一般最高。其中,寄存器间接寻址较存储器间接寻址简单,最复杂的是存储器多重间接寻址。
- 直接寻址 直接寻址的原理是,由指令中操作数地址码字段给出存放操作数在内存中的有效地址或物理地址。 ① 直接寻址可表示操作数值的范围大,可以是主存中能访问的可表示值范围最大的数。 ② 除取指外,为获得所需操作数,需要再访问一次主存。 ③ 为指明操作数所占用指令中的信息位数,是访存单元的有效地址或物理地址所需要的位数。 ④ 直接寻址的复杂性较寄存器寻址的大,而它较寄存器间接寻址要简单些。
- 寄存器寻址 寄存器寻址的原理是,指令的操作数地址码字段给出存放操作数所用的寄存器号。 ① 可表示操作数的范围大小取决于存放操作数所用的寄存器的二进位位数。 ② 除取指外,为获得操作数不用访存,即访存 0 次。 ③ 为指明操作数所占用指令中的信息位数,只是寄存器编号所占的二进位位数,很短。 ④ 寄存器寻址简单,其取数的时间要比访存的时间短得多。
- 自相对寻址 自相对寻址方式主要用于转移指令形成转向目标地址,有的也用于访问存储器寻找操作数,以访问存储器操作数寻址为例,指令中操作数字段给出所访问操作数存放在主存中相对于指令计数器当前值的位移地址。 ① 自相对寻址所寻址的操作数可表示范围大,可以是主存中能访问的可表示值范围最大的值。 ② 除取指外,为获得操作数所需访问的次数为 1 次。 ③ 为指明该操作数所占用指令中的信息位数取决于允许的最大相对位移量大小。 ④ 寻址复杂性较直接寻址的略复杂些。
按与CPU远近来分,离得最近的是寄存器,然后缓存,最后内存。所以,寄存器是最贴近CPU的,而且CPU只与寄存器中进行存取。寄存器从内存中读取数据,但由于寄存器和内存读取速度相差太大,所以有了缓存。
CPU<------>寄存器<------>缓存<------->内存
当寄存器没有从缓存中读取到数据时,也就是没有命中,那么就从内存中读取数据。
2.2.3 程序在主存中的定位技术
程序的静态再定位和动态再定位的含义及实现方法:
静态再定位是指程序在执行时物理地址不再改变的定位技术。它是利用 Von Neumann 型机器指令可修改的特点,在目的程序装入主存时,由装入程序用软件方法把目的程序的逻辑地址变换成物理地址,程序在执行时物理地址不再改变。
动态再定位是指在执行每条指令时才形成物理地址的定位技术。该方法利用硬件上增加基址寄存器和地址加法器,程序执行时,通过地址加法器将逻辑地址加上基址寄存器的程序基址形成物理(有效)地址后去访问主存。
2.3 指令系统的设计和优化
计算机的运算类指令和运算器结构主要是按机器有什么样的数据表示来确定的。
2.3.2 指令操作码的优化
指令是由操作码和地址码两部分组成。
哈夫曼树例题: 假设某机器共有 8 条指令(I1-I8),使用频度如表所示,要求:
这题如果学过数据结构这门课程应该很容易做出来。
(1)构造哈夫曼(Huffman)树;
(2)列表写出操作码的哈夫曼编码和只有两种码长的扩展操作码;
(3)分别计算使用哈夫曼编码和只有两种码长的扩展操作码的平均码长。
构造哈夫曼树的方法:将所有指令按使用频度升序排列,每次选择最小的两个频度节 点合并为一个频度作为新节点。哈夫曼树节点左侧线标记 1,右侧标记 0。
根据上图可知每个指令的哈夫曼编码,也就知道了它们分别对应的码长。
2.4 指令系统的发展和改进
对指令系统设计的话,我们需要根据:以经常性事件为重点,我们会选择频率高的功能用硬件来实现,因为硬件速度快,但是灵活性差。
对指令系统的要求是:完整,规整,正交,高效率,和兼容。
- 完整的意思是指令系统能给基本的问题解法给答案,保证能用这些指令组合能完成更多任务;
- 正交的意思是各个字段独立,兼容指的是能够新增新指令。
在机器指令系统的设计、发展和改进上有两种不同的途径和方向,分别是 复杂指令系统计算机 (CISC) 和 精简指令系统计算机 (RISC)。
2.4.2 按 CISC 方向发展和改进指令系统
设计 CISC 系统时,可以从面向目标程序、面向高级语言、面向操作系统三个方面的优化实现来考虑。
CISC 的问题:
① 指令系统庞大,一般指令在 200 条以上;
② 许多指令的操作复杂,执行速度很低,甚至不如用几条简单、基本的指令组合实现;
③ 难以优化生成高效机器语言程序,编译程序也太长、太杂;
④ 指令使用频率不太高,且差别很大,增加机器设计人员负担,降低性能价格比。
2.4.3 按 RISC 方向发展和改进指令系统
(1)设计 RISC 的基本原则(p63,简答题)
① 确定指令系统时,只选择使用频度很高的指令,再增加少量能有效支持操作系统、高级语言实现及其他功能的指令;
② 减少指令系统所用寻址方式种类;
③ 让所有指令都在一个机器周期内完成;
④ 扩大通用寄存器数,尽量减少访存;
⑤ 大多数指令都用硬联控制实现,少数指令用微程序实现;
⑥ 通过精简指令和优化设计编译程序,简单有效地支持高级语言的实现。
【扩展知识】当我们谈论指令在一个机器周期内完成时,指的是在计算机的时钟周期内完成所有指令的执行过程。
一个机器周期是计算机中最小的时间单位,它由时钟信号控制。计算机的时钟信号以固定的频率发出,每个时钟周期的持续时间相等。在每个时钟周期内,计算机的各个部件(例如控制单元、算术逻辑单元等)都会执行特定的操作。
当所有指令都在一个机器周期内完成时,意味着计算机能够以非常高的速度执行指令。这是因为计算机的硬件设计和优化使得在每个时钟周期内能够完成多个操作。当一条指令执行完成后,下一条指令会立即开始执行,而不需要等待下一个时钟周期。
举个例子来说明,假设我们有一条简单的指令:“将寄存器A的值加上寄存器B的值,并将结果存储在寄存器C中”。在一个机器周期内完成这个指令意味着以下几个步骤会在同一个时钟周期内完成:
- 从寄存器A和寄存器B中读取数据。
- 执行加法操作,将两个值相加。
- 将结果存储到寄存器C中。
在传统的计算机中,每个步骤通常需要多个时钟周期才能完成。但在一些高性能的计算机中,优化的硬件设计可以在一个时钟周期内同时执行多个步骤,从而实现指令在一个机器周期内完成。
总之,指令在一个机器周期内完成意味着计算机能够以非常高的速度执行指令,提高计算机的性能和效率。
(2)设计 RISC 结构的基本技术。(p64~66,简答题)
① 按照设计 RISC 的一般原则来设计;
② 逻辑实现采用硬联和微程序相结合;
③ 在 CPU 中设置大量工作寄存器并采用重叠寄存器窗口;
④ 指令用流水和延迟转移;
⑤ 采用高速缓冲存储器 Cache,设置指令 Cache 和数据 Cache 分别存放指令和数据;
⑥ 优化设计编译系统。