# Print a number in any base without help

[Courses](https://asm-editor.specy.app/learn/courses.md) › [MIPS assembly](https://asm-editor.specy.app/learn/courses/mips.md) › Examples

Web page: https://asm-editor.specy.app/learn/courses/mips/examples/number-to-string

> Repeated division for the digits, a buffer filled backwards from its end, and the same number printed in base 16, 10 and 2.

The same program in: [M68K](https://asm-editor.specy.app/learn/courses/m68k/examples/number-to-string.md), [RISC-V](https://asm-editor.specy.app/learn/courses/risc-v/examples/number-to-string.md), [Z80](https://asm-editor.specy.app/learn/courses/z80/examples/number-to-string.md), [x86-64](https://asm-editor.specy.app/learn/courses/x86/examples/number-to-string.md)

This program prints 48879 in three bases: `BEEF` in base 16, `48879` in base 10, and
`1011111011101111` in base 2. The `print_in_base` subroutine makes the digits itself, stores them
as a string, and asks service 4 to print that string.

Pass a nonnegative signed 32-bit integer (0 through 2147483647) in `$a0` and a base from 2 through
36 in `$a1`. The subroutine prints the number followed by a newline. It changes `$a0`, `$t0`,
`$t1`, `$v0`, `hi`, and `lo`; callers that need those old values must save them. Bases below 2 are
invalid for this loop: division by zero has no answer, and dividing a positive number by 1 never
makes it smaller.

```mips
.data
buffer:     .space 34       # room for 31 binary digits, a zero, and two spare bytes
buffer_end:
newline:    .asciiz "\n"

.text
.globl main

# print_in_base(n, base): n in $a0, base in $a1
print_in_base:
    la $t0, buffer_end      # build the text backwards from the end
    addi $t0, $t0, -1
    sb $zero, 0($t0)        # the terminator goes down first
digit:
    div $a0, $a1            # n / base in lo, n % base in hi
    mfhi $t1                # the digit
    mflo $a0                # n = n / base
    blt $t1, 10, number
    addi $t1, $t1, 55       # 'A' is 65, so a 10 becomes 'A'
    j store
number:
    addi $t1, $t1, 48       # '0' is 48, so a 0 becomes '0'
store:
    addi $t0, $t0, -1       # next free byte before the digits already stored
    sb $t1, 0($t0)
    bnez $a0, digit         # until nothing is left of n
    li $v0, 4               # service 4: print the string that was built
    move $a0, $t0
    syscall
    li $v0, 4
    la $a0, newline
    syscall
    jr $ra

main:
    li $a0, 48879
    li $a1, 16              # in hexadecimal
    jal print_in_base
    li $a0, 48879
    li $a1, 10              # in decimal
    jal print_in_base
    li $a0, 48879
    li $a1, 2               # in binary
    jal print_in_base
    li $v0, 10
    syscall
```

The console shows:

```text
BEEF
48879
1011111011101111
```

Dividing by the base and keeping the remainder gives you one digit, and it is the **lowest** one:
48879 divided by 16 is 3054 with 15 left over, and 15 is the `F` at the right hand end of `BEEF`. So
the digits arrive rightmost first. This program stores them from the end of the buffer toward its
beginning, leaving them in the order service 4 must print.

`div` is exactly the right instruction for this, because one pass of the loop needs both of its
answers: the remainder is the digit and the quotient is what you carry on dividing. One `div`, one
`mfhi` and one `mflo`, and the pass has everything it needs.

`sb` writes one character byte at a time. The `addi` before it moves `$t0` to the next free byte;
`sb` itself does not move the pointer. At the end, `$t0` points to the first digit. Service 4
starts there and prints bytes until it reaches the zero terminator placed at the end.

A digit is a number from 0 to `base - 1` and it has to become a character. `'0'` is 48, so adding it
turns 0 to 9 into `'0'` to `'9'`; `'A'` is 65 and a 10 has to become that, so the amount added
is 55. This assembler does not accept `'A' - 10` as the operand here, so the code uses 55 and
explains it in the comment. `blt $t1, 10, number` picks between numbers and letters, allowing
digits up to `Z` for base 36.

`bnez $a0, digit` checks the quotient copied into `$a0` by `mflo`. When that quotient reaches zero,
there are no more digits to make. The loop still runs once for input zero: `0 / base` gives a zero
remainder, so it stores one `0` character before stopping.

The longest input in the stated range, 2147483647, takes 31 binary digits. The last byte of
`buffer` holds the zero terminator. Up to 31 bytes before it hold digits, and two bytes at the
beginning remain unused. For the 16-digit binary result shown above, `$t0` ends at
`buffer_end - 17`: 16 digits followed by the terminator.

Predict the third line if you change its base from 2 to 36. Select **Open in editor**, make the
change, then **Build** and **Run**: it should print `11PR`. Base 36 is the limit because the routine
has characters for ten decimal digits and 26 letters.

Now change that third call to pass 0 in `$a0` and base 16 in `$a1`. Predict how many characters the
loop stores, then **Build** and **Run**. The third line should be a single `0`. Try 255 in base 16
as another check; the third line should be `FF`.

## Instructions in this Lecture

- MIPS: [`la`](https://asm-editor.specy.app/documentation/mips/instruction/la.md), [`addi`](https://asm-editor.specy.app/documentation/mips/instruction/addi.md), [`sb`](https://asm-editor.specy.app/documentation/mips/instruction/sb.md), [`div`](https://asm-editor.specy.app/documentation/mips/instruction/div.md), [`mfhi`](https://asm-editor.specy.app/documentation/mips/instruction/mfhi.md), [`mflo`](https://asm-editor.specy.app/documentation/mips/instruction/mflo.md), [`blt`](https://asm-editor.specy.app/documentation/mips/instruction/blt.md), [`j`](https://asm-editor.specy.app/documentation/mips/instruction/j.md), [`bnez`](https://asm-editor.specy.app/documentation/mips/instruction/bnez.md), [`li`](https://asm-editor.specy.app/documentation/mips/instruction/li.md), [`move`](https://asm-editor.specy.app/documentation/mips/instruction/move.md), [`syscall`](https://asm-editor.specy.app/documentation/mips/instruction/syscall.md), [`jr`](https://asm-editor.specy.app/documentation/mips/instruction/jr.md), [`jal`](https://asm-editor.specy.app/documentation/mips/instruction/jal.md)

Previous: [Read two numbers and print their sum](https://asm-editor.specy.app/learn/courses/mips/examples/sum-of-two-numbers.md)

Next: [Drawing shapes on the screen](https://asm-editor.specy.app/learn/courses/mips/examples/drawing-on-the-screen.md)
