1、堆栈保存初始变量
.data
newLine: .asciiz "\n" #定义换行变量
.text
main:
addi $s0,$zero,10 # 将10 存到s0堆栈寄存器中,用于保存s0的初值
jal increaseMyReg #跳转到 自定义方法
# 打印换行符号
li $v0,4
la $a0,newLine
syscall
#打印当前s0寄存器中的值
li $v0,1
move $a0,$s0
syscall
#return,关闭程序
li $v0,10
syscall
#自定义函数方法
increaseMyReg:
addi $sp,$sp,-4 # 令sp寄存器值为 -4
sw $s0,0($sp) #将$s0内容存到$sp寄存器的值指向的内存地址中 s0此时是 10,10--->(-4)
addi $s0,$s0,30 # s0 = 10 + 30 =40
#print new valude in function
li $v0,1
move $a0,$s0 #打印 s0 = 40
syscall
lw $s0,0($sp) #加载之前存入地址为(-4)内存中的值
addi $sp,$sp,4 #sp寄存器地址值加4,指向一个新地址(栈顶) = -4+4 = 0
jr $ra #退出方法,回到main
40是计算函数得到的值,而10是存放在栈内的值。
2.递归调用函数
.data
newLine: .asciiz "\n"
.text
main:
addi $s0,$zero,10
jal increaseMyReg
#换行
li $v0,4
la $a0,newLine
syscall
jal printf_s0
#return
li $v0,10
syscall
increaseMyReg:
addi $sp,$sp,-8 #sp指针地址 -4 先向下一个栈
sw $s0,0($sp) #将$s0内容存到$sp的内存地址中 s0此时是 10
sw $ra,4($sp)
addi $s0,$s0,30 #s0 = 10 + 30 =40//
#Nested Procedure
jal printf_s0
lw $s0,0($sp) #从一个指定的地址$s0中内容 加载一个word类型的值到一个寄存器s0中,s0现在是10
lw $ra,4($sp)
addi $sp,$sp,4 #sp寄存器值= -4+4 = 0
jr $ra
printf_s0:
li $v0,1
move $a0,$s0 #打印 s0 = 40
syscall
jr $ra
此处要注意保存 $ra寄存器中的地址变量,它会保存return address,也就是函数返回地址。
如果此处不保存 $ra寄存器的变量的话,当第一次调用完printf_s0函数,他会保存increaseMyReg方法的返回地址,而此时,它正在该方法体内运行。因此 它将无法跳出该方法回到 main方法中。因此会报出溢出或者其他的错误。
按照上述代码执行后,将利用 $ s0 寄存器保存main方法的ra(return address) 得到正确的结果: