You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RV64汇编find_smallest函数错误排查:无法正确返回数组最小元素地址

RV64汇编函数find_smallest问题排查

需求说明

需在find_smallest.s中实现RV64汇编函数find_smallest:

  • 输入:数组起始地址begin_address、结束地址end_address(end_address为有效元素后的首个地址)
  • 输出:数组中最小64位元素的首次出现地址

我编写的汇编代码

.global find_smallest
.text

# find_smallest(begin_address, end_address) -> address_of_smallest
find_smallest:
                bge a0, a1, 4f        # 如果a0 == a1(数组为空),退出
                ld t0, 0(a0) # 当前最小地址对应的值
                addi t1, a0, 0 # 存储当前最小元素的地址
                li t4, 1 # 索引值
                #addi t5, a1, -8
                

1:
                addi t4, t4, 1
                bge t1, a1, 4f
                slli t2, t4, 3
                add t2, a0, t2 # t2现在是元素地址
                bge t2, a1, 4f
            
                ld t3, 0(t2) # t3是该地址中的值
                blt t3, t0, 3f


2:
                
                j 1b
3:
                mv t0, t3
                mv t1, t2
                j 1b
                
                
4:
                mv a0, t1
                ret

测试失败输出对比

提交rv64-selection-sort步骤1进行评分
  步骤1解决方案失败
  报告卡:解析单元测试结果出错:第104行XML语法错误:非法字符编码U+001B
$ make grade
riscv64-alpine-linux-musl-as -g --warn --fatal-warnings -march=rv64im start.s -o start.o
riscv64-alpine-linux-musl-as -g --warn --fatal-warnings -march=rv64im find_smallest.s -o find_smallest.o
riscv64-alpine-linux-musl-as -g --warn --fatal-warnings -march=rv64im print.s -o print.o
riscv64-alpine-linux-musl-ld --fatal-warnings start.o find_smallest.o print.o
rm -f test_details.xml inputs/*.actual
python3 lib/grader
$ python3 lib/rv64sim -m run < inputs/test.input

!!! 输出不正确:
$ icdiff inputs/test.actual inputs/test.expected
inputs/test.actual                      inputs/test.expected
                                        查找11370到11410之间最小元素的地址
                                            ===> 11370
                                        查找11378到11410之间最小元素的地址
                                            ===> 11380
                                        查找11380到11410之间最小元素的地址
                                            ===> 11380
查找11388到11428之间最小元素的地址      查找11388到11410之间最小元素的地址
    ===> 11388
查找11390到11428之间最小元素的地址
    ===> 113b0
查找11398到11428之间最小元素的地址
    ===> 11398                              ===> 11398
                                        查找11390到11410之间最小元素的地址
                                            ===> 11398
                                        查找11398到11410之间最小元素的地址
                                            ===> 11398
查找113a0到11428之间最小元素的地址      查找113a0到11410之间最小元素的地址
    ===> 113b0                              ===> 113d8
查找113a8到11428之间最小元素的地址      查找113a8到11410之间最小元素的地址
                                            ===> 113d8
                                        查找113b0到11410之间最小元素的地址
                                            ===> 113d8
                                        查找113b8到11410之间最小元素的地址
                                            ===> 113d8
                                        查找113c0到11410之间最小元素的地址
                                            ===> 113d8
                                        查找113c8到11410之间最小元素的地址
                                            ===> 113d8
                                        查找113d0到11410之间最小元素的地址
                                            ===> 113d8
                                        查找113d8到11410之间最小元素的地址
                                            ===> 113d8
                                        查找113e0到11410之间最小元素的地址
    ===> 113f0                              ===> 113f0
查找113b0到11428之间最小元素的地址
    ===> 113b0
查找113b8到11428之间最小元素的地址      查找113e8到11410之间最小元素的地址
    ===> 113f0                              ===> 113f0
查找113c0到11428之间最小元素的地址      查找113f0到11410之间最小元素的地址
    ===> 113f0                              ===> 113f0
查找113c8到11428之间最小元素的地址      查找113f8到11410之间最小元素的地址
    ===> 113f0                              ===> 11400
查找113d0到11428之间最小元素的地址      查找11400到11410之间最小元素的地址
    ===> 113f0                              ===> 11400
查找113d8到11428之间最小元素的地址      查找11408到11410之间最小元素的地址
    ===> 113f0
查找113e0到11428之间最小元素的地址
    ===> 113f0
查找113e8到11428之间最小元素的地址
    ===> 11408                              ===> 11408
查找113f0到11428之间最小元素的地址
    ===> 113f0
查找113f8到11428之间最小元素的地址
    ===> 11408
查找11400到11428之间最小元素的地址
    ===> 11418
查找11408到11428之间最小元素的地址
    ===> 11408
查找11410到11428之间最小元素的地址
    ===> 11420
查找11418到11428之间最小元素的地址
    ===> 11418
查找11420到11428之间最小元素的地址
    ===> 11420


0/1测试通过,耗时0.72秒

代码问题分析

  1. 索引逻辑错误:初始t4设为1,第一次循环直接addi t4, t4, 1变成2,跳过了数组的第二个元素(索引1对应的地址),导致部分元素未被遍历。
  2. 终止条件错误:用当前最小元素地址t1判断bge t1, a1, 4f完全不合理,t1是最小元素的地址,和结束地址a1没有直接的遍历终止关系,会导致提前退出或者越界。
  3. 地址计算冗余且易出错:通过索引左移3位(乘8)计算地址的方式,不如直接用地址递增的方式可靠,容易出现索引和地址不匹配的问题。

修正后的代码

.global find_smallest
.text

# find_smallest(begin_address, end_address) -> address_of_smallest
find_smallest:
    bge a0, a1, 4f        # 空数组直接返回起始地址
    ld t0, 0(a0)          # 初始化当前最小值为第一个元素的值
    mv t1, a0             # 初始化当前最小值地址为起始地址
    addi t2, a0, 8        # 从第二个元素开始遍历

1:
    bge t2, a1, 4f        # 遍历到结束地址则退出循环
    ld t3, 0(t2)          # 读取当前遍历元素的值
    blt t3, t0, 3f        # 如果当前元素更小,跳转到更新逻辑
    addi t2, t2, 8        # 否则,地址加8,继续下一个元素
    j 1b

3:
    mv t0, t3             # 更新当前最小值
    mv t1, t2             # 更新当前最小值地址
    addi t2, t2, 8        # 地址加8,继续下一个元素
    j 1b

4:
    mv a0, t1             # 返回最小元素的首次出现地址
    ret

修正说明

  • 直接用地址遍历:从起始地址+8开始,每次地址加8,避免索引计算的错误,确保遍历所有有效元素。
  • 正确的终止条件:判断当前遍历地址t2是否大于等于结束地址a1,符合数组的边界定义。
  • 简化逻辑:去掉冗余的索引变量,减少出错点,代码更易读。

内容的提问来源于stack exchange,提问作者Aaron Valentine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 14:48:14