目录
一、MIPS指令分类
二、常用指令详解
三、常用MIPS指令集及格式:
四、CPU内部的32个寄存器:
一、MIPS指令分类
MIPS(Microprocessor without Interlocked Pipeline Stages)指令集是一种广泛用于教学和嵌入式系统的指令集体系结构。MIPS指令可以分为以下几类:
-
算术指令(Arithmetic Instructions):这些指令执行算术运算,如加法、减法、乘法和除法。例如,ADD(加法)、SUB(减法)、MUL(乘法)和DIV(除法)等。
-
逻辑指令(Logical Instructions):这些指令执行逻辑运算,如逻辑与、逻辑或、逻辑非和位运算等。例如,AND(逻辑与)、OR(逻辑或)、NOT(逻辑非)和XOR(异或)等。
-
数据传输指令(Data Transfer Instructions):这些指令用于数据的加载和存储,包括从内存到寄存器的加载和从寄存器到内存的存储。例如,LW(加载字)、SW(存储字)等。
-
分支指令(Branch Instructions):这些指令用于控制程序的流程,包括条件分支和无条件分支。例如,BEQ(分支相等)、BNE(分支不相等)、J(跳转)等。
-
跳转指令(Jump Instructions):这些指令用于无条件改变程序的执行位置。例如,J(跳转)、JR(寄存器跳转)等。
-
访存指令(Memory Access Instructions):这些指令用于直接访问内存,而不是通过寄存器。例如,LBU(加载字节无符号)、SB(存储字节)等。
-
特权指令(Privileged Instructions):这些指令只能在特权模式下执行,用于操作系统和硬件管理。例如,SYSCALL(系统调用)、HALT(停止)等。
-
浮点指令(Floating-Point Instructions):这些指令用于执行浮点运算,如浮点加法、浮点乘法等。例如,ADD.S(单精度浮点加法)、MUL.D(双精度浮点乘法)等。
这些是MIPS指令集的主要类别,每个类别下又有许多具体的指令。
二、汇编编程
2.1 示例
MIPS汇编编程涉及使用MIPS汇编语言编写程序,该程序会在MIPS体系结构的计算机上执行。以下是一些关键的概念和示例,帮助你入门MIPS汇编编程:
1. 寄存器:
MIPS体系结构有32个通用寄存器,每个寄存器都用符号表示。例如,符号表示。例如,t0表示临时寄存器0,$s1表示保存寄存器1。
# 示例:将值存储到寄存器 LI $t0, 10 # 将立即数10加载到$t0
2. 内存访问:
MIPS使用Load(LW)和Store(SW)指令来读取和写入内存。
# 示例:从内存读取数据 LW $t1, 0($t0) # 从地址($t0 + 0)读取数据到$t1 # 示例:将数据写入内存 SW $s0, 4($t2) # 将$s0的值写入地址($t2 + 4)
3. 分支和跳转:
MIPS提供条件分支和无条件跳转指令,例如BEQ(Branch if Equal)和J(Jump)。
# 示例:条件分支 BEQ $s0, $t0, label_equal # 如果$s0和$t0相等,则跳转到label_equal # 示例:无条件跳转 J label_jump # 无条件跳转到label_jump
4. 过程调用:
过程调用涉及将参数传递给函数、调用函数以及从函数中返回。在MIPS中,参数通常通过寄存器传递。
# 示例:过程调用 LI $a0, 5 # 将参数5传递给函数 JAL my_function # 调用函数my_function,JAL会保存返回地址到$ra寄存器
5. 伪指令:
前面已经提到了一些常见的MIPS伪指令,它们在汇编阶段被转换为真实的MIPS指令。
# 示例:使用伪指令 NOP # 无操作 MOVE $t0, $s0 # 移动寄存器值 CLEAR $t1 # 清零寄存器值
6. 示例程序:
下面是一个简单的MIPS程序,演示了寄存器、内存访问、分支和过程调用:
.data message: .asciiz "Hello, MIPS!\n" .text main: # 输出字符串 LI $v0, 4 # 调用系统服务4,用于打印字符串 LA $a0, message # 将字符串地址传递给参数 SYSCALL # 执行系统调用 # 退出程序 LI $v0, 10 # 调用系统服务10,用于退出程序 SYSCALL # 示例函数 my_function: # 函数体... JR $ra # 返回,使用$ra中保存的返回地址
以上是一个简单的示例,涵盖了一些基本的MIPS汇编编程概念。在实际编程中,你可能会遇到更复杂的任务,但这个起点可以帮助你理解和掌握MIPS汇编语言。
2.2 函数定义
MIPS汇编中的函数定义通常遵循一定的约定和结构。下面是一个简单的MIPS函数定义示例:
# 函数声明
my_function:
# 函数体
# 返回
JR $ra # 返回,使用$ra中保存的返回地址
让我们来解释一下:
-
函数声明:在MIPS汇编中,函数声明由标签表示,例如
my_function:
。函数的开始由该标签标识。 -
函数体:在函数的标签之后,是函数的实际代码内容,包括各种指令、操作和逻辑。
-
返回指令:在函数体的结尾通常会有一个返回指令,用于将控制流返回到调用函数的地方。在MIPS中,使用
JR $ra
指令来实现返回操作,这里的$ra
寄存器保存了函数调用前的返回地址。
在实际编程中,函数可能会有参数传递、局部变量分配和其他复杂的逻辑。参数通常通过寄存器传递,而局部变量通常被存储在堆栈上。这些方面会在更复杂的函数中涉及到,但基本的函数结构如上所示。
2.3 段定义
在MIPS汇编中,段(section)通常用来定义不同类型的数据和代码。常见的段包括.data
段和.text
段。
- .data 段:
.data
段用于定义静态数据。在这个段中,你可以声明和初始化全局变量、字符串、数组等。这些数据在程序执行过程中通常是不变的。
.data
message: .asciiz "Hello, MIPS!\n"
array: .word 1, 2, 3, 4, 5
- .text 段:
.text
段用于存放程序的指令部分,也就是代码段。在这个段中,你可以定义函数、指令序列等。程序执行时,控制流会从.text
段开始执行指令。
.text
main:
# 函数主体
# 调用其他函数
这些段的划分有助于组织和管理程序的不同部分,使得程序的结构更加清晰明了。在实际编程中,你会在这些段中定义和实现程序的各种功能和逻辑。
2.4 伪指令
在MIPS汇编中,伪指令(pseudo-instruction)是一种不是真正的机器指令,而是由汇编器处理并转换为一系列真正的机器指令的指令。它们提供了一些方便的功能和语法糖,使得编写和理解汇编代码更加简单。以下是一些常见的MIPS伪指令:
-
.data:定义数据段,用于声明和初始化全局变量、字符串等静态数据。
.data message: .asciiz "Hello, MIPS!\n" array: .word 1, 2, 3, 4, 5
-
.text:定义代码段,用于存放程序的指令。
.text main: # 程序指令
-
.word:用于在数据段中声明一个或多个字(32位数据)。
.data my_var: .word 42
-
.asciiz:在数据段中声明一个以空字符结尾的字符串。
.data my_string: .asciiz "MIPS Assembly"
-
.space:在数据段中为变量分配指定字节数的空间。
.data buffer: .space 100
-
.text:定义代码段,用于存放程序的指令。
.text main: # 程序指令
-
.globl或**.global**:声明一个全局符号,通常用于声明函数名或全局变量。
.globl my_function
-
.align:对齐指令,用于确保后续数据或指令在内存中按指定的边界对齐。
.align 4
-
.set:设置伪指令,用于设置汇编器选项。
.set noat # 禁用 $at 寄存器
-
.end:标记程序的结束,有些汇编器可能需要此指令。
.end
11. .type:
在MIPS汇编中,.type
伪指令用于为一个符号(symbol)指定类型信息。这对于链接器(linker)在链接过程中正确处理符号非常重要。一般情况下,.type
伪指令的语法为:
.type symbol, type
其中,symbol
是要指定类型信息的符号的名称,而type
是该符号的类型。符号的类型通常可以是函数、对象或其他类型之一。
举例来说,如果有一个名为my_function
的函数,你可以使用.type
指令为它指定类型信息,如下:
.type my_function, @function
这告诉链接器,my_function
是一个函数。类似地,如果有一个全局变量my_variable
,你可以使用以下指令:
.type my_variable, @object
这告诉链接器,my_variable
是一个对象(全局变量)。
在实际应用中,.type
伪指令通常与其他指令一起使用,以确保在链接时符号的类型得到正确识别和处理。这对于生成可执行文件或共享库时至关重要,因为链接器需要知道符号的类型以正确地连接不同的模块。
这些伪指令有助于提高汇编代码的可读性和编写效率,同时使代码更加模块化和易于维护。
三、常用指令详解
1、空操作:nop:相当于 sll zero,zero,o,
ssnop: equals sll zero,zero,1.
这个指令不得与其它指令同时发送,这样就保证了其运行要花费至少一个时钟周期。这在简单的流水线的CPU上无关紧要,但在复杂些的实现上对于实现强制的延时很有用。
空操作指令在MIPS指令集中被称为NOP(No Operation),它是一种不执行任何操作的指令。在汇编语言中,NOP通常用于填充空闲位置或者在调试时插入延迟。
在MIPS汇编中,NOP指令的操作码通常是全0的二进制序列。在某些情况下,NOP指令可能会有特定的功能,比如在乱序执行的CPU中,NOP可能会有让处理器等待的作用,以确保指令执行的正确顺序。
示例:
NOP
这条指令执行时,处理器不执行任何操作,只是简单地将控制传递到下一条指令。
2、寄存器/寄存器传送:
move: 通常用跟$zero寄存器的or来实现,或者用addu。
movf, movt, movn, movz: 条件传送。
寄存器-寄存器传送指令是MIPS指令集中的一类指令,用于在寄存器之间传送数据。这些指令通常用于数据移动、数据加载和存储等操作。以下是几种常见的寄存器-寄存器传送指令:
-
MOVE(Move):MOVE指令用于将一个寄存器的值复制到另一个寄存器中,没有任何运算或变换。例如:
MOVE $t0, $s0
这条指令将寄存器�0的值复制到寄存器s0的值复制到寄存器t0中。
-
MFHI(Move From HI):MFHI指令用于将HI寄存器的值复制到一个通用寄存器中。HI寄存器用于保存乘法或除法指令的高位结果。例如:
MFHI $t1
这条指令将HI寄存器的值复制到寄存器$t1中。
-
MFLO(Move From LO):MFLO指令用于将LO寄存器的值复制到一个通用寄存器中。LO寄存器用于保存乘法或除法指令的低位结果。例如:
MFLO $t2
这条指令将LO寄存器的值复制到寄存器$t2中。
-
MTHI(Move To HI):MTHI指令用于将一个通用寄存器的值复制到HI寄存器中。例如:
MTHI $s1
这条指令将寄存器$s1的值复制到HI寄存器中。
-
MTLO(Move To LO):MTLO指令用于将一个通用寄存器的值复制到LO寄存器中。例如:
MTLO $s2
这条指令将寄存器$s2的值复制到LO寄存器中。
这些寄存器-寄存器传送指令在MIPS汇编中被广泛使用,用于数据传送和操作。
3、常数加载:
dla、la: 用来加载程序中某些带标号的位置或者变量的地址的宏指令;
dli、li: 装入立即数常数,这是一个宏指令;
lui: 把立即数加载到寄存器高位。
常数加载指令是MIPS指令集中的一类指令,用于将常数值加载到寄存器中。在程序中,常数值经常用于进行算术运算、逻辑运算或者作为地址偏移量。以下是几种常见的常数加载指令:
LI(Load Immediate):LI指令用于将一个立即数(常数)加载到寄存器中。例如:
LI $t3, 42
这条指令将值42加载到寄存器$t3中。
LUI(Load Upper Immediate):LUI指令用于将一个16位的立即数左移16位,并将结果加载到目标寄存器的高位。通常与其他指令组合使用,用于加载32位常数。例如:
LUI $t4, 0x1234
这条指令将16位的常数0x1234左移16位,并加载到寄存器$t4的高位,低位为0。
ORI(OR Immediate):ORI指令用于将寄存器中的值与一个16位的立即数进行按位或运算,并将结果存放回寄存器。例如:
ORI $t5, $t5, 0xFF
这条指令将寄存器�5中的值与0���进行按位或运算,并将结果存放回t5中的值与0xFF进行按位或运算,并将结果存放回t5。
这些常数加载指令在MIPS汇编中允许程序员有效地将常数值加载到寄存器中,以便后续的运算或存储。
4、算术/逻辑运算:
add、addi、dadd、daddi、addu、addiu、daddu、daddiu、dsub、sub、subu:加法指令和减法指令;
abs,dabs:绝对值;
dneg、neg、negu:取相反数;
and、andi、or、ori、xor、nor:逐位逻辑操作指令;
drol、rol、ror:循环移位指令;
sll、srl、sra:移位。
算术和逻辑运算是计算机程序中常见的操作,MIPS指令集提供了一系列指令来执行这些操作。以下是几种常见的算术和逻辑运算指令:
ADD(Addition):ADD指令用于将两个寄存器中的值相加,并将结果存放到目标寄存器中。例如:
ADD $t0, $s0, $s1
这条指令将寄存器�0和s0和s1中的值相加,并将结果存放到寄存器$t0中。
SUB(Subtraction):SUB指令用于将一个寄存器中的值减去另一个寄存器中的值,并将结果存放到目标寄存器中。例如:
SUB $t1, $s2, $s3
这条指令将寄存器�2中的值减去s2中的值减去s3中的值,并将结果存放到寄存器$t1中。
AND(Logical AND):AND指令用于将两个寄存器中的值进行按位与操作,并将结果存放到目标寄存器中。例如:
AND $t2, $s4, $s5
这条指令将寄存器�4和s4和s5中的值进行按位与操作,并将结果存放到寄存器$t2中。
OR(Logical OR):OR指令用于将两个寄存器中的值进行按位或操作,并将结果存放到目标寄存器中。例如:
OR $t3, $s6, $s7
这条指令将寄存器�6和s6和s7中的值进行按位或操作,并将结果存放到寄存器$t3中。
XOR(Exclusive OR):XOR指令用于将两个寄存器中的值进行按位异或操作,并将结果存放到目标寄存器中。例如:
XOR $t4, $s8, $s9
这条指令将寄存器�8和s8和s9中的值进行按位异或操作,并将结果存放到寄存器$t4中。
这些算术和逻辑运算指令在MIPS汇编中允许程序员对数据进行各种操作,从而实现复杂的计算和逻辑控制。
5、条件设置指令:
slt、slti、sltiu、sltu、seq、sge、sle、sne:条件设置。
条件设置指令是MIPS指令集中的一类指令,用于在执行比较操作后设置条件码(例如零、正数、负数等),以便后续的条件分支或其他操作。以下是几种常见的条件设置指令:
SLT(Set on Less Than):SLT指令用于比较两个寄存器中的值,如果第一个寄存器中的值小于第二个寄存器中的值,则将目标寄存器设置为1;否则设置为0。例如:
SLT $t0, $s0, $s1
这条指令比较寄存器�0和s0和s1中的值,如果�0的值小于s0的值小于s1的值,则将$t0设置为1,否则设置为0。
SLTI(Set on Less Than Immediate):SLTI指令用于将一个寄存器中的值与一个立即数进行比较,如果寄存器中的值小于立即数,则将目标寄存器设置为1;否则设置为0。例如:
SLTI $t1, $s2, 10
这条指令比较寄存器�2中的值和立即数10,如果s2中的值和立即数10,如果s2的值小于10,则将$t1设置为1,否则设置为0。
SLTU(Set on Less Than Unsigned):SLTU指令用于比较两个无符号整数寄存器中的值,如果第一个寄存器中的值小于第二个寄存器中的值,则将目标寄存器设置为1;否则设置为0。例如:
SLTU $t2, $s3, $s4
这条指令比较寄存器�3和s3和s4中的无符号整数值,如果�3的值小于s3的值小于s4的值,则将$t2设置为1,否则设置为0。
SLTIU(Set on Less Than Immediate Unsigned):SLTIU指令用于将一个无符号整数寄存器中的值与一个立即数进行比较,如果寄存器中的值小于立即数,则将目标寄存器设置为1;否则设置为0。例如:
SLTIU $t3, $s5, 20
这条指令比较寄存器�5中的无符号整数值和立即数20,如果s5中的无符号整数值和立即数20,如果s5的值小于20,则将$t3设置为1,否则设置为0。
这些条件设置指令在MIPS汇编中常用于执行比较并根据比较结果设置条件码,以便进行条件分支或其他操作。
6、整数乘法、除法和求余数:
div、mul、rem等等。
整数乘法、除法和求余数是在计算机程序中常见的操作,MIPS指令集提供了一些指令来执行这些操作。以下是几种常见的整数乘法、除法和求余数的指令:
MULT(Multiply)和 MFHI/MFLO(Move From High/Low):MULT指令用于将两个寄存器中的有符号整数值相乘,并将结果存放在一对特殊寄存器中,即HI(高位)和LO(低位)。之后,可以使用MFHI和MFLO指令将相乘的结果的高位和低位移动到其他寄存器中。例如:
MULT $s0, $s1 # 将$s0和$s1中的值相乘 MFLO $t0 # 将乘积的低位存放到$t0中 MFHI $t1 # 将乘积的高位存放到$t1中
DIV(Divide)和 MFHI/MFLO:DIV指令用于将一个寄存器中的有符号整数值除以另一个寄存器中的值,并将商和余数存放在HI和LO寄存器中。之后,可以使用MFHI和MFLO指令将商和余数移动到其他寄存器中。例如:
DIV $s2, $s3 # 将$s2中的值除以$s3中的值 MFLO $t2 # 将商存放到$t2中 MFHI $t3 # 将余数存放到$t3中
MUL(Multiply Unsigned)和 MULU(Multiply Unsigned):MUL指令用于将两个寄存器中的无符号整数值相乘,结果存放在目标寄存器中。MULU执行类似的操作,但是用于无符号整数。例如:
MUL $t4, $t5, $t6 # 将$t5和$t6中的值相乘,结果存放到$t4中
DIVU(Divide Unsigned):DIVU指令用于将一个无符号整数寄存器中的值除以另一个无符号整数寄存器中的值,并将商存放在LO寄存器中,余数存放在HI寄存器中。例如:
DIVU $t7, $t8 # 将$t7中的值除以$t8中的值 MFLO $t9 # 将商存放到$t9中 MFHI $s4 # 将余数存放到$s4中
这些指令允许程序员在MIPS汇编中执行整数乘法、除法和求余数的操作,适用于有符号和无符号整数。
7、整数乘加(累加):
mad等。
整数乘加,也称为整数乘累加或累积乘法加法操作,是一种常见的操作,通常用于计算多个整数的乘积并将其与一个累加器相加。在MIPS指令集中,可以使用MADD(Multiply-Add)和MADDU(Multiply-Add Unsigned)指令执行整数乘加操作。
MADD(Multiply-Add):MADD指令用于将两个寄存器中的有符号整数值相乘,然后将结果与第三个寄存器中的值相加,并将最终结果存储在累加器寄存器(通常是HI和LO寄存器)中。例如:
MADD $s0, $s1, $s2 # 将$s1和$s2中的值相乘,然后与$s0中的值相加,结果存放在HI和LO寄存器中
MADDU(Multiply-Add Unsigned):MADDU指令类似于MADD,但用于无符号整数的乘加操作。它将两个无符号整数寄存器中的值相乘,然后将结果与第三个寄存器中的值相加,并将最终结果存储在累加器寄存器中。例如:
MADDU $t0, $t1, $t2 # 将$t1和$t2中的无符号整数值相乘,然后与$t0中的值相加,结果存放在HI和LO寄存器中
在执行这些指令后,可以使用MFHI和MFLO指令将累加器中的结果移动到其他寄存器中,以供后续使用。
整数乘加操作在许多计算任务中非常有用,特别是在信号处理和图形处理等应用中。这种操作允许高效地执行一系列的整数乘法和加法操作,减少了指令的数量和执行时间。
8、加载和存储:
lb、ld、ldl、ldr、sdl、sdr、lh、lhu、ll、sc、pref、sb等操作。
加载和存储指令在计算机程序中用于将数据从内存加载到寄存器中或将数据从寄存器存储到内存中。MIPS指令集提供了一系列加载和存储指令,包括以下几种:
LW(Load Word):LW指令用于从内存中加载一个字(32位数据)到寄存器中。例如:
LW $t0, offset($s1) # 将地址为$s1 + offset处的字加载到$t0中
SW(Store Word):SW指令用于将一个字(32位数据)从寄存器存储到内存中。例如:
SW $t0, offset($s1) # 将$t0中的值存储到地址为$s1 + offset处
LB(Load Byte):LB指令用于从内存中加载一个字节(8位数据)到寄存器中。加载的字节会进行符号扩展,即最高位(MSB)被复制到寄存器的其他位上。例如:
LB $t0, offset($s1) # 将地址为$s1 + offset处的字节加载到$t0中
SB(Store Byte):SB指令用于将一个字节(8位数据)从寄存器存储到内存中。例如:
SB $t0, offset($s1) # 将$t0中的最低字节存储到地址为$s1 + offset处
这些加载和存储指令允许程序员在MIPS汇编中有效地进行数据的读取和存储操作,从而支持程序的正常执行。
网络搜索
9、浮点加载和存储:
l.d、l.s、s.d、s.s等
浮点加载和存储指令在MIPS指令集中用于处理浮点数数据的加载和存储操作。MIPS架构支持单精度浮点数(32位)和双精度浮点数(64位)。以下是常见的浮点加载和存储指令:
LWC1(Load Word to Coprocessor 1):LWC1指令用于将一个32位的单精度浮点数从内存加载到浮点寄存器(协处理器1)中。例如:
LWC1 $f0, offset($s1) # 将地址为$s1 + offset处的单精度浮点数加载到$f0中
SWC1(Store Word from Coprocessor 1):SWC1指令用于将一个32位的单精度浮点数从浮点寄存器(协处理器1)存储到内存中。例如:
SWC1 $f0, offset($s1) # 将$f0中的单精度浮点数存储到地址为$s1 + offset处
LDC1(Load Double to Coprocessor 1):LDC1指令用于将一个64位的双精度浮点数从内存加载到浮点寄存器对中(协处理器1)。因为双精度浮点数占用两个寄存器,所以加载到对中。例如:
LDC1 $f0, offset($s1) # 将地址为$s1 + offset处的双精度浮点数加载到$f0和$f1对中
SDC1(Store Double from Coprocessor 1):SDC1指令用于将一个64位的双精度浮点数从浮点寄存器对中(协处理器1)存储到内存中。例如:
SDC1 $f0, offset($s1) # 将$f0和$f1对中的双精度浮点数存储到地址为$s1 + offset处
这些浮点加载和存储指令允许程序员在MIPS汇编中有效地进行浮点数数据的读取和存储操作,从而支持程序的正常执行。
网络搜索
四、常用MIPS指令集及格式:
MIPS 指令集(共31条) | |||||||||
助记符 | 指令格式 | 示例 | 示例含义 | 操作及其解释 | |||||
Bit # | 31..26 | 25..21 | 20..16 | 15..11 | 10..6 | 5..0 | |||
R-type | op | rs | rt | rd | shamt | func | |||
add | 000000 | rs | rt | rd | 00000 | 100000 | add $1,$2,$3 | $1=$2+$3 | rd <- rs + rt ;其中rs=$2,rt=$3, rd=$1 |
addu | 000000 | rs | rt | rd | 00000 | 100001 | addu $1,$2,$3 | $1=$2+$3 | rd <- rs + rt ;其中rs=$2,rt=$3, rd=$1,无符号数 |
sub | 000000 | rs | rt | rd | 00000 | 100010 | sub $1,$2,$3 | $1=$2-$3 | rd <- rs - rt ;其中rs=$2,rt=$3, rd=$1 |
subu | 000000 | rs | rt | rd | 00000 | 100011 | subu $1,$2,$3 | $1=$2-$3 | rd <- rs - rt ;其中rs=$2,rt=$3, rd=$1,无符号数 |
and | 000000 | rs | rt | rd | 00000 | 100100 | and $1,$2,$3 | $1=$2 & $3 | rd <- rs & rt ;其中rs=$2,rt=$3, rd=$1 |
or | 000000 | rs | rt | rd | 00000 | 100101 | or $1,$2,$3 | $1=$2 | $3 | rd <- rs | rt ;其中rs=$2,rt=$3, rd=$1 |
xor | 000000 | rs | rt | rd | 00000 | 100110 | xor $1,$2,$3 | $1=$2 ^ $3 | rd <- rs xor rt ;其中rs=$2,rt=$3, rd=$1(异或) |
nor | 000000 | rs | rt | rd | 00000 | 100111 | nor $1,$2,$3 | $1=~($2 | $3) | rd <- not(rs | rt) ;其中rs=$2,rt=$3, rd=$1(或非) |
slt | 000000 | rs | rt | rd | 00000 | 101010 | slt $1,$2,$3 | if($2<$3) | if (rs < rt) rd=1 else rd=0 ;其中rs=$2,rt=$3, rd=$1 |
sltu | 000000 | rs | rt | rd | 00000 | 101011 | sltu $1,$2,$3 | if($2<$3) | if (rs < rt) rd=1 else rd=0 ;其中rs=$2,rt=$3, rd=$1 |
sll | 000000 | 00000 | rt | rd | shamt | 000000 | sll $1,$2,10 | $1=$2<<10 | rd <- rt << shamt ;shamt存放移位的位数, |
srl | 000000 | 00000 | rt | rd | shamt | 000010 | srl $1,$2,10 | $1=$2>>10 | rd <- rt >> shamt ;(logical) ,其中rt=$2, rd=$1 |
sra | 000000 | 00000 | rt | rd | shamt | 000011 | sra $1,$2,10 | $1=$2>>10 | rd <- rt >> shamt ;(arithmetic) 注意符号位保留 |
sllv | 000000 | rs | rt | rd | 00000 | 000100 | sllv $1,$2,$3 | $1=$2<<$3 | rd <- rt << rs ;其中rs=$3,rt=$2, rd=$1 |
srlv | 000000 | rs | rt | rd | 00000 | 000110 | srlv $1,$2,$3 | $1=$2>>$3 | rd <- rt >> rs ;(logical)其中rs=$3,rt=$2, rd=$1 |
srav | 000000 | rs | rt | rd | 00000 | 000111 | srav $1,$2,$3 | $1=$2>>$3 | rd <- rt >> rs ;(arithmetic) 注意符号位保留 |
jr | 000000 | rs | 00000 | 00000 | 00000 | 001000 | jr $31 #寄存器跳转 | goto $31 | PC <- rs |
I-type | op | rs | rt | immediate | |||||
addi | 001000 | rs | rt | immediate | addi $1,$2,100 | $1=$2+100 | rt <- rs + (sign-extend)immediate ;其中rt=$1,rs=$2 | ||
addiu | 001001 | rs | rt | immediate | addiu $1,$2,100 | $1=$2+100 | rt <- rs + (zero-extend)immediate ;其中rt=$1,rs=$2 | ||
andi | 001100 | rs | rt | immediate | andi $1,$2,10 | $1=$2 & 10 | rt <- rs & (zero-extend)immediate ;其中rt=$1,rs=$2 | ||
ori | 001101 | rs | rt | immediate | andi $1,$2,10 | $1=$2 | 10 | rt <- rs | (zero-extend)immediate ;其中rt=$1,rs=$2 | ||
xori | 001110 | rs | rt | immediate | andi $1,$2,10 | $1=$2 ^ 10 | rt <- rs xor (zero-extend)immediate ;其中rt=$1,rs=$2 | ||
lui | 001111 | 00000 | rt | immediate | lui $1,100 | $1=100*65536 | rt <- immediate*65536 ;将16位立即数放到目标寄存器高16 | ||
lw | 100011 | rs | rt | immediate | lw $1,10($2) | $1=memory[$2 | rt <- memory[rs + (sign-extend)immediate] ;rt=$1,rs=$2 | ||
sw | 101011 | rs | rt | immediate | sw $1,10($2) | memory[$2+10] | memory[rs + (sign-extend)immediate] <- rt ;rt=$1,rs=$2 | ||
beq | 000100 | rs | rt | immediate | beq $1,$2,10 | if($1==$2) | if (rs == rt) PC <- PC+4 + (sign-extend)immediate<<2 | ||
bne | 000101 | rs | rt | immediate | bne $1,$2,10 | if($1!=$2) | if (rs != rt) PC <- PC+4 + (sign-extend)immediate<<2 | ||
slti | 001010 | rs | rt | immediate | slti $1,$2,10 | if($2<10) | if (rs <(sign-extend)immediate) rt=1 else rt=0 ; | ||
sltiu | 001011 | rs | rt | immediate | sltiu $1,$2,10 | if($2<10) | if (rs <(zero-extend)immediate) rt=1 else rt=0 ; | ||
J-type | op | address | |||||||
j | 000010 | address | j 10000 | goto 10000 | PC <- (PC+4)[31..28],address,0,0 ;address=10000/4 | ||||
jal | 000011 | address | jal 10000 #目标地址长跳转 | $31<-PC+4; | $31<-PC+4;PC <- (PC+4)[31..28],address,0,0 |
五、CPU内部的32个寄存器:
寄存器号 符号名 用途
- 0 始终为0 看起来象浪费,其实很有用
- 1 at 保留给汇编器使用
- 2-3 v0,v1 函数返回值
- 4-7 a0-a3 前头几个函数参数
- 8-15 t0-t7 临时寄存器,子过程可以不保存就使用
- 24-25 t8,t9 同上
- 16-23 s0-s7 寄存器变量,子过程要使用它必须先保存
- 然后在退出前恢复以保留调用者需要的值
- 26,27 k0,k1 保留给异常处理函数使用
- 28 gp global pointer;用于方便存取全局或者静态变量
- 29 sp stack pointer
- 30 s8/fp 第9个寄存器变量;子过程可以用它做frame pointer
- 31 ra 返回地址
硬件上这些寄存器并没有区别(除了0号),区分的目的是为了不同的编译器产生的代码可以通用