【MIPS汇编编程练习Lab4】堆栈寄存器使用与递归方法(函数)使用

本文通过示例展示了堆栈在保存初始变量和递归调用中的应用。在第一个例子中,堆栈用于保存初始值10,并在自定义函数`increaseMyReg`中进行增加后再恢复。第二个例子演示了递归调用`increaseMyReg`和`printf_s0`函数,强调了保存$ra寄存器的重要性,以正确返回到main方法。这两个实例揭示了堆栈在程序流程控制和函数调用中的关键角色。
摘要由CSDN通过智能技术生成

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此时是 1010--->(-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) 得到正确的结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值