0

I have a task where I need to take a number, e.g. 13002, and print it digit by digit using UART (including non-leading 0's). The UART expects that whatever it prints will go in the $s0 register but I can call it whenever I need using a jal.

This means I need to place a digit in $s0 and jump (the UART code has a jr $ra in it so it will return properly once complete.

My problem is I don't know how to iterate over the digits in the number. My approach so far is to mod the number by 10 (Because it's a decimal number represented in binary) but that gives me the digits in reverse order.

E.g. 13002 % 10 = 2 (then divide 13002 by 10, integer division will truncate the decimal), 1300 % 10 = 0, divide again by 10, 130 ...so on and so forth.

As mentioned above however, that gives me the digits in reverse order. How would I properly iterate over the number?

I wrote some pseudocode in python but it's having trouble with numbers that have 0's in them:

def iterateOverDigits(n):
    while (n >= 10):
        x = n
        i = 0
        while (x >= 10):
            x = x // 10
            i += 1
        print(x)
        x = n
        x = x % (10 ** i)
        n = x

iterateOverDigits(1302) # This prints 132
ABeeCDee
  • 13
  • 4
  • There's no simple way to get the digits in left-to-right printing order. One standard way is to store into a buffer in reverse order, then loop over the buffer. e.g. see the C code in [How do I print an integer in Assembly Level Programming without printf from the c library?](https://stackoverflow.com/a/46301894) (and x86 asm with lots of comments that you could probably translate to MIPS). It has no trouble with zeros, and you could even get leading zeros out to a fixed width if you wanted by using a loop counter instead of stopping when `x == 0` – Peter Cordes Apr 05 '20 at 06:09
  • Oh, I see the bug in your Python program. You're trying to get digits in printing order by iterating all the way to the highest digit, then removing that digit. That breaks when that highest digit is actually a leading 0. And that's horrible anyway because it's an O(n^2) number of divisions, instead of O(n). Just use some temporary storage like a normal person. The other option would be to digit-reverse a number by getting the digits in LSD-first order and accumulating a new one with `total=total*10+digit` and then dividing that one, but that's a lot of extra work to avoid O(log(n)) storage – Peter Cordes Apr 05 '20 at 06:39
  • Oops, if `n` is the number of digits, then O(n) storage (e.g. on the stack) + O(n) time for the normal way. The number of digits is O(log(value)). – Peter Cordes Apr 05 '20 at 06:47
  • I'm not sure how I could do this with just temporary storage? Part of the reason I was doing it this way is because I needed the correct order. If I did it in reverse order it's much simpler (just do n % 10 over and over again until n < 10) – ABeeCDee Apr 05 '20 at 08:58
  • Did you read the answer I linked in my first comment? Use a temporary array that you store in one order, read in the other. – Peter Cordes Apr 05 '20 at 09:50
  • Ah I see now. I guess that's the simplest approach in terms of implementation time. – ABeeCDee Apr 05 '20 at 19:16
  • Yes, and execution speed. Stack memory is normally already hot in cache, and much faster to access than a division. – Peter Cordes Apr 05 '20 at 19:18

1 Answers1

0
In [1]: def by_digit(n):
   ...:     for char in str(n):
   ...:         print(char)
   ...:         

In [2]: by_digit(120405)
1
2
0
4
0
5

In [3]: 

Change the print statement to the following to remove the newlines between each digit:

print(char, end="")
Paddy3118
  • 4,704
  • 27
  • 38
  • This question probably shouldn't have been tagged Python; the OP's real problem is implementing `str(n)` in MIPS asm to be able to iterate the digits in printing order. Notice that their `iterateOverDigits` only uses single arithmetic operations that don't require any looping (for fixed-width asm integers, on a machine like MIPS with hardware support for integer division). – Peter Cordes Apr 06 '20 at 08:32