素数表
计算并输出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原创,转载请注明出处!