前言:计算机组成原理是计算机科学的一门基础课程,主要研究计算机的硬件系统,包括计算机的基本组成、指令系统、CPU设计、存储器层次结构、总线结构、I/O系统等方面。
第一章:计算机系统概述
1.1.1 计算机硬件的发展
1946 年世界上第一台电子数字计算机(ENIAC)问世以来,计算机的发展经历了四代。
- 电子管时代(1946-1957)
- 晶体管时代(1958-1964)
- 中小规模集成电路时代(1965-1971)
- 超大规模集成电路(1972-至今)
1.1.2 计算机软件的发展
- 机器语言—> 汇编语言—> 面向问题的高级语言
- 操作系统方面, Windows, UNIX, Linux
1.1.3 计算机的分类和发展方向
计算机按指令和数据流分类:
- 单指令和单数据流(SISD), 即传统冯诺依曼体系结构。
- 单指令和多数据流(SIMD), 包括阵列处理器和向量处理器系统。
- 多指令和单数据流(MISD), 这种计算机实际不存在。
- 多指令和多数据流(MIMD), 包括多处理器和多计算机系统。
1.1.4 习题精选
解释程序的特点是翻译一句执行一句,边翻译边执行;由高级语言转化为汇编语言的过程称为编译,把汇编语言源程序翻译为机器语言程序的过程称为汇编。
1.2.1 计算机系统的组成
硬件系统和软件系统共同构成了一个完成的计算机系统。
1.2.2 计算机硬件的基本组成
1. 早期的冯诺依曼机
冯诺依曼提出了存储程序的概念,存储程序的思想奠定了现代计算机的基本结构。
存储程序的概念是指令以代码的形式事先存入计算机的主存储器,然后按其在存储器中的首地址执行程序的第一条指令,以后按该程序的规定顺序执行其他指令,直至程序执行结束。
2. 现代计算机组织结构
现代计算机已发展为以存储器为中心,使I/O操作尽可能的绕过CPU,直接在I/O设备和存储器之间完成,以提高系统的整体运行效率。

3. 计算机的功能部件
(1) 输入设备
(2) 输出设备
(3) 存储器
- 主存储器:cpu能够直接访问,简称主存。它由许多存储单元组成可存储一串二进制代码,称这串代码为存储字,称这串代码的位数为存储字长,存储字长可以是1B(8bit)或是字节的偶数倍。
- MAR,MDR虽然是存储器的一部分,但在现代CPU中却存在于CPU中,另外高速缓存Cache也存在CPU中。
(4) 运算器
(5) 控制器
- 控制器是计算机的指挥中心,由程序计数器(PC),指令寄存器(IR)和控制单元(CU)组成。
总结:现在计算机一般将运算器和控制器集成到同一个芯片上,合成中央处理器,简称CPU。CPU和主存储器构成主机,而计算机中除主机外的其他硬件装置(如I/O)统称为外设,外设主要包括外存和I/O设备。
1.2.3 计算机软件分类
- 系统软件和应用软件
- 三个级别的语言
1.2.4 计算机的工作过程
- 把程序和数据装入主存储器
- 从程序的起始地址运行程序
- 用程序的首地址从存储器中取出第一条指令,经过译码、执行步骤等控制计算机各功能部件协同运行,完成这条指令的功能,并计算下一条指令的地址。
- 用新得到指令地址继续读取第二条指令并执行,直到程序结束为止;每条指令都在取指、译码和执行的循环过程中完成的。
取数指令为例说明信息流程如下:
- 取指令:PC—>MAR—>M—>MDR—>IR
- 分析指令:OP(IR)—>CU
- 执行指令:Ad(IR)—>MAR—>M—>MDR—>ACC
- (PC) + 1—> PC
1.2.5 计算机系统的多层次结构

1.2.6 习题
冯诺依曼机的基本工作方式是控制流驱动方式。
按地址访问并顺序执行指令是冯诺依曼机工作方式的基本特点。
冯诺依曼计算机中指令和数据均以二进制形式存放在存储器中,CPU区分它们的依据是指令周期的不同阶段。

1.3.1 计算机的主要性能指标
- 机器字长
- 机器字长是指计算机进行一次整数运算(即定点整数运算)所能处理的二进制数据的位数,通常与CPU的寄存器位数、加法器有关。机器字长一般等于内部寄存器的大小,子长越长,计算精度越高。
- 数据通路带宽
- 是指数据总线一次所能并行传送信息的位数,这里所说的数据通路带宽是指外部数据总线的带宽,它与CPU内部的数据总线宽度(内部寄存器的大小)有可能不同。
- 主存容量
- 是指主存储器所能存储信息的最大容量,通常以字节来衡量,可用字数*子长(512K *16位)来表示存储容量。其中,MAR的位数反映存储单元的个数,反映可寻址范围的最大值。例如,MAR为16位表示2^16 = 65536,即此存储体内有65536个存储单元(可称为64K内存,1K=1024),若MDR为32位,表示存储容量为64K*32位。
- 运算速度
- 吞吐量 指系统单位时间内处理请求的数量,主要取决于主存的存取周期。
- 响应时间 指用户向计算机发送一个请求,到系统对该请求做出响应并获得所需结果的等待时间,通常包括CPU时间与等待时间(用于磁盘访问,存储访问,I/O操作,操作系统开销等时间)。
- CPU时钟周期 通常为节拍脉冲或T周期,即主频的倒数,它是CPU中最小的时间单位,每个动作至少需要1个时钟周期。
- 主频(CPU时钟频率) 主频的倒数是CPU时钟周期,对于同一个型号的计算机主频越高,完成指令的一个执行步骤所用的时间越短,执行指令的速度越快。
- CPU时钟周期 = 1/主频
- CPI(Clock cycle Per Instruction),即执行一条指令所需要的时钟周期数。
- CPU 执行时间 = CPU时钟周期数/主频 = (指令条数*CPI)/主频
- MIPS (Million Instruction Per Second),即每秒执行多少百万条指令。MIPS = 指令条数/(执行时间*10^6) = 主频/CPI,主频单位为MHz
- MFLOPS(Megal Floating-point Operations Per Second),即每秒执行多少百万次浮点运算。MFLOPS = 浮点操作次数/(执行时间 * 10^6)
1.3.2 几个专业术语
- 系列机。具有相同的体系结构,使用相同基本指令系统的多个不同型号的计算机组成的一个产品系列。
- 固件。将程序固定在ROM中组成的部件称为固件。
第二章:数据的表示和运算
2.1.1 进位计数制及其相互转换
- 进位计数法
- 进位计数法是一种计数方法。常用有十进制、二进制、十六进制、八进制。
- 不同进制数之间的相互转换
- 例子:将二进制 1111000010.01101分别转换为八进制数和十六进制数。
- (001 111 000 010. 011 010)2 = (1702.32)8
- (0011 1100 0010. 0110 1000)2 = (3C2.68)16
2.1.2 真值和机器数
- 通常把带"+"或“-”符号的数称为真值,真值是机器数所代表的实际值。
- 在计算机中,通常采用数的符号和数值一起编码的方法来表示数据。常用有原码、补码、反码。把符号“数字化”的数称为机器数。
2.1.3 BCD码
二进制编码的十进制数(Binary-Coded Decimal,BCD),通常采用4位二进制数来表示一位十进制数中的0—9 这10个数。但4位二进制数有16中状态,故必有6中冗余状态。
- 8421码(常用):若两个8421码相加之和小于等于9,不需修正。若之和大于等于10,需加6修正,并向高位进位。
- 余3码。这是一种无权码,是在8421码的基础上加(0011)2形成的。如 8–>1011;9–>1100;
- 2421码。这是一种有权码,权值由高到底分别为2,4,2,1,特点是大于等于5的4位二进制中最高位为1,小于5的为高位为0.如5–>1011而非0101。
2.1.4 字符和字符串
- ASCII 码。在ASCII码中,编码值031为控制字符,用于通信控制和设备的功能控制;编码值为127是DEL码;编码值32是空格;编码值32126共95个字符为可印刷字符。提示:0~9 的ASCII码值为48(011 0000)~ 57(011 1001),即去掉高3位,只保留低4位,正好是二进制的0~9。
- 汉字的表示和编码。GB2312-1980中,每个编码用两个字节,共计7445个。目前最新的汉字编码是GB18030-2000,它收录27484个汉字。编码标准采用1B,2B和4B。
- 字符串的存放。字符串通常是一串连续的字符,占用主存连续的多个字节,每个字节存放一个字符,主存字由2B或4B组成时,即可按大端模式也可小端模式。
2.1.5 校验码
码距,任意两个合法码字之间最少变化的二进制位数。例如:1100和1101之间的码距为1,因为只有最低位翻转了。而1001和0010之间的码距是3,因为只有1位没有变化。码距越大,检错,纠错能力越强,而且检错能力总大于纠错能力。
- 奇偶校验码
例:给出两个编码1001101和1010111的奇校验码和偶校验码。
| 1001101 | 11001101(奇校验码) | 01001101(偶校验码) |
|---|---|---|
| 1010111 | 01010111(奇校验码) | 11010111(奇偶校验码) |
- 海明码。它是一种广泛采用的有效的校验码,是一种多重奇偶校验码,具有检错和纠错能力。例如:在n=4,k = 3时,求1010的海明码。设n为有效信息的位数,k为校验位的位数,则信息位n和校验位k应满足:
海明码位数为:
则n,k有效。
- 循环冗余校验(CRC)码。CRC的基本思想:在K位信息位后再拼接R位的校验码,整个编码的长度为N位,因此这种编码又称(N,K)码。计算过程如下:
2.2.1 定点数的表示
- 无符号数和有符号数的表示
- 无符号数:指整个机器字长的全部二进制位均为数值位,没有符号位,相当于数的绝对值。若机器字长为8位,则数的范围为.
- 有符号数。有符号数的机器表示有原码、补码、反码、移码。
- 机器数的定点表示
- 定点小数
- 定点整数:是纯整数,约定小数点位置在有效数值部分最低位之后。若数据X的形式为
- 补数和模数
一个数减去两一个数(加上一个负数)等于第一个数加上第二个个数的补数。例如:时钟指针
8+(-2) = (8 + 10)(mod 12) = 6
n 位二进制数的模数为
n 位小数的模数为2- 原码、补码、反码、移码
- 纯小数的原码定义
若,字长为8位,则其原码表示为:,若字长为n+1,则原码小数的表示范围为,关于原点对称。- 纯整数的原码定义
例如,若,字长为8位,则其原码表示,其中最高位是符号位。
注意:真值0的原码表示有正零和负零两种形式,即。- 纯小数的补码定义
(mod 2)
若,字长为8位,则其补码表示:。若字长为n+1,则补码的表示范围为(比原码多表示一个-1)- 纯整数的补码定义
若字长为8位,则其补码表示:。
若字长为n+1,则补码的表示范围为.- 由原码求补码,由补码求原码
- 对于正数,补码与原码的表示相同,[X]补=[X]原。
- 对于负数,原码符号位不变,数值部分按位取反,末位加1,此规则同样使用于由[X]补求[X]原。
- 补码的算术移位
将[X]补的符号位与数值位一起右移一位并保持原符号位的值不变,可实现除法功能(除以2)- 纯小数的反码表示法
若,字长为8位,则其反码表示:。
若字长为n+1,则反码的表示范围为.(关于原点对称)- 纯整数的反码定义
若,字长为8位,则其反码表示:。
若字长为n+1,则反码的表示范围为.(关于原点对称)
真值、原码、补码、反码及[-X]补的转换规律,如下图:

- 移码表示法。移码常用来表示浮点数的阶码。它只能表示整数。
定义为:
若正数,字长为8位,则其移码表示为:。
移码有一下特点:
- 移码中零的表示唯一。
- 一个真值的移码和补码仅差一个符号位,[X]补的符号位取反即得[X]移,反之亦然。
- 移码全为0时,对应真值的最小值;移码全为1,对应真值的最大值。
- 移码保持了数据原有的大小顺序,移码大真值就大,移码小真值就小。
2.2.2 定点数的运算
1.定点数的移位
- 算术移位
| 码制 | 填补代码 | |
| 正数 | 原码、补码、反码 | 0 |
| 负数 | 原码 | 0 |
| 补码 | 左移添0 | |
| 右移添1 | ||
| 反码 | 1 |
- 算术移位的对象是有符号数,在移位过程中符号位保持不变。
- 负数的原码数值部分与真值相同,故在移位时只要使符号位不变,其空位添0。
- 逻辑移位:逻辑移位的操作数视为无符号数,移位规则:逻辑左移时,高位丢失,低位添0;逻辑右移时,低位丢失,高位添0.
- 循环移位:循环移位操作适合将数据的低字节数据和高字节数据互换。
2.原码定点数的加减运算
- 加法规则:先判断符号位,若相同,则绝对值相加,结果符号位不变;若不同,则做减法,绝对值大数减去绝对值小的数,结果符号位与绝对值大的数形同。
- 减法规则:两个原码表示的数相减,首先将减数符号位取反,然后做加法运算。
3.补码定点数的加减运算
补码运算规则简单,因此计算机系统普遍采用补码加减运算。
- 参与运算的两个数均用补码表示。
- 按二进制规则运算,逢二进一。
- 符号位与数值位按同样规则一起参与运算,符号位运算产生的进位要丢掉,结果的符号位由运算得出。
- 补码加减运算公式。当参加运算的数是定点小数时,;当参加运算的数是定点整数时,.
注意:mod M 运算是为了将溢出位丢掉。- 补码运算的结果亦为补码。
4.符号扩展
在计算机算术运算中,8位数和32位数相加时,必须将8位数转换为32位形式,这称为“符号扩展”。
- 正数符号位不变,附加位添0。
- 负数。
- 原码:符号位为1,附加位添0。
- 补码:符号位不变,附加位添1(整数),添0(小数)。
- 反码:符号位不变,附加位添1。
5.溢出概念和判别方法
仅当两个符号位相同的数相加,或符号位不同的数相减才有可能溢出。
- 采用一位符号位。设A的符号,B的符号,结果为,
,若,表示无溢出;若,表示有溢出。- 采用双符号位。
- ①S1S2=00,结果为正,无溢出。
- ②S1S2=01,结果正溢出。
- ③S1S2=10,结果负溢出。
- ④S1S2=11,结果为负,无溢出。
- 采用一位符号位根据数据位的进位判断溢出
若符号位的进位Cs与最高数位的进位C1相同,则说明没有溢出,否则发生溢出。
2.2.3 强制类型转换
1 | int main() { |
分析:[x]补 = 1 110 1111 0001 1111,[y]补=1110 1111 0001 1111,因此,[x]补=[y]补,所以,强制类型转换保持位值不变,改变了解释这些位的方式。
1 | int main() { |
分析:[x]补 =0000 0000 0000 0010 1000 0110 1010 0001,[y]补=1000 0110 1010 0001,因此,[y]补只是截取了[x]补的低两位字节,这也是一种保持位值的处理方法。[u]补 =1111 1111 1111 1111 0111 0111 0101 0001,[v]补=0111 0111 0101 0001,同理[v]补只是截取了[u]补的低两位字节。
1 | int main() { |
分析:[x]补 =1110 1111 0001 1111,[u]补=1110 1111 0001 1111,[x]补=[u]补。数值位不变,解释方式不同。其他的就很好理解了。
2.2.4 位运算
- 按位与(&)运算
- 将某一位置0,其他位不变:将char 型变量a 的最低位置0:a = a & 0b1111’1110;(a = a & 0xfe).
- 取指定位:有char c; int a; 取出a的低字节,置于c中:c=a & 0xff; (0xff:1111 1111)
- 按位或(|)运算
- 将某些位置1,其他位不变:将 int 型变量 a 的低字节置 1 : a = a | 0xff;
- 位运算——取反(~)
- 025:0000000000010101
- ~025:1111111111101010
- 位运算——按位异或(^)
- 使特定位翻转(与0异或保持原值,与1异或取反): 0111’1010 ^ 0000’1111 = 0111’0101 低四位翻转
- 位运算——移位(<<、>>)
- 左移运算(<<)
左移后,低位补0,高位舍弃 - 右移运算(>>)
低位舍弃,高位:无符号数补0,有符号数补“符号位”
2.3.1 浮点数的表示
- 浮点数的表示规格
,E,M 都是有符号的定点数,E称为阶码,M称为尾数。
,
—阶符;—阶码的数值部分;
—数符;—尾数的数值部分;- 规格化浮点数
所谓规格化操作,是指通过调整一个非规格化浮点数的尾数和阶码的大小,使非零的浮点数在尾数在尾数的最高位是一个有效值。
- 左规:将尾数算术左移一位,阶码减1的方法称为左规,左规可能要进行多次。
- 右规:当浮点数运算结果尾数出现溢出(双符号位为01或10)时,将尾数算术右移,阶码加1.需要右规时,只需进行一次。
- 1)原码规格化后。
正数为0.1xx…x的形式,其最大值为0.11…1,最小值表示为0.100…0.尾数的范围为:。
负数为1.1xx…x的形式,其最大值为1.10…0,最小值表示为1.11…1.尾数的表示范围:
。- 2)补码规格化后。
正数为0.1xx…x的形式,其最大值为0.11…1,最小值表示为0.100…0.尾数的范围为:。
负数为1.0xx…x的形式,其最大值为1.01…1,最小值表示为1.000…0.尾数的范围为:
。
注意:这里补码规格化尾数的最大负数为1.01…1,而不是原码形式1.10…0,因为1.100…0不是补码的规格化数,所以规格化尾数的最大负值是。
- IEEE 754标准
按照IEEE 754标准,常用的浮点数的格式:
| Ms | E | M |
— 数符; — 阶码部分,用移码表示;—尾数部分,用原码表示;
IEEE 754浮点数的格式如下:
| 类型 | 数符 | 阶码 | 尾数数值 | 总位数 | 偏置值 |
|---|---|---|---|---|---|
| 短浮点数 | 1 | 8 | 23 | 32 | 7FH 127 |
| 长浮点数 | 1 | 11 | 52 | 64 | 3FFH 1023 |
| 临时浮点数 | 1 | 15 | 64 | 80 | 3FFFH 16383 |
对于规格化的二进制浮点数,数值的最高位总是 1,为了能使尾数多表示一位有效位,将这个 1 隐去,因此尾数数值实际上是24位,隐含的 1 是一位正数,在浮点数格式中表示的23位尾数是纯小数。例如,(12)10=1100,将它规格化后结果为,其中整数部分的 1 将不存储在23位尾数中。
2.3.2 浮点数的加减运算
- 对阶。先求阶差,然后以小阶向大阶看齐,将阶码小的尾数右移一位,阶加1,直到两个数的阶码相等为止。尾数右移时,舍弃掉有效位数会产生误差,影响精度。
- 尾数求和。将对阶后的尾数按定点数加减运算规则进行运算。
- 规格化。以双符号位为例,当尾数大于0时,其补码规格化形式为:
[S]补=00.1xx…x,当尾数小于0时,其补码规格化为:[S]补=11.0xx…x。规格化分为左规和右规:
- 左规:当尾数出现00.0xx…x或11.1xx…x时,需左规,即尾数左移1位,和的阶码减1,直到尾数为00.1xx…x或11.0xx…x。
- 右规:当尾数求和结果溢出(如尾数为01.xx…x或01.xx…x)时,需右规,即尾数右移一位,和的阶码加1。
- 舍入。常见的舍入方法有:
- "0"舍“1”入法:类似十进制的四舍五入,即在尾数右移时,被移去的最高位数值为0,则舍去;被移去的最高位数值为1,则在尾数的末位加1.这样做可能会使尾数又溢出,此时需在做一次右规。
- 恒置“1”法。尾数右移时,不论丢掉的最高位数值为1还是0,都使右移后的尾数末位恒置1.这种方法同样有使尾数变大和变小两种可能。
- 溢出判断。
浮点数的溢出是否由阶码的符号位决定的。以双符号为补码为例,当阶码的符号位出现01时,即阶码大于最大阶码时,表示上溢,进入中断处理;当阶码的符号位出现10时,即阶码小于最小阶码时,表示下溢出,按机器零处理。- 强制类型转换
以char — int—long—double和float—double最为常见,从前到后范围和精度都从小到大,转换过程没有损失。
- 1) char 为8为ASCII 码整数,转换为int,在前补0。
- 2) int和unsigned int 可以互相转换,但彼此都可能因溢出而造成数据丢失,如8位int和unsigned int ,a=-1,(unsigned int)a=255;(unsigned int)a=128,(int)a=-128;
- 3) int和float转换,若float 是小数,则转换为int可能会发生精度损失和溢出,从int转换为float 时,虽然不会溢出,但int可以保留32位,float保留24位,可能有数据舍入,double 则不会。
2.4.1 串行加法器和并行加法器
加法器是由全加器再配以其他必要的逻辑电路组成的,根据组成加法器的全加器个数是单个还是多个,加法器有串行和并行之分。
- 一位全加器




