.global fmt_decimal .global count_digits .extern clz .extern divmod .section .rodata hexchars: .ascii "0123456789ABCDEF" powers10: .word 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 .set powers10_end, . .text # Write decimal representation of word into buffer # arguments: # a0: value to format # a1: address of buffer to write to # buffer must have room for at least 10 bytes # temporaries used: # t0 # return: # a0: length of string written to buffer fmt_decimal: # until the value is zero: # divmod value by 10 # write remainder to output buffer as ASCII char # increment string length # subtract remainder from value # if we can know how many digits there will be up front we can write to the buffer # in the right order, if not the buffer will have to be reversed at the end addi sp, sp, -16 sw ra, 12(sp) sw s1, 8(sp) sw s0, 4(sp) mv s0, a0 # save value in a0 to s0 mv s1, a1 # save buffer address to s1 jal count_digits sw a0, 0(sp) # save digit count to return at the end addi a0, a0, -1 # a0 -= 1 add s1, s1, a0 # add the digit count to the buffer address 1: mv a0, s0 # load dividend from s0 li a1, 10 # set divisor to 10 jal divmod # divmod value by 10, a1 = remainder mv s0, a0 # move quotent to s0 addi a1, a1, 0x30 # turn remainder into ASCII digit sb a1, 0(s1) # write the digit to the output buffer addi s1, s1, -1 # decrement buffer address bnez s0, 1b lw a0, 0(sp) # load digit count into a0 lw s0, 4(sp) lw s1, 8(sp) lw ra, 12(sp) addi sp, sp, 16 ret # Calculate number of decimal digits input word has. # arguments: # a0: value to count # return: # a0: count of decimal digits count_digits: mv a2, a0 # a2 = value la a1, powers10 # a1 = powers10 la a4, powers10_end # a4 = powers10_end li a0, 0 # a0 = powers array offset * 4 1: bgeu a1, a4, 2f # if a1 >= powers10_end return 10 lw a3, 0(a1) # a3 = load value from powers array addi a0, a0, 1 # increment offset bltu a2, a3, 3f # if a2 < a3 return addi a1, a1, 4 # a1 = index into powers array j 1b # loop 2: li a0, 10 3: ret