MIPS指令字典

MIPS指令字典

0. 寄存器约定表

名称 序号 用法
zero 0 存放常数0
at 1 汇编器保留
v0 – v1 2 3 函数调用时作为出口参数
a0 – a3 4 7 入口参数
t0 – t7 8 15 存放临时变量
s0 – s7 16 23 保留寄存器
t8 – t9 24 25 更多的临时寄存器
k0 – k1 26 27 内核保留
gp 28 全局指针
sp 29 堆栈指针
fp 30 帧指针
ra 31 存放返回地址

1. 运算类指令

1.1 add 加法

例:

1
add $s1, $s2, $s3

将s2和s3寄存器内的值之和放入s1

tips:由于 $0寄存器的值始终为 0,add $s1,$s2,$0等效于C语言中 s1=s2

1.2 sub 减法

例:

1
sub $s1, $s2, $s3

将s2和s3寄存器内的值之差放入s1

1.3 addi,subi 与立即数的加法/减法

例:

1
2
addi $s1,$s2,100
subu $1,$2,100

将立即数与s2寄存器内值运算并放入s1寄存器中

指令后带 i 一般表示与立即数操作,后续还会遇到

1.4 addu,subu 无符号加法/减法

指令后带u一般表示无符号操作,后续还会遇到

1.5 addiu,subiu 与立即数的无符号加法/减法

2. 数据传输指令

2.1 lw 加载字

例:

1
lw $s0,12($s3)		#	$t0 = A[3]

从储存器地址+偏移(4的倍数)位置提取一个字的数据,放入寄存器

2.2 sw 存放字

例:

1
sw $t0,40($s3) 	 # 	A[10]=A[3]+a

从寄存器中提取一个字的数据,放入储存器地址+偏移(4的倍数)位置

2.3 lb sb 加载/存放字节

例:

1
2
3
#*($s0) = 0x00000180	#$s0中存放的储存器地址处的那个字,存放数据为0x00000180
lb $s1,1($s0) # $s1=0x00 00 00 01
lb $s2,0($s0) # $s2=0xFF FF FF 80

从储存器地址+偏移(不必须是4的倍数)位置提取一个字节的数据,放入寄存器的最低有效字节中(最低8位,前24位由符号位拓展)

1
sb $s2,2($s0)  			#($s0)=0x00 80 01 80

从寄存器中提取一个字节的数据,放入储存器地址+偏l移位置(不必须是4的倍数)(只将对应寄存器的最低字节放入储存器地址+偏移所对应的字节,储存器中其他位置被忽略)

2.4 lbu 无符号加载字节

如果不希望对提取的但字节数据进行符号拓展,可以采用lbu指令

3. 转移类指令

3.0 标签

在代码中插入行“lable:”则创立了一个名为lable的标签,在程序中可以根据标签名跳转到此处并从此继续运行

3.1 beq 相等则跳转

例:

1
beq $S0,$s1,label

如果s0中存放的内容等于s1中的内容,则跳转到标号label处

3.2 bne 不等则跳转

例:

1
bne $s0,$s1,label

如果s0中存放的内容不等于s1中的内容,则跳转到标号label处

3.3 j 无符号跳转

例:

1
j label

无条件跳转到标号label处

4. 不等式判定

4.1 slt 小于则置1

例:

1
slt $t0,$s0,$s1

如果s0中内容小于s1中内容,则t0中存1,否则存0

常与beq、bne结合与$0比较进行不等式判定跳转

4.2 sltu、slti、sltiu

1
2
3
4
sltu		$t0,$s0,$s1		# 无符号数比较
addi $s0,$0,-1 #给s0赋值-1 $s0=0xFFFFFFFF
slti $t0,$s0,1 #与立即数比较(-1<1) $t0=1
sltiu $t1,$s0,1 #与立即数的无符号比较(4,294,967,295>1) $t1=0

5. 函数调用指令

5.0 函数约定使用寄存器

1
2
3
$a0–$a3: 	4个入口参数寄存器
$v0–$v1: 2个返回值寄存器
$ra: 返回地址寄存器

5.1 jal 跳转并链接

例:

label```
1
2
3
4
5
6
7
8
9

首先存储下一条指令地址到$ra寄存器中,然后跳转到函数地址label处
用于函数调用



#### 5.2 jr 返回

例:```jr $ra

无条件根据寄存器内容跳转到指定地址处,一般使用$ra

用于函数返回

5.3 $sp 栈操作

当函数中调用函数时$ra会被覆盖,所以压入栈中,子函数返回后在出栈

$sp是一个用来始终指向栈底堆栈指针,时存放栈底地址的寄存器

标准流程:

1
2
3
int sumSquare(int x, int y) {
return mult(x,x)+ y;
}
入栈:
1
2
3
addi	$sp,$sp,-8		# 创建堆栈空间
sw $ra, 4($sp) # 备份返回地址
sw $a1, 0($sp) # 存储y值
1
2
add		$a1,$a0,$zero	# 重设第2入口参数
jal mult # 调用mult
出栈:
1
2
3
4
lw		$a1, 0($sp)		# 恢复y值	
add $v0,$v0,$a1 # 返回结果 val = mult(x,x)+y
lw $ra, 4($sp) # 恢复返回地址
addi $sp,$sp,8 # 恢复堆栈指针
1
jr		$ra

6. 其他

6.1 lui 直接向高地址写入立即数

众所周知mips的所有指令、地址都是32位的,那么如果没有特殊手段,我们将永远无法通过命令的方式将一个地址塞进寄存器里,因为如果仅仅地址就时32位了,那么这条命令加上opcode和寄存器号,一定会超过32位,而lui就是这个特殊手段

例:

1
2
lui		$s0,0x1234
addi $s0,$s0,0x5678

通过这样的两条命令组合,分别向高地址写入16位立即数0x1234,然后再对寄存器s0加上0x5678,把0x5678写入低地址(用ori也可以达到这样的效果),我们就可以把0x12345678这样一条32位的数据传入寄存器中了。