MIP指南(一)
.eqv 为寄存器命名
主要是为了提高代码的可读性
习惯了C语言的函数命名,现在看一堆寄存器的名字就很不习惯
寄存器功能约定
这个其实我在上一篇也提到了这一点,但我当时的想法只是针对每一个题,规定不同的寄存器的用途,是一个比较初步的想法。
而学长的做法就相对比较成熟了,算是直接将这个想法抽象出来,直接规定哪几个寄存器是做什么的,这样以后无脑用就很方便。
- for循环变量:$t0,$t1
这里我们特别强调一下,函数调用时要注意这两个寄存器的入栈和出栈,防止发生冲突
- 验证真值:$t2
- 恒1变量:$t3
- 数组地址位移:$t4
- 数组的数:$t5
宏定义
宏定义的简单使用
这里其实我在第一篇有关COpre的文章里就提到过,但是那个没有这个全面,我也正好试一下学习的新板块功能
宏定义大致分为以下5类:
- int数字的输入(5)和输出(1)
- char字符的输入(12)和str字符串的输出(4)
- 数组位移偏移量的获取
- 函数的寄存器压栈[push(-4),pop(4)]
- 结束程序(10)
1 2 3 4 5 6 7 8 9 10 11
| .macro getInt(%des) li $v0,5 syscall move %des,$v0 .end_macro
.macro printInt(%src) move $a0,%src li $v0 ,1 syscall .end_macro
|
1 2 3 4 5 6 7 8 9 10 11
| .macro getChar(%des) li $v0,12 syscall move %des,$v0 .end_macro
.macro printStr(%src) la $a0, %src li $v0, 4 syscall .end_macro
|
1 2 3 4 5 6 7 8 9
| .macro push(%src) addi $sp,$sp,-4 sw %src,0($sp) .end_macro
.macro pop(%des) lw %des,0($sp) addi $sp,$sp,4 .end_macro
|
1 2 3 4 5 6 7 8 9 10 11
| .macro One_Array(%ans,%i) sll %ans,%i,2 .end_macro
//Array[M][N] 元素Array[i][j] .macro Two_Array(%ans,%i,%j,%m) mult %i,%m mflo %ans add %ans,%ans,%j sll %ans,%ans,2 .end_macro
|
1 2 3 4
| .macro end li $v0,10 syscall .end_macro
|
到这里我们对宏的使用就结束了吗?
当然没有!!!
宏具备以下特性,使其非常适合封装函数
- 独立的段:可以有自己的.data和.text段
- 重载支持:同名宏可以根据参数个数不同实现重载
因此!我们考虑将麻烦的输出、for循环等等封装成宏!
宏定义的进阶使用
print函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| .macro print(%str) .data _str:.asiiz %str .text la $a0, _str li $v0,4 syscall .end_macro
.macro print(%int,%sep) .data _str:.asiiz %sep .text li $v0,1 move $a0,%int syscall la $a0, _str li $v0,4 syscall .end_macro
|
1 2
| print("hello") print($t0,"is $t0")
|
for循环
通过宏封装,不仅可以实现嵌套循环,而且代码的可读性也会得到显著提高.
原理是将标签作为参数传入宏,从而实现循环的嵌套.
1 2 3 4 5 6 7 8 9 10 11
| .macro for(%i,%n,%startLabel,%endLabel) li %i,0 %startLabel: bge %i,%n,%endLabel .end_macro
.macro for_end(%i,%startLabel,%endLabel) add %reg,%reg,1 j %startLabel %endLabel: .end_macro
|
1 2 3 4 5
| for($t0,n,begin1,end1) for($t1,m,begin2,end2)
for_end($t1,begin2,end2) for_end($t0,begin1,end1)
|
递归函数调用过程
这里我们直接以Hamilton回路为例
1 2 3 4 5 6 7 8 9 10
| .macro dfs(%int) move $a0,%int push($t0) push($t1) push($ra) jal dfs_function pop($ra) pop($t1) pop($t0) .end_macro
|
参考1
参考2