计算机组成原理与系统结构——指令集:特性与功能
计算机组成原理与系统结构——指令集:特性与功能
计算机指令集是计算机硬件与软件之间的桥梁,它定义了CPU能够执行的各种操作。本文将从机器指令的特性、指令表示、指令类型、地址个数、指令集设计等多个维度,深入浅出地介绍计算机指令集的相关知识。
机器指令特性
CPU的操作由其执行的指令决定,称为机器指令/计算机指令,CPU可以执行的不同指令的集合称为CPU的指令集。
机器指令的要素
指令必须包含CPU执行时所需信息,它展示指令执行的步骤并暗示定义了机器指令的要素。
- 操作码——指明要执行操作的二进制编码
- 源操作数引用——操作可能涉及一个或多个源操作数,即为操作而输入的操作数
- 结果操作数引用——操作可能产生的结果
- 下一条指令引用——当前指令执行完成后,告诉CPU去哪儿取下一条指令(实地址OR虚拟地址取决于体系结构)
源操作数和结果操作数可以位于下列四个区域之一:
- 主存/虚拟内存——与下一条指令的引用一样,必须通过主存/虚拟内存地址
- CPU寄存器——CPU包含一个或多个寄存器,寄存器由机器指令引用
- 立即数——正在执行的指令字段中包含了操作数的值
- I/O设备——指令必须为操作指定I/O模块和设备,若使用内存映射I/O,则这是另一个主存/虚拟内存地址
指令表示
在计算机中,每条指令都表示一个唯一的位序列。指令被划分为字段,对应于该指令的组成元素。下图是一个简单的指令格式示例:4位操作码,2个6位操作数引用。
程序员和读者都很难处理机器指令的二进制代码,因而使用符号表示。例如ADD表示加法、SUB表示减法、MUL表示乘法、DIV表示除法、LOAD表示从内存加载数据、STOR表示向内存存储数据等。操作数也可以表示为符号,例如ADD X,Y意味着把数据位置Y包含的值加到寄存器X的内容上。
指令类型
计算机应该具有一组允许用户指定任何数据处理任务的指令,查看指令的另一种方法是考虑高级编程语言的功能。当然,任何用高级语言编写发程序都必须译码成机器语言才能被执行。因此,机器指令集必须足以表示任何来自高级语言的指令,并以此指令类型:
- 数据处理——算术和逻辑指令
- 数据存储——数据移入/移出寄存器和内存位置
- 数据移动——I/O指令
- 控制——测试和分支指令
任何高级语言编写的程序都能翻译成上述指令,任何数据处理任务都能用上述指令表示。
地址个数
描述处理器体系结构的传统方法是看每条指令包含的地址个数。所有的算术和逻辑操作要么是一元的(一个源操作数),要么是二元的(两个源操作数)。因此我们最多需要两个地址来引用源操作数。操作的结果必须保存,建议用第三个地址来定义目的操作数。最后指令完成之后,必须取下一条指令,因而需要该指令地址。现代计算机通常采用两个或三个地址指令。
这种推导方式表明,一条指令可能需要包含4个地址引用:两个源操作数,一个目的操作数和一个下一条地址引用。大多数体系结构中,许多指令有一个、两个或三个操作数地址,而下一条地址引用是隐含的(从程序计数器获得)。
简单直观、4次访问主存、地址空间2^6=64
隐含下一个指令地址、4次访问主存、地址空间2^8=256
地址兼作操作数和结果、4次访问主存、地址空间2^12=4K
隐含第二地址、2次访问主存、地址空间2^24=16M
更多地址——更复杂的指令、更多的寄存器、每个程序的指令更少
更少地址——不太复杂的指令、每个程序的指令更多、获取和执行指令更快
指令集设计
指令集是程序员控制CPU的手段,定义了CPU执行的功能,指令集设计的基本问题包括:
- 操作库——提供操作的数量、种类和复杂度
- 数据类型——用于执行的各种数据类型
- 指令格式——指令长度、地址个数、各字段大小等
- 寄存器——能被指令引用的CPU寄存器个数及它们的用法
- 寻址——一个或多个指定操作数地址的方式
操作数类型
机器指令对地址、数字、字符、逻辑数据等数据进行操作。许多情况必须对指令中的操作数引用执行计算以决定主存或虚拟内存的地址,此时地址可以被认为是无符号整数。
- 地址——无符号整数
- 数字——使用各种进制的整数/浮点/小数
- 字符——ASCII、EBCDIC
- 逻辑数据——位或标志、布尔值
操作类型
不同操作码的数量因机器而呈现出很大差异,但所有机器中都能找到相同的常规操作类型。有用而典型的分类是数据传输、算术运算、逻辑运算、转换、I/O、系统控制、转移控制。
数据传输
数据传输指令是最基本的机器指令。数据传输指令必须指定以下几件事:
- 指定源操作数和目的操作数的位置,如内存、寄存器、栈顶
- 指明待传输数据的长度
- 指定每个操作数的寻址方式
对于CPU操作,数据传输可能是最简单的类型,若有一个或两个操作数在内存中,则CPU必须执行下列的某些或全部操作:
- 根据地址模式计算内存地址
- 若地址指向虚拟内存,则将虚拟地址转换为实际地址
- 确定被寻址项是否在高速缓存中
- 若不是,则向模块发出命令
算术运算
大多数机器都提供基本的算术操作:加法、减法、乘法、除法。这些操作总是提供给有符号整数,一般还提供给浮点数和压缩十进制数。其他可能操作还包括各种单操作数指令,例如绝对值、取负、递增、递减。
逻辑运算
大多数机器还提供各种操作来控制字或其他可寻址单元的单个位,一般称为“位运算”,它们都以布尔运算为基础。带两个操作数的常见逻辑函数是NOT、AND、OR、XOR。
- 逻辑移位——将一个字中的位左移/右移,在一端丢失移出的位,在另一端移入0。逻辑移位主要用于隔离字中的字段,移入字中的0替换了从另一端移出的不再需要的信息。
- 算术移位——把数据当作有符号整数且不移动符号位。在算术右移时符号位被复制到其右边的位上,在算术左移时除了符号位之外的其他所有位被逻辑左移。而对于使用二进制补码的数来说,算术右移对应除2并截断奇数,算术左移对应乘2。
- 循环移位——保留所有被处理的位,把每个位依次带入最左边的位,并可以通过测试数据的符号(被当作数来处理)来识别。
转换
转换指令指那些改变数据格式或对数据格式进行操作的指令,例如从十进制转换为二进制。翻译是转换的一种情况,指内存中的某些值通过表查询进行转换,例如ASCII-->EBCDIC。
I/O
I/O可以采用多种方法,包括独立编程I/O、内存映射编程I/O、直接内存访问DMA、使用I/O处理器,许多只提供少许I/O指令,其中包含由参数、编码或命令字指定的特定操作。
系统控制
系统控制指令指那些仅当CPU处于某种特权状态或在特殊特权内存区执行程序时才能执行的指令,通常这些指令保留给操作系统使用。例如读取或修改存储保护密钥的指令,在多道程序设计系统中访问进程控制块的指令。
转移控制
对于到目前为止讨论的所有操作类型,要执行的下一条指令是内存中紧跟当前指令的一条。但是任何程序中都有相当一部分指令的功能是改变指令执行的顺序。对这些指令来说,CPU执行的操作是更新程序计数器,以包含内存中某条指令的地址。
指令集中最常见的转移控制操作包括分支、跳过、过程调用。
- 分支——也称跳转指令,其操作数之一是将要执行的下一条指令的地址,通常这是条件分支指令。也即仅当满足特定条件时才执行分支,否则将顺序执行下一条指令。若总是执行分支指令中的分支,则为无条件分支。
- 跳过——跳过指令有一个隐含地址,通常意味着一条指令被跳过。因此隐含地址等于下一条指令的地址和长度,由于跳过指令不需要目标地址字段,所以它可以自由地执行其他操作。例如ISZ指令:若为零则递增并跳过。
- 过程调用——过程是一种独立的计算机程序,它被合并到更大的程序中。在程序的任何位置都可以调用过程。CPU被指示去执行整个过程,然后返回调用开始的地方。
过程机制包含两条基本指令:其一,调用指令——从当前位置分支到过程;其二,返回指令——从过程返回到该过程被调用的位置。这两条基本指令都是分支指令的形式。
过程调用的优点是经济性和模块化,它允许多次使用相同的代码片段,还允许把大型编程任务分解为较小的单元,从而极大地简化编程任务。