实验内容
(1)编写两个矩阵相乘的程序。
(2)实现多项选择功能(包括循环)。
(3)进一步熟悉运用WinDLX模拟器。
(4)掌握DLX流水线的定向技术、加速比等技术参数,分析读后写停顿周期,进一步掌握调试技术。
实验结果与分析
本程序设计为固定大小的两个矩阵相乘(A为3行4列,B为4行2列)
首先提示A矩阵的大小,按提示输入后会将A矩阵输出,接着提示输入B矩阵
按提示输入B矩阵后,根据老师要求将B矩阵连续输出两次,接着计算结果并显示出来。提示输入0截至程序运行,输入其他的值继续进行运算。
如下图输入其他值继续运行
如下图若输入0,则结束程序
实验结果分析:
本次实验主要内容为计算两个矩阵相乘,如上图结果所示能够按老师要求完成实验所有内容,在初次检查时,输入较大的数后,因为显示位数的问题会将结果显示到一起导致无法看清结果,后改进后解决了这个问题,根据老师要求实现输入矩阵A后立即将矩阵A打印出来接着再输入矩阵B,并实现在输出矩阵B时将矩阵B连续输出两次。最后利用循环分支语句实现多次输入矩阵并计算。
程序代码
;********multiply an array to an array*****
;******* Written by ty *********
;三个矩阵按行存储
;第一个矩阵的大小为:3*4
;第二个矩阵的大小为:4*2
;存放结果的矩阵大小为:3*2
;l 代表了第一个矩阵的当前被扫描的那行
;r4<=r 相对于result的偏移量
;r5<-l
;r10<-i 第一个矩阵某一行的某个元素的索引
;r7<-j 第二个矩阵某一列的某个元素的索引
;*******************************************
.data
dat1: .space 12
dat2: .space 8
result: .space 6
Prompt1: .asciiz "Input the martrixA's number:"
Prompt2: .asciiz "Input the martrixB's number:"
Prompt3: .asciiz "Input 0 to end,other continue:"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PrintfFormat: .asciiz "%7d"
.align 2
PrintfPar: .word PrintfFormat
PrintfValue: .space 4
;
PrintfFormat1: .asciiz "\n"
.align 2
PrintfPar1: .word PrintfFormat1
PrintfValue1: .space 4
;
PrintfFormat2: .asciiz "Output the martrixA:\n"
.align 2
PrintfPar2: .word PrintfFormat2
PrintfValue2: .space 4
;
PrintfFormat3: .asciiz "Output the martrixB:\n"
.align 2
PrintfPar3: .word PrintfFormat3
PrintfValue3: .space 4
;
PrintfFormat4: .asciiz "The result of martrix A*B:\n"
.align 2
PrintfPar4: .word PrintfFormat4
PrintfValue4: .space 4
;A 3*4
PrintfFormat5: .asciiz "martrixA is 3*4:\n"
.align 2
PrintfPar5: .word PrintfFormat5
PrintfValue5: .space 4
;B 4*2
PrintfFormat6: .asciiz "martrixB is 4*2:\n"
.align 2
PrintfPar6: .word PrintfFormat6
PrintfValue6: .space 4
;
PrintfFormat7: .asciiz "Calculation has been completed!"
.align 2
PrintfPar7: .word PrintfFormat7
PrintfValue7: .space 4
.text
.global main
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
main:
addi r11,r0,0 ;temp,表示矩阵C的一个元素的累加器
addi r4,r0,result ;r 初始化矩阵C的偏移量
addi r5,r0,0 ;l 矩阵A当前被扫描的行号
addi r1,r0,3
movi2fp f1,r1 ;矩阵A的行数
addi r1,r0,4
movi2fp f2,r1 ;n矩阵A的列数,矩阵B的行数
addi r1,r0,2
movi2fp f3,r1 ;k矩阵B的列数
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;input A
movfp2i r8,f1 ;将f1转换为整数存入r8
movfp2i r6,f2 ;将f2转换为整数存入r6
multu r4,r6,r8 ;计算矩阵A的元素总个数存入r4
addi r2,r10,dat1 ;指向A的首地址
addi r14,r0,PrintfPar5 ;输入提示信息
trap 5
loop1: ;循环输入矩阵A中的元素
add r1,r0,Prompt1 ;矩阵A元素输入提示信息
jal InputUnsigned
sb 0(r2),r1 ;将输入的r1存入r2指针位置,储存字节,读入元素
addi r2,r2,1 ;指针地址加1
sub r4,r4,1 ;总的矩阵元素个数r4减一
bnez r4,loop1 ;r4不为0时跳转重复输入
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;output A
addi r10,r0,0
addi r2,r10,dat1 ;指向A的首地址
sw PrintfValue2,r1
addi r14,r0,PrintfPar2
trap 5
loopA:
lbu r1,0(r2)
sw PrintfValue,r1
addi r14,r0,PrintfPar ;换行
trap 5
addi r2,r2,1 ;元素个数加一
sub r6,r6,1 ;矩阵A的列数r6减一
beqz r6,outputA ;矩阵A的列数r6等于0时跳到outputA
j loopA ;否则继续loopA
outputA:
sw PrintfValue1,r1
addi r14,r0,PrintfPar1
trap 5
sub r8,r8,1 ;矩阵A的行数r8减一
beqz r8,inputB ;矩阵A的行数r8等于0时跳到B1
movfp2i r6,f2
j loopA ;否则继续loopA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
inputB:
movfp2i r6,f2 ;将f2矩阵B行数转换为整数存入r6
movfp2i r12,f3 ;将f3矩阵B列数转换为整数存入r12
addi r10,r0,0 ;
multu r4,r6,r12 ;总的矩阵B的元素个数r4
addi r2,r10,dat2 ;指向B的首地址
addi r14,r0,PrintfPar6
trap 5
loop2:
addi r1,r0,Prompt2 ;分别读入矩阵B的元素值
jal InputUnsigned
sb 0(r2),r1 ;将输入的r1存入r2指针位置,储存字节,读入元素
addi r2,r2,1 ;指针地址加1
sub r4,r4,1 ;总的矩阵元素个数r4减一
bnez r4,loop2 ;r4不为0时跳转重复输入
;addi r10,r0,0 ;分别读出矩阵B的元素值
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;output B
B1:
movfp2i r6,f2
addi r2,r10,dat2 ;指向B的首地址
sw PrintfValue3,r1
addi r14,r0,PrintfPar3
trap 5
loopB:
lbu r1,0(r2)
sw PrintfValue,r1
addi r14,r0,PrintfPar ;换行
trap 5
addi r2,r2,1 ;元素个数加一
sub r12,r12,1 ;矩阵B的列数r12减一
beqz r12,outputB ;矩阵B的列数r12等于0时跳到outputB
j loopB ;否则继续loopB
outputB:
sw PrintfValue1,r1
addi r14,r0,PrintfPar1
trap 5
sub r6,r6,1 ;矩阵B的行数r6减一
beqz r6,B2 ;矩阵B的行数r6等于0时跳到countiu
movfp2i r12,f3
j loopB ;否则继续loopB
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;output B2
B2:
movfp2i r12,f3
addi r10,r0,0
movfp2i r6,f2
addi r2,r10,dat2 ;指向B的首地址
sw PrintfValue3,r1
addi r14,r0,PrintfPar3
trap 5
loopB2:
lbu r1,0(r2)
sw PrintfValue,r1
addi r14,r0,PrintfPar ;换行
trap 5
addi r2,r2,1 ;元素个数加一
sub r12,r12,1 ;矩阵B的列数r12减一
beqz r12,outputB2 ;矩阵B的列数r12等于0时跳到outputB
j loopB2 ;否则继续loopB
outputB2:
sw PrintfValue1,r1
addi r14,r0,PrintfPar1
trap 5
sub r6,r6,1 ;矩阵B的行数r6减一
beqz r6,countiue ;矩阵B的行数r6等于0时跳到countiu
movfp2i r12,f3
j loopB2 ;否则继续loopB
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
countiue:
addi r11,r0,0 ;表示矩阵C的一个元素的累加器
addi r4,r0,0 ;初始化矩阵C的偏移量
addi r5,r0,0 ;矩阵A当前被扫描的行号
line:
movi2fp f4,r5 ;判断是否扫描完
ltf f4,f1 ;f4>f1跳转(矩阵A的行是否扫描完)
bfpf finish ;是,则跳转结束程序
addi r6,r0,0 ;r6表示当前B矩阵的列号
column:
movi2fp f4,r6
ltf f4,f3 ;矩阵B的列是否扫描完
bfpf leveladd ;是,则跳到矩阵a的下一行
movfp2i r1,f2
multu r10,r5,r1 ;i<-l*n r10表示矩阵A当前行的第一个元素的索引
addi r7,r6,0 ;mov col to j(矩阵B某一列的某个元素的索引)
addi r11,r0,0 ;temp=0,矩阵C当前的元素值的初始化
addi r9,r5,1 ;r9<-l+1,r9代表矩阵A当前数组中的实际行号(r5的初值为0)
movfp2i r1,f2 ;f2是矩阵A的列数
multu r9,r1,r9 ;p<-n*(l+1),r9代表矩阵A当前行中最后一个元素在数组中的索引
calculate:
movi2fp f4,r10
movi2fp f9,r9
ltf f4,f9 ;compare i to pz(判断是否计算到当前行的最后一个元素)
bfpf asign ;当前行列相乘完毕,得出结果矩阵C的一个元素(跳转赋值)
addi r1,r10,dat1 ;取矩阵A当前元素在内存区域中的地址
lbu r2,0(r1) ;从r1所指向的内存单元中取出矩阵A当前的元素暂存在r2
addi r1,r7,dat2 ;取矩阵B当前元素在内存区域中的地址
lbu r3,0(r1) ;从r1所指向的内存单元中取出矩阵B当前的元素暂存在r3
multu r1,r2,r3 ;temp1<-dat1[i]+dat2[j]
add r11,r11,r1 ;temp<-temp+temp1,累加到累加器
addi r10,r10,1 ;i++,计算矩阵A当前行的下个元素的索引
movfp2i r1,f3
add r7,r7,r1 ;j<-j+k,计算矩阵B的当前列的下个元素的索引
j calculate
asign:
addi r1,r4,result ;r1表示矩阵C当前的地址
sb 0(r1),r11 ;store result,把新计算出来的元素放入当前内存单元
addi r4,r4,1 ;赋值完一个元素,偏移量自增1
addi r6,r6,1 ;矩阵B的当前列数自增1
j column ;矩阵B新的一列开始
leveladd:
addi r5,r5,1 ;矩阵A当前行自增1
j line ;矩阵A新的一行开始
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
finish:
addi r10,r0,0
movfp2i r8,f1 ;将矩阵A的行数亦为矩阵C的行数存入r8
movfp2i r12,f3 ;将矩阵B的列数亦为矩阵C的列数存入r12
addi r2,r10,result ;将r2指向存放结果C的首地址
sw PrintfValue4,r1
addi r14,r0,PrintfPar4
trap 5
loop3:
lbu r1,0(r2)
sw PrintfValue,r1
addi r14,r0,PrintfPar
trap 5
addi r2,r2,1 ;地址加1
sub r12,r12,1 ;列数减1
beqz r12,outputC ;当列数为0跳转outputC,否则继续循环loop3
j loop3
outputC:
sw PrintfValue1,r1 ;换行
addi r14,r0,PrintfPar1
trap 5
sub r8,r8,1 ;将行数减一
beqz r8,end1 ;当行数为0则跳转到end1,否则将列数重新传给r12,继续循环loop3
movfp2i r12,f3
j loop3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
end1:
sw PrintfValue7,r1
addi r14,r0,PrintfPar7
trap 5
sw PrintfValue1,r1 ;换行
addi r14,r0,PrintfPar1
trap 5
add r1,r0,Prompt3 ;是否重复
jal InputUnsigned
beqz r1,end2 ;为0则结束运行,否则则重复执行
j main
end2:
trap 0
原创出品,如有不足,欢迎指正