2019年年历by MIPS
我在写2019年历的时候遇到了比较多的困难,而网上关于MIPS的代码又比较少,所以我在这贴一下我的代码,希望能帮到大家。
独立思考最重要!
.data
cal: .space 2113
calname:.asciiz "JanFebMarAprMayJunJulAugSepOctNovDec"
start: .asciiz "Put out the calendar of 2019: \n"
weekday: .asciiz "SMTWTFS"
monday: .word 31,28,31,30,31,30,31,31,30,31,30,31
end99: .asciiz "\nEnding by XiaZeYu919106840637"
.text
main: la $a0,start #打印提示语
li $v0,4
la $s0,calname
syscall
la $s1,cal
sb $0,2112($s1) #为空间末尾放置结束符
li $t0,0x20
li $t1,0
loop0: sb $t0,($s1) #为cal空间全部赋空格
addi $s1,$s1,1
addi $t1,$t1,1
blt $t1,2112,loop0
li $t0,0
li $t1,0
li $s1,0
li $a0,2 #已知2019年1月1日是星期2
li $a1,1 #$a1为月份
monLoop:jal month
move $a0,$v0
blt $a0,7,go_on0#当weekday为周日时清零
addi $a0,$a0,-7
go_on0: addi $a1,$a1,1
bgt $a1,12,end
b monLoop
end: li $t0,0x0a #为空间内每一层的末尾加上换行符
la $t1,cal
addi $t1,$t1,65
li $t2,1
loop_n: sb $t0,($t1)
addi $t2,$t2,1
addi $t1,$t1,66
bgt $t2,32,endd
b loop_n
endd: la $a0,cal #输出年历
li $v0,4
syscall
la $a0,end99
li $v0,4
syscall
li $v0,10 #结束
syscall
month: addi $a2,$a1,-1 #利用$a2来计算该月份的偏移量
rem $t5,$a2,3
mul $t5,$t5,22
ble $a1,3,add1 #1-3月
ble $a1,6,add2 #4-6月
ble $a1,9,add3 #7-9月
ble $a1,12,add4 #10-12月
add1: la $a3,cal #基址在第一大段
b end_add
add2: la $a3,cal
addi $a3,$a3,528#把基址移到第二大段
b end_add
add3: la $a3,cal
addi $a3,$a3,1056#把基址移到第三大段
b end_add
add4: la $a3,cal
addi $a3,$a3,1584#把基址移到第四大段
b end_add
end_add: add $a3,$a3,$t5 #让$a3存储每个月所在缓存区的基址
#开始初始化每个月份表头
li $t0,0 #loop1为初始化缓冲区内每个月份的坐标
loop1: blt $t0,10,kong1
bgt $t0,12,kong1
add $t1,$a3,$t0
lb $t2,($s0)
sb $t2,($t1)
addi $s0,$s0,1 #使$s0指向calname字符串中的下一个字符
addi $t0,$t0,1
b loop1
kong1: add $t1,$a3,$t0 #输入空格的循环
li $t2,0x20
sb $t2,($t1)
addi $t0,$t0,1
bgt $t0,21,go_on1#当过了这个月份就跳出
bne $t0,9,loop1 #当要输入月份数字时特殊处理
addi $t0,$t0,-1
bge $a1,10,ano1 #判断月份是否有十分位
move $t2,$a1
addi $t2,$t2,48
sb $t2,($t1)
addi $t0,$t0,1
b loop1
ano1:li $t3,10 #当月份大于10时
div $a1,$t3
addi $t1,$t1,-1
mflo $t2 #将月份的前一位放置
addi $t2,$t2,48
sb $t2,($t1)
addi $t1,$t1,1
mfhi $t2 #将月份的后一位放置
addi $t2,$t2,48
sb $t2,($t1)
addi $t0,$t0,1
b loop1
go_on1: li $t0,0
li $t1,0
li $t2,0
li $t3,0
li $t5,0 #临时寄存器清零
#开始初始化星期日期
addi $t0,$a3,66 #将指针指向基址的下一层
la $t1,weekday #用$t1选择weekday
li $t3,0 #用$t3来记录已初始化天数,达七天跳出
loop2: li $t2,0x20 #输入空格
sb $t2,($t0)
addi $t0,$t0,1
lb $t2,($t1) #输入weekday
sb $t2,($t0)
addi $t0,$t0,1
addi $t1,$t1,1
li $t2,0x20 #输入空格
sb $t2,($t0)
addi $t0,$t0,1
addi $t3,$t3,1 #已初始化天数加一
bgt $t3,6,go_on2#当初始化完毕则跳出
b loop2 #继续
go_on2: li $t2,0x20 #输入两月间的空格
sb $t2,($t0)
#开始初始化具体日期
li $t0,0 #清空临时寄存器
li $t1,0
li $t2,0
li $t3,0
li $t0,1 #用$t0存储每个月具体的日期,$a0存储这个日期代表星期几
addi $t1,$a3,132#用$t1指向基址的所在区域的第三层,开始存放日期
mul $t2,$a0,3
add $t1,$t1,$t2#使指针指向每个月第一天所在weekday
loop3: bge $t0,10,ano2#当日期大于十时分类处理
blt $a0,7,go_on3 #当一个星期满后开始下一个星期
addi $t1,$t1,-21 #指针跳至下一层
addi $t1,$t1,66
addi $a0,$a0,-7 #开始从星期天循环
go_on3: addi $t1,$t1,1 #输入日期
addi $t3,$t0,48
sb $t3,($t1)
addi $t1,$t1,2
addi $t0,$t0,1
addi $a0,$a0,1
b loop3 #循环
ano2: mul $t7,$a2,4 #通过$t6,$t7来获取该月的最大天数
la $t6,monday
add $t7,$t7,$t6
lw $t6,($t7)
bgt $t0,$t6,out_end#当日期超过最大天数时结束函数
blt $a0,7,go_on4 #同上,判断是否满一个星期
addi $t1,$t1,-21
addi $t1,$t1,66
addi $a0,$a0,-7
go_on4: li $t3,10 #处理大于10的日期
div $t0,$t3 #取商为十位,余数为个位放置
mflo $t3
addi $t3,$t3,48
sb $t3,($t1)
addi $t1,$t1,1
mfhi $t3
addi $t3,$t3,48
sb $t3,($t1)
addi $t1,$t1,2
addi $a0,$a0,1
addi $t0,$t0,1
b loop3 #循环
out_end:move $v0,$a0 #将下个月的第一天的weekday作为参数返回
jr $ra
具体的思路是把内存段看成一个二维平面来一个一个放值。