CO-Mips

CO-Mips

Charles Lv7

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.基本原则

首先强调一些关于汇编程序设计的要点。

  1. 先了解语言的基本结构和特征。
  2. 保持良好的代码风格习惯。
  3. 再开始敲代码之前,先写出c语言程序(或者其他语言也行).
  4. 积极拆分每个独立功能,分开实现。(多用.macro)
  5. 多写注释。

2.进阶技巧

优雅地实现方式会大大提高程序的可读性。如果码完就再也不看,那么请随便写。

  1. 自定义编辑器。

MARS的默认配色不是很易读。建议把编辑器调到舒适为止。

  1. 遵守寄存器的用法。

如果不加区分地随便使用寄存器,大家都知道会变成什么样的。

  1. 保持固定的缩进格式。

我用的缩进是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

整齐的话,读起来也轻松一些

  1. 多打label。

就像上面那个例子一样,就算打不使用的label也可以让代码更明确。

我在lable和macro用了不同的命名方式,可能有一点让人不适,请谅解。

  1. 可以打标点也可以不打,但是不要时打时不打。
  2. 多用macro
  3. 在macro里做好出入栈
  4. 遵守对特定寄存器的回避。

macro的入参和macro中使用的寄存器重复时,会发生难以定位的错误。所以不要使用macro中用过的寄存器作为入参。

一种做法是将$a0, $t8, $t9用于macro部分,此后的运算中再也不用这几个寄存器。

  1. 使用更稳定(运行稳定,或者让你自己心态稳定)的指令。

比如在ori $t0,$0,100li $t0,100中,优先选择更稳定的后者。

又如在自加(根本记不住那是什么指令)和addi $t0,$t0,1,优先使用更易于快速理解的后者。

又如减少使用.ascii,使用.asciiz

  1. 固定重要变量所对应的寄存器。

比如循环变量,数据范围,常数,答案等值,优先使用固定的寄存器记录,并不再改变。 记得记录每个寄存器固定成了什么变量。例如:

1
2
3
4
5
6
scanInt($s1)            #n
scanInt($s2) #m
li $s3, 0 #ans
li $s4, 0 #i
# $s5 #x
# $s6 #y

之后使用的时候就能更明确哪个寄存器存的是什么了。

在函数里可以把不需要的变量压栈,省出寄存器的位置。

  1. 固定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:
  1. 封装对存储的访问。
  2. 封装输入输出。
  3. 用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.
Comments