文章目录
第1讲:指令系统的设计
主 要 内 容
- 指令系统设计的基本原则
- 指令类型和格式
- 数据类型
- 寄存器组织、存储器组织
- 操作数的寻址方式
- 立即 / 寄存器 / 寄存器间接 / 直接 / 间接 / 堆栈 / 偏移
- 操作码的编码
- 定长编码法、变长扩展编码法
- 条件码和标志寄存器
- 指令设计风格
- 异常和中断处理机制
Instruction Set Design
- 指令系统处在软/硬件交界面,同时被硬件设计者和系统程序员看到
- 硬件设计者角度:指令系统为CPU提供功能需求,要求易于硬件设计
- 系统程序员角度:通过指令系统使用硬件,要求易于编写OS和编译器
- 指令系统设计的好坏还决定了:计算机的性能和成本
回顾:冯.诺依曼结构机器对指令规定:- 用二进制表示,和数据一起存 放在主存中
- 由两部分组成:操作码和操作数(或其地址码)
- Operation Code: defines the operation type
- Operands: indicate operation source and destination
一条指令须包含的信息
- 问题:一条指令必须明显或隐含包含的信息有哪些?
- 操作码:指定操作类型
(操作码长度:固定/可变) - 源操作数参照:一个或多个源操作数所在的地址
(操作数来源:主(虚)存/寄存器/I/O端口/指令本身) - 结果值参照:产生的结果存放何处(目的操作数)
(结果地址:主(虚)存/寄存器/I/O端口) - 下一条指令地址:下条指令存放何处
(下条指令地址 :主(虚)存)
(正常情况隐含在PC中,改变顺序时由指令给出)
- 操作码:指定操作类型
一条指令中应该有几个地址码字段?
-
零地址指令
(1) 无需操作数 如:空操作/停机等
(2) 所需操作数为默认的 如:堆栈/累加器等
形式: -
一地址指令
其地址既是操作数的地址,也是结果的地址
(1) 单目运算:如:取反/取负等
(2) 双目运算:另一操作数为默认的 如:累加器等
形式: -
二地址指令(最常用)
分别存放双目运算中两个操作数,并将其中一个地址作为结果的地址。
形式: -
三地址指令(RISC风格)
分别作为双目运算中两个源操作数的地址和一个结果的地址。
形式: -
多地址指令
用于成批数据处理的指令,如:向量 / 矩阵等运算的SIMD指令。
4.2.1基本设计问题
从指令执行周期看指令设计涉及的问题**(这一章的内容)**
- 从存储器取指令
指令地址、指令长度(定长/变长) - 对指令译码,以确定将要做什么操作
指令格式、操作码编码、操作数类型 - 计算操作数地址并取操作数
地址码、寻址方式、操作数格式和存放方式 - 进行相应计算,并得到标志位
操作类型、标志或条件码 - 将计算结果保存到目的地
结果数据位置(目的操作数) - 计算下条指令地址(通常和取指令同时进行)
下条指令地址(顺序 / 转移)
指令格式的设计
- 指令格式的选择应遵循的几条基本原则
- 应尽量短
- 要有足够的操作码位数
- 指令编码必须有唯一的解释,否则是不合法的指令
- 指令字长应是字节的整数倍
- 合理地选择地址字段的个数
- 指令尽量规整
- 与指令集设计相关的重要方面
- 操作码的全部组成:操作码个数 / 种类 / 复杂度
LD/ST/INC/BRN 四种指令已足够编制任何可计算程序,但程序会很长 - 数据类型:对哪几种数据类型完成操作
- 指令格式:指令长度 / 地址码个数 / 各字段长度
- 通用寄存器:个数 / 功能 / 长度
- 寻址方式:操作数地址的指定方式
- 下条指令的地址如何确定:顺序,PC+1;条件转移;无条件转移;……
- 操作码的全部组成:操作码个数 / 种类 / 复杂度
- 一般通过对操作码进行不同的编码来定义不同的含义,操作码相同时,再由功能码定义不同的含义!
4.2.2 操作数类型和存储方式
- 操作数是指令处理的对象,与高级语言数据类型对应,基本类型有哪些?
- 地址(指针)
被看成无符号整数,用来参加运算以确定主(虚)存地址 - 数值数据
定点数(整数):一般用二进制补码表示
浮点数(实数):大多数机器采用IEEE754标准
十进制数:用NBCD码表示,压缩/非压缩(汇编程序设计时用) - 位、位串、字符和字符串
用来表示文本、声音和图像等
» 4 bits is a nibble(一个十六进制数字)
» 8 bits is a byte
» 16 bits is a half-word (若一个字为32位)
» 32 bits is a word (若一个字为32位) - 逻辑(布尔)数据
按位操作(0-假/1-真)
存放在寄存器或内存单元中
IA-32 & MIPS Data Type
- IA-32
- 基本类型:
» 字节、字(16位)、双字(32位)、四字(64位) - 整数:
» 16位、32位、64位三种2-补码表示的整数
» 18位压缩8421 BCD码表示的十进制整数 - 无符号整数(8、16或32位)
- 近指针:32位段内偏移(有效地址)
- 浮点数:IEEE 754(80位扩展精度浮点数寄存器)
- 基本类型:
- MIPS
- 基本类型:
» 字节、半字(16位)、字(32位)、四字(64位) - 整数: 16位、32位、64位三种2-补码表示的整数
- 无符号整数:(16、32位)
- 浮点数:IEEE 754(32位/64位浮点数寄存器)
- 基本类型:
4.2.3寻址方式 Addressing Modes
- 什么是“寻址方式”?
指令或操作数地址的指定方式。即:根据地址找到指令或操作数的方法。 - 地址码编码由操作数的寻址方式决定
- 地址码编码原则:
指令地址码尽量短
操作数存放位置灵活,空间应尽量大
地址计算过程尽量简单- 为什么?
目标代码短,省空间
利于编译器优化产生高效代码
指令执行快
- 为什么?
- 指令的寻址----简单
正常:PC增值
跳转 ( jump / branch / call / return ):同操作数的寻址 - 操作数的寻址----复杂(想象一下高级语言程序中操作数情况多复杂)
操作数来源:寄存器 / 外设端口 / 主(虚)存 / 栈顶
操作数结构:位 / 字节 / 半字 / 字 / 双字 / 一维表 / 二维表 /…
通常寻址方式特指“操作数的寻址” - 寻址方式的确定
(1)没有专门的寻址方式位(由操作码确定寻址方式)
如:MIPS指令,一条指令中最多仅有一个主(虚)存地址,且仅有一到两种寻址方式,Load/store型机器指令属于这种情况。
(2)有专门的寻址方式位
如:X86指令,一条指令中有多个操作数,且寻址方式各不相同,需要各自说明寻址方式,因此每个操作数有专门的寻址方式位。 - 有效地址的含义
操作数所在存储单元的地址(可能是逻辑地址或物理地址),可通过指令的寻址方式和地址码计算得到 - 基本寻址方式
立即 / 直接 / 间接 / 寄存器 / 寄存器间接 / 偏移 / 堆栈
基本寻址方式的算法和优缺点
假设:A=地址字段值,R=寄存器编号, EA=有效地址, (X)=X中的内容
- 问题:以上各种寻址方式下,操作数在寄存器中还是在存储器中?有没有可能在磁盘中?什么情况下,所取数据在磁盘中?
- 只有当操作数在存储器中时,才有可能“缺页”,此时操作数在磁盘中!
偏移寻址方式
指令中给出的地址码A称为形式地址
- 偏移寻址:EA=A+ ( R ) R可以明显给出,也可以隐含给出
R可以为PC、基址寄存器B、变址寄存器 I- 相对寻址: EA=A+(PC) 相对于当前指令处位移量为A的单元
- 基址寻址: EA=A+(B) 相对于基址(B)处位移量为A的单元
- 变址寻址: EA=A+(I) 相对于首址A处位移量为(I)的单元
- 相对寻址
- 指令地址码给出一个偏移量(带符号数),基准地址隐含由PC给出。
- 即:EA=(PC)+A (ex. MIPS’s instruction: Beq)
- 可用来实现程序(公共子程序)的浮动 或 指定转移目标地址
- 注意:当前PC的值可以是正在执行指令的地址或下条指令的地址
- 基址寻址
- 指令地址码给出一个偏移量,基准地址明显或隐含由基址寄存器B给出。即:EA=(B)+A (ex. MIPS’s instructions: lw / sw)
- 可用来实现多道程序重定位 或 过程调用中参数的访问
- 变址寻址
- 指令地址码给出一个基准地址,而偏移量(无符号数)明显或隐含由变址寄存器 I 给出。即:EA=(I)+A
- 可为循环重复操作提供一种高效机制,如实现对线性表的方便操作
相对寻址实现公共子程序的浮动
相对寻址实现相对转移
-
举例:双字节定长指令字,其中转移指令的第一字节是操作码Jxx,第二字节是位移量D,用补码表示,则转移目标指令相对于转移指令的范围为多少?-128~+127 ?不一定!
-
若转移指令地址为2000H,转移目标地址为1FF0H,总是在取指令同时对PC增量,则转移指令第二字节位移量为多少?不知道!
-
只有确定了是按字还是字节编址、位移量D是指指令条数还是单元数,才能确定目标地址范围(目标地址范围不等于位移量D的表示范围!)。
-
当按字节编址且D为单元数时,转移目标地址= (PC)+2+D
跳转范围:-126~128单元
- 63~64条指令- 1FF0H = 2000H+2+D
D=1FF0H–2002H=EEH(–18)
- 1FF0H = 2000H+2+D
-
举例:MIPS指令“beq $1, $2, 25”的转移目标地址为(PC)+4+4*25,这里的25是指令条数而不是单元数,MIPS采用定长指令字,按字节编址, 所有指令的长度都是32位(4字节)。
基址寻址实现程序重定位
用户程序装入系统后有一个基址,虽然偏移量都为51,但因基址不同,故操作数不同。
变址寻址实现线性表元素的存取
- 自动变址
指令中的地址码A给定数组首址,变址器I每次自动加/减数组元素的长度x。
EA=( I )+A
I=( I ) ± x
例如,X86中的串操作指令- 对于“for (i=0;i<N;i++) ….”,即地址从低→高增长:加
- 对于“for (i=N-1;i>=0;i–) ….”,即地址从高→低增长:减
- 可提供对线性表的方便访问
- 假定一维数组A从内存100号单元开始
- 若每个元素为一个字节,则 I=(I) ± 1
若每个元素为4个字节,则 I=(I) ± 4
- 若每个元素为一个字节,则 I=(I) ± 1
- 一般RISC机器不提供自动变址寻址,并将变址和基址寻址统一成一种偏移寻址方式
Example:MIPS中的循环处理
- for (i=0;i<N,i++) g = g +A[i];
- Assuming variables i, g ~ $7, $8 and base address of array is in $9,
- 数组元素为int类型,即 sizeof(int)=4。
- 数组元素为int类型,即 sizeof(int)=4。
4.2.5操作码编码
Instruction Format(指令格式)
- 操作码的编码有两种方式
- Fixed Length Opcodes (定长操作码法)
- Expanding Opcodes (扩展操作码编法)
- instructions size
- 代码长度更重要时:采用变长指令字、变长操作码
- 性能更重要时:采用定长指令字、定长操作码
- 为什么?
变长指令字和变长操作码使机器代码更紧凑;定长指令字和定长操作码便于快速访问和译码。学了CPU设计就更明白了。 - 问题:是否可以有定长指令字、变长操作码?定长操作码、变长指令字呢?
指令长度是否可变与操作码长度是否可变没有绝对关系,但通常是 :“定长操作码不一定是定长指令字”、 “变长操作码一般是变长指令字”。
定长操作码编码 Fixed Length Opcodes
- 基本思想
指令的操作码部分采用固定长度的编码
如:假设操作码固定为6位,则系统最多可表示64种指令 - 特点
译码方便,但有信息冗余 - 举例
- IBM360/370采用:
8位定长操作码,最多可有256条指令
只提供了183条指令,有73种编码为冗余信息
机器字长32位,按字节编址
有16个32位通用寄存器,基址器B和变址器X可用其中任意一个 - 问题:通用寄存器编号有几位?B和X的编号占几位?
都是4位!
- IBM360/370采用:
IBM370指令格式
扩展(变长)操作码编码 Expanding Opcodes
- 基本思想
将操作码的编码长度分成几种固定长的格式。被大多数指令集采用。PDP-11是典型的变长操作码机器。 - 种类
等长扩展法:4-8-12;3-6-9;…… / 不等长扩展法 - 举例说明如何扩展
PDP-11中典型指令格式
4.2.6标志信息的生成与使用
条件测试方式
- 条件转移指令通常根据Condition Codes (条件码 CC/ 状态位 / 标志位)转移
通过执行算术指令或显式地由比较和测试指令来设置CC
ex: sub r1, r2, r3 ;r2和r3相减, 结果在r1中,并生成标志位ZF、CF等
bz label ;标志位ZF=1时转到label处执行;否则顺序执行 - 常用的标志(条件码)有四种(哪四种?)
SF – negative OF – overflow
CF – 进位/借位 ZF – zero
借位如何生成?CF=Cout⊕sub - 标志可存标志寄存器/条件码寄存器
/状态寄存器/程序状态字寄存器
也可由指定的通用寄存器来存放状态位
Ex: cmp r1, r2, r3 ;比较r2和r3, 标志位存储在r1中
bgt r1, label ;判断r1是否大于0,是则转移到label处 - 可以将两条指令合成一条指令,即:计算并转移
Ex: bgt r1, r2, label ;如果r1>r2,则转移到label处执行;否则顺序执行 - 对于带符号和无符号运算,标志生成方式有没有不同?
没有,因为加法电路不知道是无符号数还是带符号整数! - bgt的条件?
无符号数:ZF=0^CF=0
带符号整数:ZF=0^SF≡OF
标志信息是干什么的?
IA-32中的条件转移指令
分三类:
(1)根据单个标志的值转移
(2)按无符号整数比较转移
(3)按带符号整数比较转移
4.2.7指令系统设计风格
指令设计风格 – 按操作数位置指定风格来分
- Accumulator: (earliest machines) 累加器型
- 特点:其中一个操作数(源操作数1)和目的操作数总在累加器中
1 address add A acc ← acc + mem[A]
1(+x) address add x A acc ← acc + mem[A + x]
- 特点:其中一个操作数(源操作数1)和目的操作数总在累加器中
- Stack: (e.g. HP calculator, Java virtual machines) 堆栈型
- 特点:总是将栈顶两个操作数进行运算,指令无需指定操作数地址
0 address add tos ← tos + next
- 特点:总是将栈顶两个操作数进行运算,指令无需指定操作数地址
- General Purpose Register: (e.g. IA-32, Motorola 68xxx) 通用寄存器型
- 特点:操作数可以是寄存器或存储器数据(即A、B和C可以是寄存器或存储单元)
2 address add A B EA(A) ← EA(A) + EA(B)
3 address add A B C EA(A) ← EA(B) + EA©
- 特点:操作数可以是寄存器或存储器数据(即A、B和C可以是寄存器或存储单元)
- Load/Store: (e.g. SPARC, MIPS, PowerPC) 装入/存储型
- 特点:运算操作数只能是寄存器数据,只有load/store能访问存储器
3 address add Ra Rb Rc Ra ← Rb + Rc
load Ra Rb Ra ←mem[Rb]
store Ra Rb mem[Rb] ← Ra
- 特点:运算操作数只能是寄存器数据,只有load/store能访问存储器
指令风格比较
Examples of Register Usage
指令设计风格 – 按指令格式的复杂度来分
- 按指令格式的复杂度来分,有两种类型计算机:
复杂指令集计算机CISC (Complex Instruction Set Computer)
精简指令集计算机RISC (Reduce Instruction Set Computer) - 早期CISC设计风格的主要特点
- (1) 指令系统复杂
变长操作码 / 变长指令字 / 指令多 / 寻址方式多 / 指令格式多 - (2) 指令周期长
绝大多数指令需要多个时钟周期才能完成 - (3) 各种指令都能访问存储器
除了专门的存储器读写指令外,运算指令也能访问存储器 - (4) 采用微程序控制
- (5) 有专用寄存器
- (6) 难以进行编译优化来生成高效目标代码
- (1) 指令系统复杂
- 例如,VAX-11/780小型机
16种寻址方式;9种数据格式;303条指令;
一条指令包括1~2个字节的操作码和下续N个操作数说明符。一个说明符的长度达1 ~10个字节。
复杂指令集计算机CISC
- CISC的缺陷
- 日趋庞大的指令系统不但使计算机的研制周期变长,而且难以保证设计的正确性,难以调试和维护,并且因指令操作复杂而增加机器周期,从而降低了系统性能。
- 1975年IBM公司开始研究指令系统的合理性问题,John Cocks提出精简指令系统计算机 RISC ( Reduce Instruction Set Computer )。
- 对CISC进行测试,发现一个事实:
- 在程序中各种指令出现的频率悬殊很大,最常使用的是一些简单指令,这些指令占程序的80%,但只占指令系统的20%。而且在微程序控制的计算机中,占指令总数20% 的复杂指令占用了控制存储器容量的80%。
- 1982年美国加州伯克利大学的RISCⅠ,斯坦福大学的MIPS,IBM公司的IBM801相继宣告完成,这些机器被称为第一代RISC机。
Top 10 80x86 Instructions
RISC设计风格的主要特点
- (1) 简化的指令系统
指令少 / 寻址方式少 / 指令格式少 / 指令长度一致 - (2) 以RR方式工作
除Load/Store指令可访问存储器外,其余指令都只访问寄存器。 - (3) 指令周期短
以流水线方式工作, 因而除Load/Store指令外,其他简单指令都只需一个或一个不到的时钟周期就可完成。 - (4) 采用大量通用寄存器,以减少访存次数
- (5) 采用组合逻辑电路控制,不用或少用微程序控制
- (6) 采用优化的编译系统,力求有效地支持高级语言程序
- MIPS是典型的RISC处理器,82年以来新的指令集大多采用RISC体系结构
x86因为“兼容”的需要,保留了CISC的风格,同时也借鉴了RISC思想
指令系统举例: Address & Registers
指令系统举例:Pentium指令格式
Pentium处理器的寻址方式
- 操作数的来源:
立即数(立即寻址):直接来自指令
寄存器(寄存器寻址):来自32位 / 16位 / 8位通用寄存器
存储单元(其他寻址):需进行地址转换
虚拟地址 => 线性地址LA ( => 内存地址)
分段 分页 - 指令中的信息:
(1) 段寄存器SR(隐含或显式给出)
(2) 8/16/32位偏移量A (显式给出)
(2) 基址寄存器B (明显给出,任意通用寄存器皆可)
(3) 变址寄存器I (明显给出,除ESP外的任意通用寄存器皆可。)- 有比例变址和非比例变址
- 比例变址时要乘以比例因子S (1:8位 / 2:16位 / 4:32位 / 8:64位)
- 指令“ MOV EAX, ES: [EBP+ESI*8+100]”的含义是什么?
保护模式下的寻址方式
存储器操作数的寻址方式
int x;
float a[100];
short b[4][4];
char c;
double d[10];
- a[i]的地址如何计算?
104+i×4
i=99时,104+99×4=500 - b[i][j]的地址如何计算?
504+i×8+j×2
i=3、j=2时,504+24+4=532 - d[i]的地址如何计算?
544+i×8
i=9时,544+9×8=616 - 各变量应采用什么寻址方式?
x、c:位移 / 基址
a[i]:104+i×4,比例变址+位移
d[i]:544+i×8,比例变址+位移
b[i][j]: 504+i×8+j×2,
基址+比例变址+位移 - 将b[i][j]取到AX中的指令可以是:
“movw 504(%ebp,%esi,2), %ax”
其中, i×8在EBP中,j在ESI中,
2为比例因子
Pentium处理器的存储器寻址
MMX(Microprocessor Media Extension)指令技术
- 图形/像、音/视频多媒体信息处理特点
- 多个短整数并行操作(如8位图形像素和16位音频信号)
- 频繁的乘-累加(如FIR滤波,矩阵运算)
- MMX的出发点
- 使用专门指令对大量数据进行并行、复杂处理
- 处理的数据基本单位是8b、16b、32b、64b等
- MMX指令集由Intel提出,1997年首次用于P54C Pentium处理器
- 引入新的数据类型和通用寄存器
- 四种64位紧缩定点整数类型(8 x 1B、4 x 1W、2 x 2W、1 x 4W)
- 8个64位通用寄存器MX0~MX7(借用8个80位浮点寄存器)
- 采用SIMD(Single Instruction Multi Data)技术
- 单条指令同时并行处理多个数据元素
例如,一条指令完成图像中8个像素的并行操作
- 单条指令同时并行处理多个数据元素
- 引入饱和(Situration)运算
非饱和(环绕)运算:上溢时高位数据被截去;饱和运算:上溢时结果取最大值
例如,图像插值运算:若a点亮度F3H,b点亮度1DH,对a和b线性插值结果为:
环绕运算:(F3H+1DH)/2=10H/2=08H 插值点的亮度比1DH还低,不合理!
饱和运算: (F3H+1DH)/2=FFH/2=7FH 合理
- 引入新的数据类型和通用寄存器
- 在Intel以后的处理器中又增加了SSE、SSE2、SSE3,AVX等指令集
SSE(Streaming SIMD extensions)
4.2.8异常和中断处理机制
- 程序执行过程中CPU会遇到一些特殊情况,使正在执行的程序被“中断”
- CPU中止原来正在执行的程序,转到处理异常情况或特殊事件的程序去执行,结束后再返回到原被中止的程序处(断点)继续执行。
- 程序执行被 “中断” 的事件有两类
- 内部异常:在CPU执行某指令时内部发生的意外事件或特殊事件
故障(fault):执行某条指令时发生的异常事件,如溢出、缺页、越界、越权、越级、非法指令、除数为0、堆/栈溢出、访问超时等。
自陷(trap):执行预先设置的指令,如断点、单步、系统调用等。
终止(abort):指令执行过程中出现了硬件故障,如访存校验错等。 - 外部中断:在CPU外部发生的特殊事件,通过“中断请求”信号向CPU请求处理。如实时钟、控制台、打印机缺纸、外设准备好、采样计时到、DMA传输结束等。
- 内部异常:在CPU执行某指令时内部发生的意外事件或特殊事件
- 异常/中断处理分两个阶段
- 检测和响应:由硬件完成
- 具体的处理过程由软件(操作系统)执行程序完成
- 发生异常(exception)和中断(interrupt)事件后,系统将进入OS内核态对相应事件进行处理,即改变处理器状态(用户态→内核态)
第一讲小结
- 指令由“操作码”和“地址码”两部分组成。
- 操作类型
- 传送 / 算术 / 逻辑 / 移位 / 字符串 / 转移控制 / 调用 / 中断 / 信号同步
- 操作数类型
- 整数(带符号、无符号、十进制)、浮点数、位、位串
- 地址码的编码要考虑:
- 操作数的个数
- 寻址方式:立即 / 寄存器 / 寄间 / 直接 / 间接 / 相对 / 基址 / 变址 / 堆栈
- 操作码的编码要考虑:
- 定长操作码 / 扩展操作码
- 条件码的生成
- 四种基本标志:NF(SF) / VF(OF) / CF / ZF
- 指令设计风格:
- 按操作数地址指定方式来分:
- 累加器型 、堆栈型 、通用寄存器型、load/store型
- 按指令格式的复杂度来分
- 复杂指令集计算机CISC、精简指令集计算机RISC
- 按操作数地址指定方式来分:
- 异常和中断
以下通过MIPS指令系统,介绍如何在机器语言级表示程序