一、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种指令格式
1、Regesiter型(又称为R-格式,3寄存器)
实例:add $s0, $s1, $s2
查上面的表(寄存器对应的编号)可知对应寄存器的字段值(此时为10进制)。add不涉及移位,故shamt为0.
在 MIPS 指令集中,R-格式的指令的操作码op字段都是固定的,值为0
有关R-格式的函数操作码(funct)对照表如下:
add对应的funct为32,因此有:
转换成二进制如下:
再转换成16进制即可得到相应的机器指令 :0x02328020
2、Immediate型(又称为I-格式,2寄存器+16位立即数)
实例:addi $s0, $s1, -4
有关I-格式的op参照表如下
查表可知op为001000,即可写:
转换成二进制表示为:
转换成16进制即可得到机器指令为:0x2232FFFC
3、Jump型(又称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汇编代码