南理工MIPS大作业

南理工汇编大作业

素数表

计算并输出N的下一个素数。

#######################################################
#最后一次修改:2022.3.29
#最主要自主函数创建部分:  
#void Nextprime(int n){ 
#	int flag=0;
#	if(n%2==0)
#     	{
#	     n++;
#	}
#   while(1){		
#	for(int i=0;(prime[i]*prime[i])<=n;i++){
#		if(n%prime[i]==0){
#			flag=0;
#			break;
#		}
#		else {
#                   flag=1;
#		}
#		if(flag==1){
#			cout<<n;
#			break;
#		}
#		else n+=2;
#	}
#######################################################
.data 
prime: 	.space 14000  #定义半字数组大小
out_1: 	.asciiz " primes created. The last 10 primes is: \n"
table:	.asciiz "\n"
nps:  .asciiz "   "
tip1: .asciiz "Please input a number: \n"
tip2: .asciiz "The next prime is: \n"
tip3: .asciiz "The program is over! "
tip4: .asciiz "The number out of range \n"

	.align 2	
	.globl main
	.text
main:	jal CreatePrimes  #跳转链接函数
	jal NextPrime	#跳转链接函数2
	li $v0,10	#调用系统终止参数,防止继续执行
	syscall

#第一个函数
CreatePrimes:
	la $a1,prime #把数组首地址存放到a1
	li $t7,3   #数组第一个数设置为3
	sh $t7,0($a1) #半字存储
	addi $a1,$a1,2 #地址偏移加2
	li $t1,5  #定义变量i,赋初值5
	li $t2,1  #定义变量j,赋初值1
	li $t3,65536  #初始化循环计数
loop:		  #外层循环
	li $t4,3  #定义变量k
loop2:		  #内层循环
	divu $t1,$t4		#判断能否整除
	mfhi $t0			#将余数移入
	beqz $t0,loop3		#第一个if判断
	mul $t5,$t4,$t4		#计算循环计数k*k,存入t5
	addi $t4,$t4,2		#变量k累计加2
	ble $t5,$t1,loop2	#判断k*k是否小于等于i
loop3:	
	move $t7,$t4		#这里注意要重新设置一个判断数,因为t5里的值可能用不到
	mul $t8,$t7,$t7		#相当与k*k
	ble $t8,$t1,else 	#第二个if判断???
	sh $t1,0($a1)		#半字存入
	addi $t2,$t2,1		#个数累加
	addi $a1,$a1,2		#地址累加
else:	
	addi $t1,$t1,2
	blt $t1,65536,loop
	
print:	
	subi $t1,$t2,10	#设置循环变量
	la $t3,prime	#将数组地址赋值给t3
	mul $t7,$t1,2	#因为以2字节存储,所以要将个数存入
	add $t3,$t3,$t7	#地址量偏移
	
	li $v0,1
	move $a0,$t2	#打印素数个数
	syscall
	li $v0,4		#打印提示字符串
	la $a0,out_1
	syscall
loop4:	li $v0,1		#调用打印整数的系统接口
	lhu $a0,($t3) #将指针所指向的数移入$a0
	syscall
	li $v0,4		#调用打印字符串的系统接口
	la $a0,nps
	syscall
	addi $t1,$t1,1	#个数递增1
	addi $t3,$t3,2	#地址递增2
	blt $t1,$t2,loop4	#如果小于的话继续循环
	li $v0,4		#打印字符串
	la $a0,table
	syscall		
	move $a0,$t2	#将素数个数通过寄存器$a0返回
	jr $ra		#返回主函数
	

#第二个函数
NextPrime:
again:		
	li $v0,4		#打印提示字符串
	la $a0,tip1	
	syscall	
	li $v0,5		#调用读取整型数的系统接口
	syscall	 
	beq $v0,2,out3
	ble $v0,1,over
	
	#小于65521,直接查表遍历(最后一个素数)
	bge $v0,65521,label
	
	move $t3,$v0
	li $t1,0
	la $t0,prime
loop5: 
	sll $t2, $t1, 1 # 左移乘以2
	add $t2, $t0, $t2 #指向我们需要的那个数
	lhu $s0 0($t2) # 将遍历得到的值与输入的值进行比较
	bge $s0,$t3,out2	#当大于等于时退出循环
	addi $t1, $t1, 1 # 对幂次进行累加
	j loop5
out2:	
	li $v0,4
	la $a0,tip2 #给出提示字符
	syscall
	li $v0,1
	move $a0,$s0
	syscall
	li $v0,4
	la $a0,table
	syscall
	move $v0,$t1  #结果由v0传出
	j again
	
out3:	
	li $v0,4
	la $a0,tip2
	syscall
	li $v0,1  #输出out of range
	li $a0,2	 
	syscall
	li $v0,4		
	la $a0,table
	syscall
	j again	
		
	#大于65521
label:
	move $t1,$v0	#将读取的整型数存入t1
	li $t2,2		#这里存2的目的是先判断奇数和偶数,偶数必不是
	div $t1,$t2	#t1除以t2
	mfhi $t4		#将余数存入t4
	bnez $t4,loop6	#如果余数不为0,说明是奇数,直接跳转处理
	addi $t1,$t1,1	#是偶数就加1处理成奇数
loop6:			#利用素数表的素数作为因子进行检验
	li $t4,3		#与上述判断素数方法类似,赋值3
loop7:	div $t1,$t4	#对所求数字进行判断
	mfhi $t0		#将余数放入t0中
	beqz $t0,loop8	#如果等于0,跳转
	mul $t5,$t4,$t4	#相当于质数表中的数相乘
	move $t6,$t4
	addi $t4,$t4,2	#地址递增
	ble  $t5,$t1,loop7	#如果质数相乘小于所需判断的数,继续循环
loop8:	mul $t8,$t6,$t6		#这边要多一次相乘求值,因为跳转之后可能无法获取之前得到的值
	ble $t8,$t1,else1	#若小于等于就跳转回到循环
	j out			#跳转到输出处
else1:	addi $t1,$t1,2		#对所求的数+2,保证是奇数
	j loop6			#跳转回原判断
out:	
	li $v0,4			#调用系统参数,输出提示字符
	la $a0,tip2
	syscall
	li $v0,1
	move $a0,$t1	#打印字符串和所求数
	syscall	
	li $v0,4
	la $a0,table
	syscall
	move $v0 $t1
	j again
over:	
	li $v0,4
	la $a0,tip3
	syscall
	jr $ra

万年历

计算和输出2022年的年历(基础),这里实现的是万年历。

##############################
#功能描述:
#程序运行后,在控制台输入你想打印的年历的年份,即可输出在控制台。0-1000000年及以上
#############################
#input_function函数:
#参数:$a1  输入的年份
#返回值:$v0  该年的一月一日的星期
##############################
#initialize函数:
#函数内部直接对内存空间初始化,无返回值
#############################
#month函数:
#参数:$a0   第几个月
#参数:$a1   该年的一月一日是星期几
#参数:$a2  月份字符串的地址  
#参数:$a3  每月的天数的地址
#无返回值
################################
.data
calendar: .space 2816
.align 2
monthdays: .word 31,28,31,30,31,30,31,31,30,31,30,31
months: .asciiz"JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"
space: .byte 32
linebreak: .byte 10
week: .asciiz" Sun Mon Tue Wed Thu Fri Sat "
detail_days: .asciiz"12345678910111213141516171819202122232425262728293031"
input_tip:.asciiz"please input a year: "
output_tip: .asciiz"The output of the annual calendar is as follows:\n"
      .globl main
      .text
main: li $v0,4 #输出提示字符
      la $a0,input_tip
      syscall
      li $v0,5 #输入年份
      syscall
      move $a1,$v0  #$a0作为参数传递给函数month
      jal input_function #a1作为参数传入,返回值是v0(包含该年一月一日是星期几)
      move $t5,$v0   #将函数返回值暂时存在t5
      jal initialize   #调用初始化函数
      li $v0,4     #输出打印提示字符
      la $a0,output_tip
      syscall
      move $a1,$t5
      li $t8,12 #设置函数循环次数为12
      la $a2,months #把月份字符串的地址加载到a2中
      la $a3,monthdays #把每月的天数存放在s5中
      li $a0,0 #对应的月份
jump_d:   
      jal month #调用函数
      addi $t8,$t8,-1
      bgt $t8,0,jump_d    
      li $v0,4 #输出日历
      la $a0,calendar 
      syscall
      li $v0,10 #结束程序
      syscall
	
	
#输入年份并返回该年的一月一日所在的星期数并判断平年闰年的函数
input_function:     #参数a1,返回值v0
      move $t5,$a1
      li $t7,4 	#判断是否是闰年
      rem $t8,$t5,$t7 #判断年份是否能整除4
      bne $t8,$0,start   #能被4但不能被100整除,或能被400整除(如果不能被4整除的话,可以直接跳转)
      li $t7,100		
      rem $t8,$t5,$t7	
      beq $t8,$0,leapyearjudge #到这里如果不能被100整除就可以说明是闰年
      la $t1,monthdays #如果是闰年将第二个月置为29
      addi $t1,$t1,4
      li $t7,29
      sw $t7,($t1)
      b start
leapyearjudge: li $t7,400 #同上检查闰年 
      rem $t8,$t5,$t7   
      bne $t8,$0,start
      la $s1,monthdays
      addi $s1,$s1,4
      li $t7,29     #同上重置第二个月
      sw $t7,($s1) 
#计算所输入年份的一月一日是星期几(由t1存储)         
start:
      li $t6,2022      #将2022年1月1日的日期记录下来
      li $t1,6
      bgt $t5,$t6,jump1 
      blt $t5,$t6,tran1
      beq $t5,$t6,equal
jump1:  
      li $t7,4     
      rem $t8,$t6,$t7
      bne $t8,$0,jump2 #如果余数不等于0则跳转到jump2
      li $t7,100	      #如果余数为0,则再试除100
      rem $t8,$t6,$t7	
      bne $t8,$0,jump3	#不等于0跳转到jump3
      li $t7,400		
      rem $t8,$t6,$t7
      bne $t8,$0,jump2
      beq $t8,$0,jump3

jump2: addi $t1,$t1,1   #平年处(365=364+1,364%7=0)
      blt $t1,8,jump4 #如果满7天重新赋值为1,没满7天可以直接跳转了
      li $t1,1
      
jump4: b judge 

jump3:addi $t1,$t1,1  #闰年处(闰年366=364+2)所以要累加两次
      blt $t1,8,ji
      li $t1,1
      
ji:   addi $t1,$t1,1
      blt $t1,8,judge
      li $t1,1           
        
judge: addi $t6,$t6,1
       bne $t6,$t5,jump1        
       b over1
        
tran1: addi $t6,$t6,-1
tran:  li $t7,4 #通过公式计算该年的1月1日是星期几
      rem $t8,$t6,$t7
      bne $t8,$0,tran2
      li $t7,100
      rem $t8,$t6,$t7
      bne $t8,$0,tran3
      li $t7,400
      rem $t8,$t6,$t7
      bne $t8,$0,tran2
      beq $t8,$0,tran3
      
tran2: addi $t1,$t1,-1 #同上,平年减一次,闰年减两次
      bgt $t1,0,tran4
      li $t1,7
      
tran4: b judge1

tran3:addi $t1,$t1,-1
      bgt $t1,0,jii
      li $t1,7
      
jii:   addi $t1,$t1,-1
      bgt $t1,0,judge1
      li $t1,7        
          
judge1: addi $t6,$t6,-1
         bge $t6,$t5,tran       
        b over1        
equal: li $t1,6          
       b over1
over1: 	move $v0,$t1 #(将星期几存入返回值v0)
	jr $ra 
	
 #初始化内存空间函数  
initialize:
      li $t0,2816 #空间循环次数
      la $t2,space #$t2中放空格的地址
      la $t3,linebreak #$t3中放换行符的地址
      la $t1,calendar #$a1中放最终日历的地址
      la $s5,monthdays #$s5中放每月天数的地址
      lb $s1,($t3) #$s1中加载换行
      lb $s0,($t2) #$s0中加载空格
       #初始化年历表
jump_a:   li $t4,87 #通过循环将整张日历初始化(置换为空格和换行符)
jump_b:   sb $s0,($t1) #存入空格
	addi $t0,$t0,-1	#总循环变量
      addi $t1,$t1,1	#地址递增
      addi $t4,$t4,-1	#循环变量递减
      beq $t0,0,jump_c 	#等于0时跳转
      bgt $t4,0,jump_b	#小于等于0向下执行,大于0继续循环
      sb $s1,($t1)	#一行的末尾存入换行符
      addi $t1,$t1,1	
      addi $t0,$t0,-1
      bgt $t0,0,jump_a
jump_c:  jr $ra

     #月份函数
month:
      li $s6,29  #一小行29个字符
      la $t6,calendar #把日历的首地址加载到$t6中
      la $t5,week #把星期的首地址加载到$t5中
      ble $a0,2,loop #对日历分段计算(1,2,3,4)
      ble $a0,5,loop1
      ble $a0,8,loop2
      ble $a0,11,loop3
loop1: addi $t6,$t6,616 #跳转地址
       addi $t6,$t6,1
       b loop
loop2: addi $t6,$t6,1232 #跳转地址
       addi $t6,$t6,2
       b loop
loop3: addi $t6,$t6,1848 #跳转地址
       addi $t6,$t6,3
       b loop                
       
loop: mul $s6,$s6,$a0 
      add $t6,$t6,$s6 #计算放入月份的首地址(第一个月s7为0)
      addi $t6,$t6,13
      li $t2,0
loop_s:   #每次存取三个字符
      lb $s0,($a2) #将月份存入日历
      sb $s0,($t6)
      addi $a2,$a2,1
      addi $t6,$t6,1
      addi $t2,$t2,1
      blt $t2,3,loop_s
      
      addi $t6,$t6,72 #计算星期的首地址
      li $t3,29
loop_w: lb $t2,($t5) #将星期存入日历
      sb $t2,($t6)
      addi $t5,$t5,1
      addi $t6,$t6,1
      addi $t3,$t3,-1
      bgt $t3,0,loop_w
      lw $t0,($a3) #将该月的天数存入$t0
      addi $s5,$a3,4 #地址后移
      li $t2,0
      li $t3,7
      li $t4,4
      la $s4,detail_days #把具体日期的地址存入$s4
      addi $t6,$t6,60 #地址移到具体日期的位置
      beq $t3,$a1,jump_h
      mul $t4,$t4,$a1   #4*n前进
      add $t6,$t6,$t4            
jump_h: lb $t7,($s4) #把前10个具体日期(1-9)存入日历
      sb $t7,($t6)
      addi $s4,$s4,1
      addi $t0,$t0,-1      
      addi $t2,$t2,1
      addi $a1,$a1,1 #$t1中记录下次在星期几输出并且不断改变$t1(最关键的一个点不仅要改变而且要保存状态)
      blt $a1,8,tran_b
      li $a1,1
tran_b:blt $a1,7,tran_a
      addi $t6,$t6,64 #换行
      b tran_c
tran_a: addi $t6,$t6,4 #后移       
tran_c:blt $t2,9,jump_h #将后面的具体日期存入日历      
jump_j:
      li $t3,1
loop_r:  
      lb $t7,($s4)
      sb $t7,($t6)
      addi $s4,$s4,1
      addi $t6,$t6,1
      addi $t3,$t3,1
      ble $t3,2,loop_r
      addi $t0,$t0,-1    
      addi $a1,$a1,1
      blt $a1,8,tran_d
      li $a1,1
tran_d:blt $a1,7,tran_e
      addi $t6,$t6,62 #换行
      b tran_f
tran_e: addi $t6,$t6,2 #后移    
tran_f:bgt $t0,0,jump_j
	addi $a0,$a0,1 #累计循环次数
      jr $ra #函数返回



文章作者:Krcoding
版权声明:本文章由Krcoding原创,转载请注明出处!

  • 5
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 计算机组成原理MIPS大作业是关于使用Verilog语言实现MIPS指令集的设计与开发。MIPS(Microprocessor without Interlocked Pipeline Stages)是一种精简指令集(RISC)架构,广泛应用于嵌入式系统和大规模计算机中。 在这个大作业中,我们需要使用Verilog语言来实现MIPS处理器的核心功能,包括指令译码、数据通路、控制单元等。首先,我们需要根据MIPS指令集的格式和规则,设计和编写Verilog模块来进行指令译码,将二进制指令解析为对应的操作码和操作数。同时,我们还需要设计和实现数据通路,包括寄存器堆、ALU(算术逻辑单元)、数据存储器等,用于执行指令中的操作并存储数据。最后,我们还需要设计和编写控制单元,通过产生控制信号来驱动数据通路的操作。 在实现过程中,我们需要注意保持指令的顺序和正确性,确保每一条指令的执行都符合MIPS指令集的规则。我们还需要进行仿真和测试,使用Verilog的仿真工具来模拟和验证实现的正确性。 此外,为了进一步提升处理器的性能,我们可以添加流水线和多级缓存等技术来提高指令的执行效率。流水线可以将指令的执行划分为多个阶段,使得每个阶段可以并行执行,从而提高处理器的吞吐量。而多级缓存可以通过提前缓存数据,减少对主存的访问时间,进一步加快指令的执行速度。 总之,计算机组成原理MIPS大作业是一个重要且具有挑战性的项目,需要我们熟练掌握Verilog语言和MIPS指令集,通过设计与实现MIPS处理器的核心结构和功能,来加深对计算机组成原理的理解和实践。 ### 回答2: 计算机组成原理MIPS大作业Verilog是一门以硬件描述语言Verilog实现MIPS指令集的课程项目。MIPS指令集是一种经典的RISC指令集架构,由于其简洁、清晰的设计,常被用于CPU、嵌入式系统等领域。 该大作业的主要目标是使用Verilog HDL编写一个能够正确执行MIPS指令集的CPU模拟器。实现一个完整的CPU模拟器是一个复杂而庞大的工程,需要包含一系列功能模块,如指令存储器、数据存储器、寄存器组、ALU等。 在实现过程中,首先需要了解MIPS指令集的特点和功能,包括指令的格式、指令的执行过程及指令的功能。然后按照MIPS指令集的要求,设计并编写各种功能模块的Verilog代码。同时,还需要设计合适的时钟控制电路和数据通路,以确保指令能够按顺序、正确地执行。最后,进行功能验证和测试,验证所写的模块能够正确地执行各种MIPS指令。 在实现过程中,还需要注意一些细节,如处理异常和中断、支持乘法和除法指令、实现流水线等。这些都是实际的CPU设计中常见的问题。 通过完成这个大作业,可以深入理解计算机组成原理中的各个概念和原理,并通过实践掌握Verilog HDL编程技能。此外,通过调试和测试,还可以提高自己的问题解决能力和团队协作能力。 总而言之,计算机组成原理MIPS大作业Verilog是一个能够锻炼自己对计算机硬件设计、MIPS指令集和Verilog HDL编程的综合能力的项目。完成该大作业可以提高我们对计算机原理的理解,并为后续的学习和研究打下坚实的基础。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值