Skip to main content
Logo image

Section 3.1 Number Conversion

The first example strengthens our skills in some low-level bit fiddling. We have already seen that we can use a simple sys call (see Section A.2) to print the contents of a register in decimal numbers. In this section, we want to write a procedure that prints the 32-bit contents of a register hexadecimally. To this end, we recall that one hexadecimal digit can represent exactly four bits. So a 32-bit register content can nicely be represented by 8 hexadecimal digits.
The idea for our program is to extract four-bit packets out of the register from most significant to least significant, one after another. For each “packet”, we convert the four bits into the respective ASCII code 5  of the character of the hexadecimal digit and print it.
For example, the four bits 1011 represent the number 11 and have the hexadecimal digit b. The ASCII code for the letter “b” is 98.
A brief look into an ASCII table reveals that the ASCII codes of decimal digits start at 48 and lower-case letters start at 97.
Let us focus first on the code that extracts the four bits and converts them into the ASCII character of the corresponding hexadecimal digit.
loop:
     srl   t2, t0, t1
     andi  t2, t2, 15
     sltiu t3, t2, 10
     bnez  t3, smaller10
     addi  t2, t2, 55
 smaller10:
     addi  t2, t2, 48
We assume here that the word to print is in register t0. The first instruction is a shift that shifts the word to print down by t1 bits. $t1 is supposed to index the four bit packets in the word and will assume the values 28, 24, 20, ..., 0 during the course of execution. To this end we will setup a loop later. Now, the shifts brings the four bits to be printed “down” so that the least significant bit of the packet is at bit position 0 of a0. Since there may be several set bits in t0 above the four bits we want to print, we need to clear all bits beyond bit 3 by and-ing with 15. Now, a0 contains the four bits to print with the LSB at position 0.
The remaining code checks, if the four bits represent a value smaller than 10 in which case we want to compute the ASCII code of the corresponding decimal digit. This is done by the addi instruction labelled smaller10. The branch at line 13 branches there if the four bits are smaller 10. If this is not the case, the branch “falls through” and the addi with 39 is also executed. In that case, a0 contains a value \(x\) between 10 and 15 (including) and \(39+48+x=87+x\) which gives the ASCII code for the lower-case hexadecimal letter representing the values between 10 and  15.
Finally, we put a loop around this piece of code to iterate through all packets in $t0. The following listing shows the final version of the code with some main routine to test it.
     .data
msg:
  .asciiz "Enter a number: "
    .text
print_hex:
    mv    t0, a0
    li    t1, 28
    li    a0, 11
loop:
    srl   t2, t0, t1
    andi  t2, t2, 15
    sltiu t3, t2, 10
    bnez  t3, smaller10
    addi  t2, t2, 55
smaller10:
    addi  t2, t2, 48
    mv a1 t2
    ecall
    addi  t1, t1, -4
check:
    bgez  t1, loop
    ret

main:
    .globl main
    la    a1, msg
    li    a0, 4
    ecall
    li    a0, 5
    ecall
    call  print_hex
    li    a0, 10
    ecall