Krewie
Krewie

Reputation: 135

Saving integers as Strings in MIPS

I was just wondering, is there any way in MIPS to store a summation of numbers as a string and later read them byte by byte, for example:

the sum 657 -> sw into a .ascii directive -> later lb on the first index to get 6 (in ascii code) same with 5 and so on. Is this possible?

Upvotes: 1

Views: 13852

Answers (3)

Erik Eidt
Erik Eidt

Reputation: 26646

Here's another implementation, factored into utoa for unsigned integers, and itoa for signed integers that uses utoa.  These provide two return values, one is the address of the string to print, and the other is a count of the number of characters in the string to print — this count is helpful when using file I/O syscalls.  The string buffer (of at least 12 characters in length) is passed in as parameter, so can be a global, or on the stack as the test main illustrates.

    .text
    j main      # jump around functions, start at main for testing itoa

# function utoa ( unsigned int, char* ) returns struct { char *, int }
# a0, unsigned number to convert to sring
# a1, pointer to free space large enough to hold integer as string (at least 11 bytes)
# v0, pointer to the beginning of the converted string
# v1, count of number of characters in the string
utoa:
    addiu $a1, $a1, 11  # move to the end of the buffer
    sb $0, ($a1)        # null terminator (sometimes helpful not always necessary)

    li $t0, 10
    li $v1, 0

utoaLoop:
    div $a0, $t0        # divide by 10
    mfhi $t2            # remainder is digit to print
    addiu $a1, $a1, -1  # back up one byte's worth
    addi $t2, $t2, '0'  # convert numeric digit to ascii digit
    sb $t2, ($a1)       # store in buffer
    addi $v1, $v1, 1    # increment counter of how many characters
    mflo $a0            # capture quotient
    bnez $a0, utoaLoop  # quotient not zero, so repeat to get another digit

        
    move $v0, $a1       # return pointer to start of character string
                           # note: $v1 holds count of number of characters in string
                           # the string is null terminated (but the null is not counted)
    jr $ra

# function itoa ( int, char* ) returns struct { char *, int }
# a0, signed number to convert to sring
# a1, pointer to free space large enough to hold integer as string (at least 12 bytes)
# v0, pointer to the beginning of the converted string
# v1, count of number of charactes in the string
# itoa calls utoa (using tco if the number is positive),
#      and otherwise prepends a '-' to the string.
itoa:
    bltz $a0, ineg
    j utoa              # tail call optimization
ineg:
    addiu $sp, $sp, -4  # space for our return address
    sw $ra, ($sp)
    neg $a0, $a0        # negate number and convert as unsigned
    jal utoa
    addiu $v0, $v0, -1  # prepend a '-' character
    li $t0, '-'
    sb $t0, ($v0)
    addi $v1, $v1, 1    # and increment character count
    lw $ra, ($sp)
    addiu $sp, $sp, 4
    jr $ra

# a simple main for testing itoa
main:
    addiu $sp, $sp, -64 # create some stack space

    li $a0, 1234        # number to print
    move $a1, $sp   
    jal itoa
    move $a0, $v0       # return 1: where to print
    move $s0, $v1       # return 2: how many chars to print
    
    li $v0, 4
    syscall
    
    li $a0, '\n'
    li $v0, 11
    syscall
    
    move $a0, $s0
    li $v0, 1
    syscall
    
    li $a0, '\n'
    li $v0, 11
    syscall

    li $a0, -1234
    move $a1, $sp
    jal itoa
    move $a0, $v0   # return 1: address of string to print
    move $s0, $v1   # return 2: how many chars to print

    li $v0, 4
    syscall
    
    li $a0, '\n'
    li $v0, 11
    syscall
    
    move $a0, $s0
    li $v0, 1
    syscall
    
    li $a0, '\n'
    li $v0, 11
    syscall

    li $v0, 10
    syscall

Upvotes: 0

ShinTakezou
ShinTakezou

Reputation: 9671

Of course. The ".ascii" directive is none but a .byte directive focused on the storage of ASCII text

   .ascii "PP"

is like

   .byte 80,80

You can use .space to make room for your ASCII string, and then use the buffer in the convertion from integer to ASCII, if you mean this by "sw into .ascii directive" of in integer. The following code converts the "binary number" into a ASCII string using itoa and prints it (just for testing) with print_string. The function uses a buffer and returns the pointer to the first ASCII digit usable for printing. This could be used as a first helper function for a sprintf-like function implementation.


       .data

buffer:
         .space 32


      .text
      # the main supposes env. like spim or MARS
main:
      li   $a0, 1234      # a number
      jal  itoa
      move $a0, $v0
      li   $v0, 4         # print_string    
      syscall
      li   $v0, 10
      syscall             # exit

itoa:
      la   $t0, buffer+30  # pointer to almost-end of buffer
      sb   $0, 1($t0)      # null-terminated str
      li   $t1, '0'  
      sb   $t1, ($t0)     # init. with ascii 0
      li   $t3, 10        # preload 10

      slt  $t2, $a0, $0   # keep the sign
      beq  $a0, $0, iend  # end if 0
      bgtz $a0, loop
      neg  $a0, $a0       # absolute value (unsigned)
loop:
      div  $a0, $t3       # a /= 10
      mflo $a0
      mfhi $t4            # get remainder
      add  $t4, $t4, $t1  # convert to ASCII digit
      sb   $t4, ($t0)     # store it
      subu  $t0, $t0, 1   # dec. buf ptr
      bne  $a0, $0, loop  # if not zero, loop
      addiu $t0, $t0, 1   # adjust buf ptr
iend:
      beq  $t2, $0, nolz  # was < 0?
      addiu $t0, $t0, -1
      li   $t1, '-'
      sb   $t1, ($t0)
nolz:
      move $v0, $t0      # return the addr.
      jr   $ra           # of the string

After you have $v0 in the main, lb R, ($v0) picks "1", lb R, 1($v0) picks second digit (2) and so on; remember the string is null-terminated, so if you pick 0 (numeric), you have to stop

Upvotes: 2

sjchin
sjchin

Reputation: 21

I believe there is a flaw in ShinTakezou's answer. The line neg $a0, $a0 will convert the positive number to negative, which results in a weird output for the code. If we remove this line. The codes work fine for positive integer

Upvotes: 2

Related Questions