如何修改RISC-V汇编代码生成中间行宽度为N的对称菱形?
修复RISC-V汇编代码以生成对称菱形
需求说明
编写RISC-V汇编代码,生成由星号组成的对称菱形,其中中间行宽度为用户输入的奇数N。例如输入5时,预期输出:
* *** ***** *** *
现有问题
现有代码在RARS中测试时,输入5仅输出每行1个星号,格式错误,但行数随输入数字正确变化。实际输出:
* * * * *
现有代码
# CONST .eqv SYSTEM_EXIT, 93 .eqv SYSTEM_READ, 63 .eqv SYSTEM_WRITE, 64 .eqv STDIN, 0 .eqv STDOUT, 1 # DATA .data space: .asciz " " asterisk: .asciz "*" newline: .asciz "\n" in_buffer: .space 16 # TEXT .text .global _start _start: li a0, STDIN la a1, in_buffer li a2, 16 li a7, SYSTEM_READ ecall la a1, in_buffer li t0, 0 li t1, 10 convert_input: lbu t2, 0(a1) beqz t2, input_done beq t2, t1, input_done sb t2, 0(a1) addi t2, t2, -48 mul t0, t0, t1 add t0, t0, t2 addi a1, a1, 1 j convert_input input_done: andi t3, t0, 1 beqz t3, not_odd li t4, 0 li t5, 0 diamond_outer_loop: bge t4, t0, end_pattern li t6, 0 print_spaces_before_asterisks: blt t5, t0, check_asterisks j next_row check_asterisks: bge t5, t6, print_asterisks j inc_space print_asterisks: li a0, STDOUT li a2, 1 la a1, asterisk li a7, SYSTEM_WRITE ecall addi t6, t6, 2 j next_asterisk inc_space: li a0, STDOUT li a2, 1 la a1, space li a7, SYSTEM_WRITE ecall addi t5, t5, 1 j print_spaces_before_asterisks next_asterisk: li a0, STDOUT li a2, 1 la a1, newline li a7, SYSTEM_WRITE ecall addi t4, t4, 1 addi t5, t5, -1 j diamond_outer_loop next_row: li a0, STDOUT li a2, 1 la a1, newline li a7, SYSTEM_WRITE ecall addi t5, t5, 2 j diamond_outer_loop not_odd: addi t0, t0, -1 end_pattern: li a0, 0 li a7, SYSTEM_EXIT ecall
修改后的代码
# CONST .eqv SYSTEM_EXIT, 93 .eqv SYSTEM_READ, 63 .eqv SYSTEM_WRITE, 64 .eqv STDIN, 0 .eqv STDOUT, 1 # DATA .data space: .asciz " " asterisk: .asciz "*" newline: .asciz "\n" in_buffer: .space 16 # TEXT .text .global _start _start: li a0, STDIN la a1, in_buffer li a2, 16 li a7, SYSTEM_READ ecall la a1, in_buffer li t0, 0 li t1, 10 convert_input: lbu t2, 0(a1) beqz t2, input_done beq t2, t1, input_done addi t2, t2, -48 mul t0, t0, t1 add t0, t0, t2 addi a1, a1, 1 j convert_input input_done: andi t3, t0, 1 beqz t3, not_odd # 如果输入是偶数,减1变成奇数 # 计算初始空格数:(N-1)/2 li t1, 2 sub t5, t0, 1 div t5, t5, t1 # t5 = 初始空格数 li t6, 1 # t6 = 当前行星号数,初始为1 li t4, 0 # t4 = 当前行数计数器 diamond_outer_loop: bge t4, t0, end_pattern # 行数达到N时退出 # 打印前置空格 li t7, 0 print_spaces: bge t7, t5, print_asterisks li a0, STDOUT la a1, space li a2, 1 li a7, SYSTEM_WRITE ecall addi t7, t7, 1 j print_spaces # 打印星号 print_asterisks: li t7, 0 print_asterisk_loop: bge t7, t6, print_newline li a0, STDOUT la a1, asterisk li a2, 1 li a7, SYSTEM_WRITE ecall addi t7, t7, 1 j print_asterisk_loop # 打印换行 print_newline: li a0, STDOUT la a1, newline li a2, 1 li a7, SYSTEM_WRITE ecall # 更新参数:前半部分(到中间行)空格减1,星号加2;后半部分空格加1,星号减2 li t1, 2 div t8, t0, t1 # t8 = 中间行索引(N//2) blt t4, t8, update_upper bgt t4, t8, update_lower # 中间行不更新,直接进入下一行 j next_row update_upper: addi t5, t5, -1 addi t6, t6, 2 j next_row update_lower: addi t5, t5, 1 addi t6, t6, -2 j next_row next_row: addi t4, t4, 1 j diamond_outer_loop not_odd: addi t0, t0, -1 # 偶数转奇数 j input_done # 重新进入处理逻辑 end_pattern: li a0, 0 li a7, SYSTEM_EXIT ecall
修改要点说明
- 初始参数修正:计算初始空格数为
(N-1)/2,初始星号数为1,匹配菱形第一行的格式要求。 - 循环逻辑重构:拆分出独立的空格打印循环和星号打印循环,避免原代码中条件判断混乱导致的打印错误。
- 参数更新逻辑修复:根据当前行数与中间行的位置关系,分别调整参数:前半部分每行空格数减1、星号数加2;后半部分每行空格数加1、星号数减2,保证菱形对称。
- 偶数输入处理优化:将偶数输入转为奇数后,重新进入处理逻辑,确保后续流程正确执行。
内容的提问来源于stack exchange,提问作者Preatorius
相关产品推荐
相关产品推荐

