寄存器种类
- MIPS共有32个通用寄存器
- 在汇编中,寄存器标志由$符号开头
- 寄存器表示共有两种方法
- 直接使用该寄存器对应编号,例如:$0,$31
- 使用对应的寄存器名称,例如:$t1, $sp(名称见下列表格)
寄存器编号 | 寄存器名 | 寄存器用途 |
---|---|---|
0 | zero | 永远返回0 |
1 | $at | 汇编保留寄存器 |
2-3 | $v0 - $v1 | 存储表达式或者函数的返回值 |
4-7 | $a0 - $a3 | 存储子程序的前4个参数,在子程序调用过程中释放 |
8-15 | $t0 - $t7 | 临时变量,同上调用时不保存 |
16-23 | $s0 - $s7 | 调用时保存 |
24-25 | $t8 - $t9 | 临时变量,同上调用时不保存 |
26-27 | $k0 - $k1 | 中断函数返回值,不可做其他用途 |
28 | $gp | (Global Pointer)保存静态或外部变量 |
29 | $sp | 栈指针,指向栈顶 |
30 | $ s8 ($ fp) | 帧指针 |
31 | $ra | 返回地址 |
指令种类
- R型指令
000000 | Rs | Rt | Rd | shamt | funct |
---|---|---|---|---|---|
6bits | 5bits | 5bits | 5bits | 5bits | 6bits |
- I型指令
OP | Rs | Rt | 立即数 |
---|---|---|---|
6bits | 5bits | 5bits | 16bits |
- J型指令
OP | 立即数 |
---|---|
6bits | 26bits |
寻址方式
立即数寻址
- I型指令
addi s1,s2, 10 相当于 $s1 = $s2 + E(10)
OP | Rs | Rt | 立即数 |
---|---|---|---|
6bits | $s2 | $s1 | 16bits |
寄存器寻址
- R型指令
add $t0, $s1, $s2 相当于 $t0 = $s1 + $s2
000000 | Rs | Rt | Rd | shamt | funct |
---|---|---|---|---|---|
6bits | $s1 | $s2 | $t0 | 00000 | 6bits |
基址寻址
- I型指令
Rs 中存放基址寄存器,因为立即数只有16位,所以我们将其带符号拓展为32位,然后与基址相加,就可以得到目标数的地址。 - 常见的基址寻址指令:lw, sw, lh, sh, lb, lbu等
相对寻址
- I型指令
将16位的立即数带符号拓展为32位后,将其左移两位(此时它的最低两位就是0),然后与PC寄存器地址相加,所得为目标值的地址 - 常见相对寻址指令有:beq,bne
伪直接寻址
- J型指令
对于26位的立即数直接左移两位,此时它为28位,而且它的最低两位为0,这时我们取PC的高四位地址做为目标地址的高四位,其余28位为得到的立即数,这个地址为目标值的地址。
指令总览
类别 | 指令 | 例 | 含义 | 备注 |
---|---|---|---|---|
算数 | 加 | add $s1,$s2,$s3 | $s1 = $s2 + $s3 | 三个操作数;检测溢出 |
算数 | 减 | sub $s1,$s2,$s3 | $s1 = $s2 - $s3 | 三个操作数;检测溢出 |
算数 | 加立即数 | addi $s1,$s2,100 | $s1 = $s2 + 100 | 加常数;检测溢出 |
算数 | 无符号加 | addu $s1,$s2,$s3 | $s1 = $s2 + $s3 | 三个操作数;不检测溢出 |
算数 | 无符号减 | subu $s1,$s2,$s3 | $s1 = $s2 - $s3 | 三个操作数;不检测溢出 |
算数 | 无符号加立即数 | addiu $s1,$s2,100 | $s1 = $s2 + 100 | 加常数;不检测溢出 |
算数 | 从协处理器寄存器中获得 | mfc0 $s1,$epc | $s1 = $epc | 复制异常PC到专用处理器 |
算数 | 乘 | mult $s2,$s3 | Hi,Lo = $s2 × $s3 | 64位有符号积存在Hi,Lo中 |
算数 | 无符号乘 | multu $s2,$s3 | Hi,Lo = $s2 × $s3 | 64位无符号积存在Hi,Lo中 |
算数 | 除 | div $s2,$s3 | Lo = $s2 / $s3;Hi = $s2 mod $s3 | Lo = 商;Hi = 余数 |
算数 | 无符号除 | div $s2,$s3 | Lo = $s2 / $s3;Hi = $s2 mod $s3 | 无符号商和余数 |
算数 | 从Hi中获得 | mfhi $s1 | $s1 = Hi | 用来获得Hi的副本 |
算数 | 从Lo中获得 | mflo $s1 | $s1 = Lo | 用来获得Lo的副本 |
数据传输 | 取字 | lw $s1,20($s2) | $s1 = Memory[$s2 + 20] | 将一个字从内存中取到寄存器中 |
数据传输 | 存字 | sw $s1,20($s2) | Memory[$s2 + 20] = $s1 | 将一个字从寄存器中取到内存中 |
数据传输 | 取无符号半字 | lhu $s1,20($s2) | $s1 = Memory[$s2 + 20] | 将半字从内存中取到寄存器中 |
数据传输 | 存半字 | sh $s1,20($s2) | Memory[$s2 + 20] = $s1 | 将半字从寄存器中取到内存中 |
数据传输 | 取无符号字节 | lbu $s1,20($s2) | $s1 = Memory[$s2 + 20] | 将一个字节从内存中取到寄存器中 |
数据传输 | 存字节 | sb $s1,20($s2) | Memory[$s2 + 20] = $s1 | 将一个字节从寄存器中取到内存中 |
数据传输 | 取链接字 | ll $s1,20($s2) | $s1 = Memory[$s2 + 20] | 取字作为原子交换的前半部 |
数据传输 | 存条件字 | sc $s1,20($s2) | Memory[$s2 + 20] = $s1或$s1 = 0/1 | 存字作为原子交换的后半部 |
数据传输 | 立即数读入高16位 | lui $s1,100 | $s1 = 100 ×2^16 | 取立即数并放在高16位 |
逻辑运算 | 与 | AND $s1,$s2,$s3 | $s1 = $s2 & $s3 | 三个寄存器操作数按位与 |
逻辑运算 | 或 | OR $s1,$s2,$s3 | $s1 = $s2 | $s3 | 三个寄存器操作数按位或 |
逻辑运算 | 或非 | NOR $s1,$s2,$s3 | $s1 = ~($s2 | $s3) | 三个寄存器操作数按位或非 |
逻辑运算 | 与立即数 | ANDi $s1,$s2,100 | $s1 = $s2 & 100 | 和常数按位与 |
逻辑运算 | 或立即数 | ORi $s1,$s2,100 | $s1 = $s2 | 100 | 和常数按位或 |
逻辑运算 | 逻辑左移 | sll $s1,$s2,10 | $s1 = $s2 << 10 | 根据常数左移相应位 |
逻辑运算 | 逻辑右移 | srl $s1,$s2,10 | $s1 = $s2 >> 10 | 根据常数右移相应位 |
条件跳转 | 相等时跳转 | beq $s1,$s2,25 | if($s1 == $s2)跳至PC + 4 + 100 | 相等检测;和PC相关的跳转 |
条件跳转 | 不相等时跳转 | bne $s1,$s2,25 | if($s1 != $s2)跳至PC + 4 + 100 | 不相等检测;和PC相关的跳转 |
条件跳转 | 小于时置位 | slt $s1,$s2,$3 | if($s2 < $s3) $s1 = 1;否则等于0 | 比较是否小于;补码形式 |
条件跳转 | 小于立即数时置位 | slti $s1,$s2,100 | if($s2 < 100) $s1 = 1;否则等于0 | 比较是否小于常数 |
条件跳转 | 无符号数比较小于时置位 | sltu $s1,$s2,$3 | if($s2 < $s3) $s1 = 1;否则等于0 | 比较是否小于 |
条件跳转 | 无符号数比较小于立即数时置位 | sltiu $s1,$s2,100 | if($s2 < 100) $s1 = 1;否则等于0 | 比较是否小于常数 |
无条件跳转 | 跳转 | j 2500 | 跳至10000 | 跳转到目标地址 |
无条件跳转 | 跳转至寄存器所指地址 | jr $ra | 跳至$ra | 用于switch语句,以及过程调用的返回 |
无条件跳转 | 跳转并链接 | jal 2500 | $ra = PC + 4; 跳至10000 | 用于过程调用 |