实验-实现向量点积-RISC-V(计算机组成原理)
目录
一、实验内容
二、实验步骤
三、源代码
四、实现效果
五、实验环境
六、实验小结与思考
一、实验内容
首先,我们用一个简单的“向量点积”运算作为热身。你将拿到一个不完整的汇编代码“task2-向量点积”,我们的目标是按照C语言描述的功能:
并在相应的地方补充完整汇编代码。
二、实验步骤
(1)首先我们在dot_product标签下面,根据提示,写入我们的代码。
(2)如果计数器为0,则结束循环:在这里我们需要用到比较相等则跳转的操作码beq。t3寄存器中保存着向量长度n的数值,在向量A、B的值还没读取完成时,(即n还没变成0时),都要在循环内部。 beq t3, x0, finish;表示如果t3寄存器里的数据为0,则跳转到finish标签。
(3)然后我们用lw操作码,将t1中的第一个数据(向量A的第一个数据)加载到t4寄存器中。将t2中的第一个数据(向量B的第一个数据)加载到t5寄存器中。
(4)用mul操作码将t4和t5中的数据保存到t6中。
(5)将t0的值与t6相加,传给t0。
(6)将t1和t2的值自加4,使得更新为A、B的下一元素。
(7)t3减一(n减一)
(8)跳回循环开始
三、源代码
# 样例代码说明:完成两个向量的点积
#
# 该样例代码完成的功能为:
# int dotProduct(int n, int vecA[], int vecB[]) {
# int sum = 0;
# for (int i = 0; i < n; i++) {
# sum += vecA[i] * vecB[i];
# }
# return sum;
# }.data
vecA: .word 1, 2, 3, 4, 5, 6 # 定义向量A
vecB: .word 8, 7, 6, 5, 4, 3 # 定义向量B
n: .word 6 # 向量的长度
C: .space 4 # 地址C存放向量点积的结果.text
main:add t0, x0, x0 # 初始化点积结果 sum = 0la t1, vecA # 加载向量A的地址la t2, vecB # 加载向量B的地址la t3, n # 加载n的地址la a3, C # 将变量C的地址保存在 a3 寄存器当中lw t3, 0(t3) # 获取向量的长度 ndot_product:beq t3, x0, finish # 如果计数器为0,则结束循环lw t4, 0(t1) # 加载vecA的当前元素lw t5, 0(t2) # 加载vecB的当前元素mul t6, t4, t5 # 计算当前元素的乘积add t0, t0, t6 # 将乘积累加到结果中addi t1, t1, 4 # 更新vecA的地址,指向下一个元素addi t2, t2, 4 # 更新vecB的地址,指向下一个元素addi t3,t3,-1 # 递减计数器j dot_product # 跳回循环开始finish:# 将c的值存至存储器中#下面是打印输出代码,如果你使用的寄存器不一样,需要根据实际情况改变addi a0, x0, 1 # 设置ecall参数,执行打印整数addi a1, t0, 0 # 设置要打印的整数值ecall # 打印整数 ecalladdi a0, x0, 10 # 设置ecall参数,执行终止程序ecall # 终止程序 ecall
四、实现效果
五、实验环境
Venus仿真器(https://venus.cs61c.org/)
六、实验小结与思考
1.问题与解决
问题:循环条件设置错误,导致程序无法正常终止
解决:改用beq
指令判断计数器是否为0,确保循环正确退出
2.主要收获
通过本次实验,我深刻体会到规范编码的重要性。例如,在循环体和跳转标签处添加详细注释,便于后续调试和修改。此外,遵循寄存器使用规范(如t0-t6用于临时存储,a0-a3用于参数传递)使程序逻辑更清晰。
掌握RISC-V循环与数组访问实现
理解高级语言到汇编的转换逻辑