MIPS常见指令集精简介绍
MIPS常见指令集精简介绍
MIPS(Microprocessor without Interlocked Pipeline Stages)是一种精简指令集计算机(RISC)架构,广泛应用于嵌入式系统和高性能计算领域。本文将详细介绍MIPS指令集的基础知识,包括寄存器、存储器的介绍,常见指令的使用方法,以及三种指令格式(R型、I型、J型)的详细解析。通过具体的实例代码,帮助读者理解MIPS指令集的工作原理和应用场景。
一、MIPS寄存器、存储器介绍
在 MIPS 指令集中,没有像 x86 架构中的 64 位(例如%rax)和 32 位(例如%eax)寄存器之分。MIPS 指令集的寄存器都是 32 位的,每个寄存器可以存储一个 32 位的值,且在MIPS指令架构中,一条指令长度为4字节。
二、常见MIPS指令
add $t0, $t1, $t2
解释:将寄存器 $t1 和 $t2 中的值相加,结果存储在寄存器 $t0 中。sub $t0, $t1, $t2
解释:将寄存器 $t1 中的值减去 $t2 中的值,结果存储在寄存器 $t0 中。lw $t0, 4($t1)
解释:从内存地址 $t1 + 4 处加载一个字(32位数据),并将其存储在寄存器 $t0 中。li $t0, 42
解释:将常数42加载到寄存器$t0中sw $t0, 8($t1)
解释:将寄存器 $t0 中的值存储到内存地址 $t1 + 8 处。beq $t0, $t1, label
解释:如果寄存器 $t0 和 $t1 中的值相等,则跳转到 label 处执行。bne $s0, $s1, label
解释:如果 $s0 和 $s1 不相等,则跳转到标签 label 处执行。j label
解释:无条件跳转到标签 label 处执行。jr $ra
解释:无条件跳转到寄存器$ra中保存的地址处。sll $t0, $s0, 2
解释:将寄存器 $s0 中的值左移两位,并将结果存储到寄存器 $t0 中。srl $t0, $s0, 3
解释:将寄存器 $s0 中的值右移三位,并将结果存储到寄存器 $t0 中。andi $t0, $s0, 0xFF
解释:将寄存器 $s0 中的值与立即数 0xFF 进行逻辑与操作,并将结果存储到寄存器 $t0 中。ori $t0, $s0, 0xFF
解释:将寄存器 $s0 中的值与立即数 0xFF 进行逻辑或操作,并将结果存储到寄存器 $t0 中。slt $t0, $t1, $t2
解释:如果寄存器 $t1 中的值小于 $t2 中的值,则将寄存器 $t0 设置为1;否则设置为0。(sltu用来表示无符号数unsigned)mul $t0, $t1, $t2
解释:将寄存器 $t1 和 $t2 中的值相乘,结果的低32位存储在寄存器 $t0 中。
三、MIPS3种指令格式
Regesiter型(又称为R-格式,3寄存器)
实例:add $s0, $s1, $s2
查上面的表(寄存器对应的编号)可知对应寄存器的字段值(此时为10进制)。add不涉及移位,故shamt为0.
在 MIPS 指令集中,R-格式的指令的操作码op字段都是固定的,值为0
有关R-格式的函数操作码(funct)对照表如下:
add对应的funct为32,因此有:
转换成二进制如下:
再转换成16进制即可得到相应的机器指令 :0x02328020Immediate型(又称为I-格式,2寄存器+16位立即数)
实例:addi $s0, $s1, -4
有关I-格式的op参照表如下
查表可知op为001000,即可写:
转换成二进制表示为:
转换成16进制即可得到机器指令为:0x2232FFFCJump型(又称J格式,26位立即数)
j loop
J-格式的op固定为000010,后面26位是标签loop所在的地址
特例:jr $s1
解释:跳转到寄存器$s1所存储的地址位置,这就属于R格式了,op为0。jal target
解释:跳转到目标地址target处,同时将当前指令的地址(PC+4)保存到$ra寄存器中,也就是说,在目标地址执行完后,程序可以通过跳转回$ra 中保存的地址来继续执行原来的代码,例如:jal foo
将控制转移到 foo 标签所在的地址,并将下一条指令的地址保存到 $ra 寄存器中($ra寄存器的一般用途就是用来存储函数返回地址,可参考上面的表格)。在 foo 函数执行完毕后,使用jr $ra
指令将控制返回到函数调用点的下一条指令.jal
的op是000011,后面26位是target表示的目标地址。
四、实例解析
示例一:一个求数组所有元素和的简单函数
.data # 数据段
array: .word 1, 2, 3 # 定义一个包含三个元素的数组
sum: .word 0 # 定义一个用于存储和的变量
.text # 代码段
main:
li $t0, 0 # 初始化求和为0
lw $t1, 0(array) # 读取数组第一个元素
lw $t2, 4(array) # 读取数组第二个元素
lw $t3, 8(array) # 读取数组第三个元素
add $t0, $t0, $t1 # 累加第一个元素
add $t0, $t0, $t2 # 累加第二个元素
add $t0, $t0, $t3 # 累加第三个元素
sw $t0, 0(sum) # 将和存储到sum变量
jr $ra # 返回调用者
示例二:C代码转换成MIPS汇编代码
(此处省略,具体实现可参考原文)