CO-Mips
CO-Mips
MIPS汇编指令翻译机器码
寄存器的编号及其地址
指令翻译为机器码,寄存器的编号十分重要,rs,rt,rd的序号都根据序号而定。
名字 | 编号 | 机器码编号 | 名字 | 编号 | 机器码编号 |
---|---|---|---|---|---|
$s0 | 0 | 00000 | $t9 | 24~25 | 11000~11001 |
$at | 1 | 00001 | $k1 | 26~27 | 11010~11011 |
$v1 | 2~3 | 00010~00011 | $gp | 28 | 11100 |
$a3 | 4~7 | 00100~00111 | $sp | 29 | 11101 |
$t7 | 8~15 | 01000~01111 | $fp | 30 | 11110 |
$s7 | 16~23 | 10000~10111 | $ra | 31 | 11111 |
机器码的格式
以R型指令为例
1 | add $s0,$s1,$s2 |
op | rs | rt | rd | shamt | funct |
---|---|---|---|---|---|
000000 | 01011 | 01101 | 01000 | 00000 | 100010 |
6bit | 5bit | 5bit | 5bit | 5bit | 6bit |
对于add指令,op值为00000,进一步来说,所有的R型指令的op都为0,它的特殊功能都由funct来决定。
rs,rt,rd的值都是从上一部分的表格中的来的 ,rs,rt,rd是通用寄存器的代称,值要根据具体使用的寄存器而定,shamt表示移位数
MIPS的一些汇编编写技巧
1.基本原则
首先强调一些关于汇编程序设计的要点。
- 先了解语言的基本结构和特征。
- 保持良好的代码风格习惯。
- 再开始敲代码之前,先写出c语言程序(或者其他语言也行).
- 积极拆分每个独立功能,分开实现。(多用.macro)
- 多写注释。
2.进阶技巧
优雅地实现方式会大大提高程序的可读性。如果码完就再也不看,那么请随便写。
- 自定义编辑器。
MARS的默认配色不是很易读。建议把编辑器调到舒适为止。
- 遵守寄存器的用法。
如果不加区分地随便使用寄存器,大家都知道会变成什么样的。
- 保持固定的缩进格式。
我用的缩进是8个空格(可能略长,请找一个看着舒服的),并且在.macro,if,for的部分会使用额外的行首缩进。我在每行指令的两个值之间也选择使用缩进(也可以不搞,因为tab键也不好按)。像这样:
1
2
3
4
5
6
7
8
9
10
11
12
13 add $s1, $zero, $t1
li $s2, -20
beq $s1, $s2, end_if
nop
begin_if:
addi $s1, 1
ori $s1, $s1, $s2
j end_if
nop
end_if:
printInt($s1)
jal func
end # This code is example整齐的话,读起来也轻松一些
- 多打label。
就像上面那个例子一样,就算打不使用的label也可以让代码更明确。
我在lable和macro用了不同的命名方式,可能有一点让人不适,请谅解。
- 可以打标点也可以不打,但是不要时打时不打。
- 多用macro
- 在macro里做好出入栈
- 遵守对特定寄存器的回避。
macro的入参和macro中使用的寄存器重复时,会发生难以定位的错误。所以不要使用macro中用过的寄存器作为入参。
一种做法是将
$a0, $t8, $t9
用于macro部分,此后的运算中再也不用这几个寄存器。
- 使用更稳定(运行稳定,或者让你自己心态稳定)的指令。
比如在
ori $t0,$0,100
和li $t0,100
中,优先选择更稳定的后者。又如在自加(根本记不住那是什么指令)和
addi $t0,$t0,1
,优先使用更易于快速理解的后者。又如减少使用
.ascii
,使用.asciiz
。
- 固定重要变量所对应的寄存器。
比如循环变量,数据范围,常数,答案等值,优先使用固定的寄存器记录,并不再改变。 记得记录每个寄存器固定成了什么变量。例如:
1
2
3
4
5
6 scanInt($s1) #n
scanInt($s2) #m
li $s3, 0 #ans
li $s4, 0 #i
# $s5 #x
# $s6 #y之后使用的时候就能更明确哪个寄存器存的是什么了。
在函数里可以把不需要的变量压栈,省出寄存器的位置。
- 固定for和if语句的格式。
比如这样:
1
2
3
4
5
6
7
8
9 func_for1_begin:
beq $s4, $s1, func_for1_end # i!=n
nop
# do something
# do something
# do something
addi $s4, $s4, 1 # i++
j func_for1_begin
func_for1_end:
- 封装对存储的访问。
- 封装输入输出。
- 用print调试。
- Title: CO-Mips
- Author: Charles
- Created at : 2022-12-27 13:02:41
- Updated at : 2023-11-05 21:36:02
- Link: https://charles2530.github.io/2022/12/27/co-mips/
- License: This work is licensed under CC BY-NC-SA 4.0.