MIPS: Aligning Output in Right Justified Columns

1.7k views Asked by At

I am taking a class about how computers function on a lower level, mostly about memory management so far. Part of it is learning to write in Assembly Language using the PCSPIM simulator for MIPS processors.

I just finished an assignment about Loops. For that, I had to write a program that prompts the User to input a number and prints the digits from 1 to that number. Print the new line character every 10 characters. It is assumed the input will be positive. I did that part no problem, program works fine.

As a bonus however I was asked to align the output into Right Justified Columns. I am stumped, I have no idea how to do it. I could figure it out in Java but I just started learning the basics of Assembly and after going over everything I learned so far in the class I realize we have not learned how to do this at all. I have had this Professor before and she likes to do this to get us thinking and see if we can figure it out without her help.

I have thought about putting all the results into an array and printing that, but I don't know how to make arrays in Assembly. I have also considered using Assembly's equivalent to IF statements but I would have to write and test one for each time a new digit is added to the number and there is no maximum number allowed for the input.

If anyone could tell me how it would be possible to print my output into Right Justified Columns I would greatly appreciate it. Here is my code so far:

###### Begin Text Section ######

    .text
    .globl __start

__start:                        # execution starts here

      la $a0,prompt     #  load address of prompt into a0
      li $v0,4          #  load instruction number to display a string into v0
      syscall           #  system call to print the prompt string

      li $v0,5              # load call code number to read first integer -> v0
      syscall               # system call to read first integer and store in v0

      move $t0,$v0          # move integer from v0 -> t0 for safe keeping
                        # t0 holds the Final Integer

      addi $t1,1        # initialize t1 to 1
                       # t1 is the counter

      addi $t2,1        # initialize t2 to 1
                       # t2 is the lineCounter

      addi $t3,10       # initialize t3 to 10
                       # t3 is the Sentinel

      la $a0,endl           # load the new line character into a0
      li $v0,4              # load the call code number to display the string into v0
      syscall               # system call to print the new line character

      move $a0,$t1      # move t1 -> a0 for display
      li $v0,1              # load call code number to display integer into v0
      syscall               # system call to print t1 as largest

      la $a0,space      #  load address of prompt into a0
      li $v0,4          #  load instruction number to display a string into v0
      syscall           #  system call to print the prompt string

WHILE:    ble $t0,$t1,ENDWHILE  # IF counter > final integer BREAK to ENDWHILE

      add $t1,$t1,1         # increment counter

      move $a0,$t1      # move t1 -> a0 for display
      li $v0,1              # load call code number to display integer into v0
      syscall               # system call to print t1 as largest

      la $a0,space      #  load address of prompt into a0
      li $v0,4          #  load instruction number to display a string into v0
      syscall           #  system call to print the prompt string

      add $t2,1             # increment lineCounter
      beq $t2,$t3,NEWLINE   # IF lineCounter = 10 BREAK to NEWLINE
      j WHILE               # go around the loop again

NEWLINE:  la $a0,endl       # display new line
          li $v0,4
          syscall

          addi $t2,-10      # re-initialize t2 to 0             

          j WHILE           # jump to WHILE

ENDWHILE: la $a0,endl       # display new line
          li $v0,4
          syscall

          li,$v0,10     #End Program
          syscall

##### End Text Section #####



##### Begin Data Section ######

        .data
prompt: .asciiz "Please enter a posetive integer: " # prompt for the Input
space:  .asciiz " "                 # Space Character
endl:   .asciiz "\n"                    # New Line Character


Example of output as the code is now:
  1 2 3 4 5 6 7 8 9 10
  11 12 13 14 15 16 17 18 19 20
  21 22 23 24 25 26 27 28 29 30
  ...92 93 94 95 96 97 98 99 100


Example of how output should look:
   1   2   3   4   5   6   7   8   9  10
  11  12  13  14  15  16  17  18  19  20
  21  22  23  24  25  26  27  28  29  30
 ...  92  93  94  95  96  97  98  99 100
1

There are 1 answers

1
nnovich-OK On BEST ANSWER

So the task is to pad output with amount of spaces depending on the length of the current value and the final value. E.g. user entered 1234, that means, that 1 should be padded with 3 additional spaces, 512 with one space and 1024 left intact.

Get length of input value

Start from 1 and multiply it by 10 in a loop until result is larger than input value while counting loop iterations. Number of iteration is equal to length of input value. Let's denote it as L.

Find necessary number of spaces

Well, naive and straight-forward way is to get length of the current value using method above and subtract it from L. However, it's a waste of resources, there is a much simpler way.

You know, that you always start with 1, so initially you need L-1 additional spaces. And you know each "milestone" number, where length of current value is incremented. So here is the way:

  • Load L-1 into register responsible for tracking number of additional spaces
  • Load 10 into register responsible for tracking milestones
  • Each time you are going to print number, do the following
    • if number equals to milestone, then decrement counter of additional spaces and multiply milestone by 10.
    • print stored number of spaces
    • print current value