mips - 在 mips32 中打印沙漏
问题描述
我在解决这个问题时遇到问题。我想使用 mips32 打印沙漏。n
是用户输入的整数,沙漏必须按n
行打印。例如,对于n = 5
输出是:
*****
***
*
***
*****
这是我第一部分的代码(沙漏的三角形顶部)。问题是它只打印第一行星星然后退出。通过在 Mars 中逐行运行我的代码,我了解到backToLoop1
每次运行时loop3
都会运行标签的第一行!所以它会导致程序在第一行之后结束。我真的不明白为什么会这样。
.data
newLine: .asciiz "\n"
.text
main:
li $v0, 5 # read n
syscall # call sysetem
addi $t2, $v0, 0 # moves n to $t2
li $t0, 1 # i= 1
loop1:
blt $t2, $t0, Exit # if n<i exit
la $a0, newLine # go to next line
addi $v0, $0, 4 # 4 represents printing string
syscall # call system
# loop2 bounds
li $t1, 1 # k= 1
subi $t3, $t0, 1 # $t3= i-1 upper bound for loop2
# loop3 bounds
li $t5, 1 # j= 1
addi $t6, $t2, 1 # t6= n+1
sub $t6, $t6, $t0 # $t6= n+1-i upper bound for loop3
loop2:
blt $t3, $t1, loop3
li $a0, ' ' # load space to $a0
la $v0, 11 # 11 represents printing character
syscall # call system
addi $t1, $t1, 1 # k++
ble $t1, $t3, loop2 # if <= i-1 loop2 again
loop3:
blt $t6, $t5, backToLoop1 # back to loop1
li $a0, '*' # load star to $a0
la $v0, 11 # 4 represents printing character
syscall # call system
addi $t5, $t5, 1 # j++
ble $t5, $t6, loop3 # if j <= n-i+1 loop3 again
backToLoop1:
addi $t0, $t0, 1 # i++
ble $t0, $t2, loop1 # if i<=n loop1 again
blt $t2, $t0, Exit
Exit: # Terminate the program
li $v0, 10 # 10 represents exit
syscall # call system
解决方案
你有一个好的开始。但是,似乎没有明确的策略来倾斜沙漏的右侧。理想情况下,我们可以编写逻辑来处理绘制下半部分,而无需复制大部分逻辑。
对于这种模式,我的默认方法是使用两个指针,左边从 0 开始,右边从 n - 1 开始。它们代表每行星号字符的索引范围。每行迭代,递减右指针并递增左指针,本质上是在 n × n 网格上绘制“X”模式。
这种策略使我们达到了 95% 的目标。最后一步是临时交换左右指针 if ,它可以在没有太多意大利面条left > right
的情况下绘制下半部分。
.data
prompt: .asciiz "enter a number: "
.text
main:
la $a0 prompt # collect n
li $v0 4
syscall
li $v0 5
syscall
move $s3 $v0 # n
li $s0 0 # left index
move $s1 $s3 # right index = n - 1
addi $s1 $s1 -1
row_loop:
bltz $s1 exit # while right-- >= 0
li $s2 0 # column index
col_loop:
beq $s2 $s3 row_loop_done # for 0..n
# if left > right, swap temporarily
move $t0 $s0
move $t1 $s1
blt $t0 $t1 pick_char
move $t2 $t0
move $t0 $t1
move $t1 $t2
pick_char:
# '*' if left <= i <= right else ' '
blt $s2 $t0 pick_space
bgt $s2 $t1 pick_space
li $a0 42 # print '*'
j print_char
pick_space:
li $a0 32 # print ' '
print_char:
li $v0 11
syscall
addi $s2 $s2 1 # column index++
j col_loop
row_loop_done:
li $a0 10 # print newline
li $v0 11
syscall
addi $s1 $s1 -1 # right--
addi $s0 $s0 1 # left++
j row_loop
exit:
li $v0 10
syscall