简体   繁体   中英

Printing an hourglass in mips32

I'm having problems solving this question. I want to print an hourglass using mips32. n is an integer given by user as input and the hourglass must be printed in n lines. For example, for n = 5 the output is:

                *****
                 ***
                  *
                 ***
                *****

Here is my code for the first part (the triangle top of the hourglass). The problem is that it prints only the first line of stars and then exits. By running my code line by line in Mars, I understood that the first line of the backToLoop1 label is run every time loop3 is run. So it causes the program to end after the first line. I really can't realize why this happens.

.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

You're off to a good start. However, there doesn't appear to be a clear strategy for slanting the right side of the hourglass. Ideally we can write logic to handle drawing the bottom half without duplicating most of the logic.

My default approach for this sort of pattern is to use two pointers, a left starting at 0 and right starting at n - 1. These represent the index bounds for the asterisk characters for each row. Per row iteration, decrement the right pointer and increment the left pointer, essentially drawing an "X" pattern on the n by n grid.

This strategy gets us 95% of the way there. The last step is to temporarily swap the left and right pointers if left > right , which handles drawing the bottom half without too much spaghetti.

.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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM