计算机组成原理 — 指令系统
目录
前文列表
《计算机组成的基本硬件设备》
《计算机组成原理 — 冯诺依曼体系结构》
《计算机组成原理 — 中央处理器》
指令系统
指令系统决定了计算机的基本功能。计算机的性能与它所设置的指令系统有很大的关系,而指令系统的设置又与机器的硬件结构密切相关。指令系统的改进主要围绕缩小指令与高级语言的语义差异以及有利于操作系统的优化而进行的,例如:高级语言中经常用到的 if 语句、do 语句,所以设置了功能较强的条件跳转指令;为了操作系统的实现和优化,设置了有控制系统状态的特权指令、管理多道程序和多处理机系统的专用指令。
然后指令系统太过于复杂并不完全是好事,在大多数场景中实际上只有算术逻辑运算、数据传输、跳转和程序调用等几十条指令会被频繁的使用到,而需要大量硬件支持的大多数复杂的指令却并不常用,由此会造成硬件资源的浪费。为了解决这个问题,指令系统被分为 精简指令系统计算机(RISC) 和 复杂指令系统计算机(CISC)。
计算机指令集与程序指令
计算机指令集是 CPU 提供的可执行指令的集合;而程序所描述的指令是程序员希望在 CPU 上执行的指令,这些指令的范围不会超出计算机指令集的范围。不同类型的 CPU 能够理解不同的 “语言”,即具有不同的计算机指令集(Instruction Set)。同一个程序可以在相同型号的 CPU 中运行,反之则无法运行。
CPU 运行一个计算机程序的本质就是运行这个程序所描述的指令,有如我们在 Linux 操作系统上执行指令一般,只是前者由 CPU 硬件支持。一个计算机程序通常由成千上万条指令组成,CPU 显然不能存放所有的指令,而是将这些指令存放在存储器中,只有在运行时才会被 CPU 读取。又因为现代计算机被设计为可以运行多种程序,存储器被各种各样的程序共享着,所以存储器也不会持久化的保存它们。而是当我们要运行(启动)某个程序时,才会将其加载到存储器中,最终再由 CPU 从存储器中逐一读取其指令。我们常见的内部存储器多为 RAM(随机存储器),这是一种被设计成掉电就会自动重置的存储设备。
以上就是冯·诺依曼机的典型特性,所以又称之为 “存储程序计算机”。冯·诺依曼体系结构解决了计算机实现领域的一个重要难题:如何能够动态加载程序指令。解决了这个问题,“计算器” 才得以成为 “计算机”,我们今天才得以在计算机上运行各种各样的应用程序。
注:计算器的 “程序” 是焊死在主板上的。
指令格式
计算机是通过执行指令来处理各种数据的,为了了解数据的来源、操作结果的去向及所执行的操作类型,一条计算机指令一般包含以下信息。
- 操作码:说明操作的性质和功能(e.g. 加减乘除、数据传输),长度有指令系统的指令条数决定(e.g. 256 条指令,则操作码需要 8 位长度)。
- 操作数的地址:CPU 通过该地址读取到所需要的操作数,可能是存储器的地址,也可能是寄存器的地址。
- 操作结果的储存地址:保存操作结果数据的地址。
- 下一条指令的地址:当程序顺序执行时,下一条指令的地址又程序计数器(PC)给出,仅当改变程序的执行顺序时(e.g. 跳转、函数调用),下一条指令的支持才会有指令本身给出。
综上,指令格式主要有 操作码 和 地址码 组成。需要注意的是,在指令字长较长的计算机中,操作码的长度一般是固定的,并且由指令集的数量决定。但在指令字较短的计算机中,为了能够充分利用指令字的位数,在有限的长度中实现更多的指令集数目,所以其操作码长度被设计成是可变的,即把它们的操作码在必要的时候扩充到地址码字段。这就是所谓的 指令操作码扩展技术。指令字的长度与 CPU 的位数密切相关。
指令类型
日常使用的 Intel CPU 大概有 2000 多条 CPU 指令。可以分为以下 5 大类型:
- 算术类指令:加减乘除。
- 数据传输类指令:变量赋值、读写内存数据。
- 逻辑类指令:与或非。
- 条件分支类指令:条件判断语句。
- 无条件跳转指令:方法、函数的调用跳转。
继续细分的话,具有如下指令类型:
- 算术逻辑运算指令
- 移位操作指令
- 算术移位
- 逻辑移位
- 循环移位
- 矢量运算指令(矩阵运算)
- 浮点运算指令
- 十进制运算指令
- 字符串处理指令
- 字符串传送
- 字符串比较
- 字符串查询
- 字符串转换
- 数据传输指令
- 寄存器与寄存器传输
- 寄存器与主存储器单元传输
- 存储器单元与存储器单元传输
- 数据交换(源操作数与目的操作下互换)
- 转移指令
- 条件转移
- 无条件转移
- 过程调用与返回
- 陷阱
- 堆栈及堆栈操作指令
- I/O 指令
- 特权指令
- 多处理机指令(在多处理器系统中保证共享数据的一致性等)
- 控制指令
指令寻址
指令寻址,即是根据指令字的地址码来获取到实际的数据,寻址的方式跟硬件关系密切,不同的计算机有不同的寻址方式。有的计算机寻址方式种类少,所以会直接在操作码上表示寻址方式;有些计算机的寻址方式种类多,就会在指令字中添加一个特别用于标记寻址方式的字段,例如:假设该字段具有 3 位,那么就可以表示 8 种寻址方式。
NOTE:寻址方式与 CPU 内的寄存器设计密切相关。
直接寻址:指令字的地址码直接给出了操作数在存储器中的地址,是最简单的寻址方式。
间接寻址:指令字的地址码所指向的寄存器或存储器的内容并不是真实的操作数,而是操作数的地址。间接寻址常用于跳转指令,只要修改寄存器或存储器的地址就可以实现跳转到不同的操作数上。
相对寻址:把程序计数器(PC)的内容,即当前执行指令的地址与地址码部分给出的偏移量(Disp)之和作为操作数的地址。这种寻址方式同样常用于跳转(转移)指令,当程序执行到本条指令后,跳转到 PC+Disp。
立即数寻址:即地址码本身就是一个操作数的寻址方式,该方式的特点就是数据块(因为实际上没有寻址),但操作数固定。常用于为某个寄存器或存储器单元赋初值,或提供一个常数。
通用寄存器寻址:CPU 中大概会有几个到几十个通用寄存器用于临时储存操作数、操作数的地址或中间结果,指令字的地址码可以指向这些寄存器。通用寄存器具有地址短,存取速度快的特性,所以地址码指向通用寄存器的指令的长度也会更短,节省存储空间,执行效率更快。常被用于执行速度要求严格的指令中。
基址寄存器寻址:基址,即基础地址,基址寄存器就是存放基址的寄存器,可以是一个专用寄存器,也可以使用通用寄存器来充当基址寄存器。执行指令时,需要将基址与指令字的地址码结合得到完成的地址,此时的地址码充当着偏移量(位移量)的角色。当存储器容量较大时,直接寻址方式是无法存取到所有存储单元的,所以通常会采用 分段 或 分页 的内存管理方式。此时,段或页的首地址就会存放于基址寄存器中,而指令字的地址码就作为段或页的长度,这样只要修改基址寄存器的内容就可以访问到存储器的任意单元了。这种寻址方式常被用于为程序或数据分配存储区,与虚拟地址实现密切相关。基址寄存器寻址方式解决了程序在存储器中的定位存储单元和扩大 CPU 寻址空间的问题。
变址寄存器寻址:变址寄存器内的地址与指令字地址之和得到了实际的有效地址,如果 CPU 中存在基址寄存器,那么就还得加上基址地址。这种寻址方式常用于处理需要循环执行的程序,例如:循环处理数组,此时变址寄存器所改变的就是数组的下标了。
堆栈寻址:堆栈是有若干个连续的存储器单元组成的先进后出(FILO)存储区。堆栈是用于提供操作数和保存运算结果的主要存储区,同时还主要用于暂存中断和子程序调用时的线程数据及返回地址。
通过 MIPS 感受指令字的设计
MIPS(Millions of Instructions Per Second)是一种最简单的精简指令集架构,由 MIPS 科技公司设计。MIPS 指令具有 32 位(最新版本为 64 位),高 6 位为操作码(OPCODE),描述了指令的操作类型。其余 26 位具有 3 种格式:R、I 和 J。不同的指令类型和操作码组合能够完成多种功能实现,如下:
加法算数指令 add $t0,$s2,$s1
的指令字及其对应的机器码如下:
- opcode:0
- rs:代表第一个寄存器 s1 的地址是 17
- rt:代表第二个寄存器 s2 的地址是 18
- rd:代表目标临时寄存器 t0 的地址是 8
- shamt:0,表示不位移
最终加法算数指令 add $t0,$s2,$s1
的二进制机器码表示为 000000 10001 10010 01000 00000 1000000(0X02324020)。可以看见,机器码中没有保存任何实际的程序数据,而是保存了程序数据的储存的地址,这也算是存储程序计算机指令集设计的一大特点。
文章来源: is-cloud.blog.csdn.net,作者:范桂飓,版权归原作者所有,如需转载,请联系作者。
原文链接:is-cloud.blog.csdn.net/article/details/96435162
- 点赞
- 收藏
- 关注作者
评论(0)