1.基本概念
- 机器指令:
由二进制代码表示的,CPU能够直接识别并执行的操作命令。机器指令是机器语言的基本单位。
- 机器语言:
由二进制代码组成的最低级别编程语言,直接被CPU执行。机器语言与特定的CPU架构紧密相关,不同的CPU有不同的机器语言。机器语言可以看做是指令集的二进制表示。
- 指令集:
CPU所能够执行的所有指令的集合,是处理器架构的一部分。
- 指令系统:
计算机系统中所有指令的组合和组织方式。指令系统不仅包括指令集,还涉及指令的实现方式、执行效率和指令之间的协同工作。指令系统提供了计算机软硬件之间的接口(软件通过指令系统把需要执行的操作告知硬件,硬件通过指令系统把运算结果和硬件的状态返回给软件)。
- 操作系统:
操作系统是管理计算机硬件和软件资源的系统软件,为计算机用户和应用程序提供基本服务。操作系统提供用户与计算机的接口。
指令系统 | 操作系统 | |
层次 | 位于计算机硬件层之上,直接与处理器硬件交互,是最低级别的软件接口。 | 位于指令系统之上,为用户和应用程序提供高级别的服务和环境。 |
功能 | 提供基本的指令集合,供处理器执行基本操作,如算术运算、数据移动、逻辑运算、控制流等。 | 管理硬件资源,提供系统服务,简化应用程序开发和运行,提供用户接口。 |
作用范围 | 只涉及处理器能够直接执行的指令和操作,是硬件和软件之间的直接接口。 | 涵盖整个计算机系统的资源管理和服务提供,协调硬件和软件资源的有效使用。 |
2.机器指令
2.1指令的格式
注:操作码字段集中放置只是一种逻辑的表示,实际中可以分散。
1.操作码
(1)作用
指出进行什么操作、对什么样的数据进行操作、操作数的寻址方式。
(2)长度
a.长度固定
集中在指令的某一个特定字段中。用于指令字较长的情况,固定操作码可使译码过程方便,译码电路简单。例如精简指令集系统(RISC)、IBM 370。
b.长度可变
操作码分散在指令字的不同字段中。例如x86系列处理器。
(3)扩展操作码技术
a.保留一个编码的码点作为扩展标志
假设OP是操作码字段,A1、A2、A3都是地址码字段,且长度均为4位。操作码的位数随地址数的减少而增加。下图中蓝色字体为扩展标志(码点)。
为了使计算机能够正确识别操作码,扩展过程中需遵循原则:短操作码不能是长操作码的前缀。
三地址指令操作码每减少一种,最多可构成2^4种二地址指令。(例如,将1110和1111均作为二地址指令的码点,则三地址指令减少了1110开头的1条,而二地址指令增加了1110开头的2^4条。)同理,二地址指令操作码每减少一种,最多可构成2^4种一地址指令。
b.利用操作码当中某一位作为扩展标志
2.地址码
(1)四地址
(A1)OP(A2)-->A3
访存次数:4次(取指*1,取操作数*2,结果写入内存*1)。
假设指令字长和操作码长度固定,地址码的长度相等,为了扩大寻址范围,需要减少地址码的数量,增加其长度。
(2)三地址
用PC代替A4。
(A1)OP(A2)-->A3
访存次数:4次(取指(到PC)*1,取操作数*2,结果写入内存*1)。
(3)二地址
进一步减少地址码字段,取消A3,将运算结果保存在A1或A2中。
(A1)OP(A2)-->A1
(A1)OP(A2)-->A2
访存次数:4次(取指(到PC)*1,取操作数*2,结果写入内存*1)。
为了减少访存次数,可将结果保存在寄存器ACC中(3次访存)。
(A1)OP(A2)-->ACC
(4)一地址
若用ACC代替A1或A2,可进一步减少地址码的位数,并减少访存次数。只需指明另外一个操作数 在内存单元中的地址。
(ACC)OP(A1)-->ACC
访存次数:2次(取指(到PC)*1,取操作数*1)。
(5)零地址
无地址码。例如对ACC中的数据进行操作,ACC采用隐含寻址的方式(在操作码中做出规定),或者对堆栈类型的寄存器进行操作,操作数隐含在堆栈指针中。
访存次数:1次(取指(到PC)*1)。
若将指令预取到缓存中,取指令可以不直接访问主存,但仍依赖于处理器内部资源,并不是完全意义上的不访存。
(6)指令的地址字段为寄存器
若指令字长不固定,由于寄存器的数量远远少于主存地址单元的个数,编码所需的地址码字段长度较短,因此当指令的地址字段为寄存器时,可以缩短指令字长,同时减少访存次数。
2.2指令的字长
由指令的格式,不难看出指令字长= 操作码的长度+操作数地址的长度*操作数地址的个数
机器字长:处理器一次处理的二进制位数。机器字长与通用寄存器的宽度相同,此外,程序计数器(PC)和堆栈指针(SP)通常与机器字长相同;
存储字长:计算机内存中每个存储单元的位数,即内存中一次性可以存储和读取的数据位;
总线宽度:处理器和内存之间一次可以传输的数据量;
指令字长:一条指令所包含的位数,通常是处理器架构的一部分。指令字长与机器字长有关,通常为单字长、双字长或半字长(在许多指令集架构中,为了节省指令长度和存储空间,可以采用灵活的寻址方式,使指令中的地址码长度小于内存地址的长度)。指令字长越长,地址码长度越长,可直接寻址空间越大,但同时指令字占用空间越大,取指令越慢。
理想情况下,机器字长、存储字长、总线宽度相匹配,以保证传输效率,实际中三者没有固定的长度大小关系,但都为字节的整数倍。计算机字长通常指的是机器字长,因为机器字长直接影响了处理器的基本运算能力和内存访问能力。
(1)固定字长
指令字长<=存储字长
定长指令结构简单,控制线路简单,如MIPS指令。
(2)可变字长
指令字长按字节的倍数变化
变长指令结构灵活,充分利用指令长度,控制复杂,如x86指令。
3.操作数类型和操作种类
3.1操作数类型
地址 无符号整数(绝对寻址)、有符号整数(相对寻址)
数字 定点数、浮点数、十进制数
字符 ASCII
逻辑数 逻辑运算
3.2操作类型
(1)x86指令的操作类型
类型 | 举例 | |
数据传送类 | 取数 | MOV AX,TEMP(表示将TEMP中的数据传送到寄存器AX中,TEMP可以是一个立即数、寄存器或者内存地址。) |
存数 | MOV TEMP,AX(TEMP可以是一个内存地址,也可以是一个变量名或者一个内存偏移量,表示数据要存储的位置。) | |
传送 | MOV AX,CX(将寄存器CX中的值传送给寄存器AX。) | |
算术运算类 | 定点 | 加,减,乘,除等 |
浮点 | 加,减,乘,除等 | |
整数 | 加,减,乘,除,求反,求补等 | |
逻辑运算类 | NOT,AND,OR,XOR,TEST | |
程序控制类 | 无条件转移 | JMP |
条件转移 | C(进位标志),Z(零标志),N(符号标志),P(奇偶标志),V(溢出标志) | |
转子程序 | JSR | |
子程序返回 | RET | |
中断返回 | IRET | |
输入/输出类 | 输入 | IN AX,n |
输出 | OUT n,AX | |
其他类 | CLC(Clear Carry Flag)将进位标志寄存器清零 CLI(Clear Interrupt Flag)将中断标志寄存器清零 HLT WAIT |
(2)MIPS指令的操作类型
类型 | 举例 | 格式 | |||
运算指令 | 算数 | add | 有符号整数相加指令,将两个寄存器中的值相加,并将结果存储到目标寄存器中。 | add $rd, $rs, $rt rd:目标寄存器 rs:第一个源寄存器 rt:第二个源寄存器 | |
addi | 有符号整数立即数相加指令,将一个寄存器中的值与一个立即数相加,并将结果存储到目标寄存器中。 | addi $rt,$ts,immediate rt:目标寄存器 rs:源寄存器 immediate:立即数(16位有符号整数) | |||
addu | 无符号整数相加指令,与add指令类似,但不处理溢出。 | addu $rd, $rs, $rt | |||
addiu | 无符号整数立即数相加指令,与addi指令类似,但不处理溢出。 | addiu $rt,$rs,immediate (16位无符号整数) | |||
sub | 有符号整数减法指令,将第二个寄存器的值从第一个寄存器的值中减去,并将结果存储到目标寄存器中。 | sub $rd, $rs, $rt | |||
subu | 无符号整数减法指令,与sub指令类似,但不处理溢出。 | subu $rd, $rs, $rt | |||
mult | 有符号整数乘法指令,将两个寄存器中的值相乘,并将结果存储到HI和LO寄存器中。 | mult $rs, $rt | |||
multu | 无符号整数乘法指令,与mult指令类似,但对无符号整数进行乘法。 | multu $rs, $rt | |||
div | 有符号整数除法指令,将第一个寄存器的值除以第二个寄存器的值,并将商存储到LO寄存器中,余数存储到HI寄存器中。 | div $rs, $rt | |||
divu | 无符号整数除法指令,与div指令类似,但对无符号整数进行除法。 | divu $rs, $rt | |||
slt | 有符号整数比较指令,比较两个寄存器中的值,如果第一个值小于第二个值,则将目标寄存器设置为1,否则设置为0。 | slt $rd, $rs, $rt | |||
slti | 有符号整数立即数比较指令,将一个寄存器中的值与一个立即数进行比较,设置目标寄存器的值为1或0。 | slti $rt, $rs, immediate | |||
sltiu | 无符号整数立即数比较指令,与slti指令类似,但对无符号整数进行比较。 | sltu $rt, $rs, immediate | |||
逻辑 | and,andi,or,ori,xor,xori,nor(均为按位操作) | and $rd, $rs, $rt andi $rt, $rs, immediate | |||
移位 | sll(Shift Left Logical) 将寄存器中的值逻辑左移指定的位数。 sllv(Shift Left Logical Variable) 将寄存器中的值逻辑左移,移位量由另一个寄存器中的值指定。 srl srlv sra(Shift Right Arithmetic) 将寄存器中的值算术右移指定的位数。 srav(Shift Right Arithmetic Variable) 将寄存器中的值算数右移,移位量由另一个寄存器中的值指定。 | sll $rd, $rt, sa sa:移位位数(5位立即数) sllv $rd, $rt, $rs rs:指定移位位数的寄存器 | |||
分支指令 | beq:比较两个寄存器,如果它们相等,则跳转到指定的地址。 | beq $rs, $rt, offset | |||
bne | |||||
blez(<=0):检查寄存器的值,如果小于或等于零,则跳转到指定的地址。 | blez $rs, offset | ||||
bgez(>=0) | |||||
bltz(<0) | |||||
bgtz(>0) | |||||
jal(jump and link):跳转到指定的地址并保存返回地址到寄存器$ra(一般为$31)。 | jal target | ||||
j:无条件跳转到指定的地址。 | j target | ||||
jr:跳转到寄存器中存储的地址,常用于返回调用者。 | jr $rs | ||||
访存指令 | lw:从内存中加载一个字到指定的寄存器。 lh,lb,sw,sh,sb | lw $rt, offset($rs) offset为偏移字节数 | |||
系统指令 | syscall:执行系统调用,通常用于与操作系统进行交互,例如 I/O 操作。 break:产生一个断点异常,一般用于调试。 sync:同步指令,确保之前的指令在之后的指令执行前完成(主要用于多处理器系统中的同步)。 cache:用于管理缓存操作,例如刷新或无效缓存行。 | syscall break sync cache op,offset(base) |
4.寻址方式
寻址:确定本条指令的操作数地址,或下一条要执行的指令的地址。
4.1指令寻址
(1)顺序寻址
(PC)+1-->PC
偏移量为一条指令的长度
(2)跳跃寻址
目标地址由转移指令指出
4.2数据寻址
(1)指令格式
形式地址A:指令字中的地址
有效地址EA:操作数的真实地址
(2)立即寻址
A是补码形式的立即数,可正可负。
A就是操作数,在取指阶段被写入CPU中,执行阶段无需再次访存。A的位数决定操作数的范围。
(3)直接寻址
EA=A 有效地址(内存单元的物理地址)由形式地址直接给出。A的位数决定操作数的寻址范围。
根据内存单元的物理地址访问内存,取出操作数并送到寄存器ACC中。需要访问一次存储器。
(4)隐含寻址
寻址方式隐含在操作码中,或参与运算的某个数据的位置由操作码直接给出。
寻址特征指出的是A的寻址特征,在上图中,A是其中一个操作数的地址,采用直接寻址的方式。另一个操作数隐含在ACC中。执行一次指令的过程中需要访问一次存储器。
其他例子:
以8086处理器为例,MUL指令的被乘数隐含在AX(16位)或AL(8位)中,MOVS指令源操作数的地址隐含在SI中,目的操作数的地址隐含在DI中。
采用隐含寻址的方式,指令中地址字段减少,可缩短指令字长。
(5)间接寻址
操作数的地址保存在某一个内存单元中。
EA=(A) 有效地址由形式地址间接提供
a.一次间址
有效地址保存在A指向的内存单元中
显然指令执行阶段需要进行两次访存。
通过这种方式可以扩大寻址范围,并且只需要修改EA的值就可以修改操作数的地址,方便编制程序。
b.多次间址
A是下一个中间地址的地址。通过标志位1或0区分中间地址和有效地址。
c.间接寻址的应用
将程序断点保存在A指向的地址单元,子程序执行完后返回。
(6)寄存器寻址(寄存器直接寻址)
EA=Ri 有效地址为寄存器编号
执行阶段 Q不访存,只访问寄存器,执行速度快。另外寄存器的个数有限,编码短,可缩短指令字长。
(7)寄存器间接寻址
EA=(Ri) 有效地址在寄存器中
执行阶段需要访存。要修改操作数的地址只需修改寄存器的内容,便于编制循环程序。
(8)基址寻址
a.采用专用寄存器作为基址寄存器
EA=(BR)+A BR为基址寄存器
基址寻址方式可以扩大寻址范围,另外有利于多道程序设计, 将程序的起始地址放在BR,执行过程中动态的形成操作数的地址(程序的动态定位)。
基址寄存器的内容一般由操作系统或管理程序确定,用户不能修改。
b.采用通用寄存器作为基址寄存器
可以由用户指定哪个寄存器作为基址寄存器,但是执行过程中基址寄存器的内容由操作系统决定, 用户不能修改,形式地址A可变。
(9)变址寻址
EA=(IX)+A IX为变址寄存器(可以专用,也可以指定通用寄存器作为变址寄存器)
IX的内容由用户指定,程序执行过程中IX内容可变,A是固定的,便于处理数组问题。
注:
#是直接寻址特征,#后面的数即为操作数
指令ADD X,D的含义为(ACC)+((X)+D)-->ACC
(10)相对寻址
EA=(PC)+A A是相对于当前指令的位移量,是补码形式的立即数,可正可负。
A的位数决定操作数的寻址范围。有利于程序浮动(程序在内存中的存数位置发生变化),广泛应用于转移指令(实际上是指令寻址)。
在取出当前指令后执行指令之前,PC就已经完成+1的操作。
(11)堆栈寻址
堆栈 | 硬堆栈 | 使用较多。两个或以上的寄存器作为栈顶,内存作为栈底。 |
软堆栈 | 8086使用软堆栈。是指定的内存空间。 |
栈顶地址由SP指出。栈顶为低地址。
进栈 (SP)-1->SP (更新SP的位置,使其指向新的栈顶元素)
出栈 (SP)+1->SP
注:加1或减1前提是压栈或弹栈的数据恰好占用一个编址单元,实际上偏移量为1个存储字长的字节数。
5.指令格式举例
5.1设计指令格式应考虑的各种因素
1.指令系统的兼容性
2.操作类型 包括指令个数及操作的难易程度
3.数据类型 确定哪些数据类型可以参与操作
4.指令格式 指令字长是否固定;操作码位数、是否使用扩展操作码技术;地址码位数、地址个数、寻址方式类数
5.寻址方式 指令寻址、操作数寻址,各个操作能够使用哪些寻址方式,针对不同的数据类型有什么区别
6.寄存器个数 寄存器的多少直接影响指令执行的时间
5.2MIPS指令集
1.32个通用寄存器
寄存器 | 助记符 | 释义 |
0 | $zero | 常量寄存器,值固定为0,硬件实现 |
1 | $at | 临时变量,保留给汇编器使用 |
2~3 | $v0~$v1 | 函数调用返回值 |
4~7 | $a0~$a3 | 四个函数调用参数 |
8~15 | $t0~$t7 | 暂存寄存器,子程序内可以直接调用 |
16~23 | $s0~$s7 | 变量寄存器,子程序返回应复原内容 |
24~25 | $t8~$t9 | 暂存寄存器,子程序内可以直接调用 |
26~27 | $k0~$k1 | 操作系统保留,中断异常处理 |
28 | $gp | 全局指针 |
29 | $sp | 栈指针 |
30 | $fp | 帧指针 |
31 | $ra | 函数返回地址 |
MIPS的寄存器:
- 32个通用寄存器$0~$31
- 32个 单精度浮点寄存器f0~f31
- 2个乘商寄存器Hi和L0
- PC有单独的寄存器
- 没有程序状态寄存器
- 没有专门的寻址方式字段,寻址方式由OP指定
- RISC-V有类似的32个寄存器设置
2.三种指令格式
所有指令都是32位宽,按字地址对齐
(1)R-type
指令字段的含义:
- OP:操作码
- rs:第一个源操作数寄存器
- rt:第二个源操作数寄存器
- rd:结果寄存器
- shamt:移位指令的位移量
- func:功能码。操作码相同时,由功能码定义不同的含义。R-type指令的OP字段是固定的000000,具体操作由func字段给出,例如加法操作的func字段是100000。
举例:sub rd,rs,rt
寻址方式:寄存器(rs)寻址
(2)I-type
举例:
- 运算指令,如ori rt,rs,imm16
- LOAD和SRORE指令,如lw rt,rs,imm16
- 分支指令,如beq rs,rt,imm16
寻址方式:
- 立即寻址
- 基址或变址
- 相对寻址 (PC)+4+immediate<<2
(3)J-type
无条件跳转指令,如j target
寻址方式:伪直接寻址
target address是无条件转移地址的低26位,PC高4位拼上26位直接地址,后面添2个0就是目标地址。(存储单元按字节编址,指令按字对齐,每个字至少有4个或8个字节,所以指令的地址一定是4的倍数)
5.3x86指令集
待补充
6.RISC技术
RISC | CISC |
选用频度较高的一些简单指令,复杂指令的功能由简单指令组合实现
| 系统指令复杂庞大,各种指令使用频度相差大 |
指令长度固定,指令格式种类少,寻址方式少 | 指令长度不固定,指令格式种类多,寻址方式多 |
只有LOAD/STORE指令访存 | 指令格式不受限制 |
CPU中有多个通用寄存器 | CPU中设有专用寄存器 |
采用流水技术,一个时钟周期内完成一条指令 | 大多数指令需要多个时钟周期执行完毕 |
采用组合逻辑实现控制器 | 采用微程序控制器 |
采用优化的编译程序 | 难以用优化编译生成高效的代码 |
不易实现指令系统兼容 | 易于实现指令系统兼容 |