我被要求编写一个RISC-V汇编代码,以生成一个由菱形组成的对称菱形,其中间行宽度为N。N是用户输入的奇数。
例如:在终端输入5,结果应该是:
*
***
*****
***
*
字符串
由于我是一个初学者,在使用RISC-V方面相对缺乏经验,我无法完全完成这一点。
我在RARS中编写和测试的是:
# 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
型
这个程序产生的结果,例如输入5是:
*
*
*
*
*
型
它根据输入的数字正确地改变大小(例如,如果输入7,则为7行),但星星的数量始终为1,并且格式不正确。
1条答案
按热度按时间vs91vp4v1#
首先,你需要一个可以工作的算法。如果你已经有了它(比如在你的脑海里,或者用C语言,或者你很熟悉的语言),那么你需要调试它。调试的方法是单步调试,观察它在每条指令上做了什么。由于输出立即出错(它应该先打印一些空格),你马上就有东西可以调试了。
在做汇编版本之前,最好有一个使用C或你熟悉的语言的算法。(换句话说,你不必用汇编语言来开发算法。)一旦你有了算法,如果你已经知道代码应该做什么,那么汇编语言会简单得多(您需要的变量和控制流)。
如果你把一个可以工作的C代码转录成汇编语言,那么你就会知道任何错误都是汇编翻译问题,而不是算法问题,这些问题更容易调试。
当你有一个C或其他语言的算法时,你就有了一些东西可以在调试过程中进行比较,它会告诉你汇编代码到底哪里出错了。C和汇编程序都是单步执行,你会看到汇编程序哪里出错了。
你可能认为你不需要一个C版本,但让我们注意到,这将是一个3-5行的代码,它实际上是强制性的,你必须取得进展。
我建议让它在C中工作,然后把它带到C中的“if-goto-label”风格。
例如,像这样的嵌套for循环(用于打印一个简单的方阵):
字符串
仍然可以在C中转换为if-goto-label:
型
这是一个简单的嵌套for循环例子中使用的控制结构的精确转录。这个转换将运行与for循环版本相同。
正确地翻译控件结构需要一些工作,因为汇编语言会允许许多无用或错误的东西。:但请放心,每个控制流结构(if-then-else,for/while,顺序语句,嵌套语句)都有一个简单的if-goto-label模式。遵循正确的模式,汇编中的控制流将与C版本一样运行。
(It在这里,尝试在转换到汇编过程中优化某些东西是很容易的,但是要抵制这种冲动,使用简单的模式,即使它们看起来是可优化的。我的偏好是首先对C if-goto-label代码应用优化,然后如果有效,将其带到汇编。)