/*
 * @topic T0M305 MIPS assembly
 * @brief reverse string and string length using MIPS procedure
 * reverse the characters in the string
 */
.data
    .eqv SERVICE_EXIT         10
    .eqv SERVICE_PRINT_INT    1
    .eqv READ_STRING_SERVICE  8
    .eqv PRINT_STRING_SERVICE 4
    .eqv EXIT_PROGRAM_SERVICE 10
    .eqv MAX_STRING_SIZE      80
    .eqv NEWLINE              0xA # \n

input:      .space  MAX_STRING_SIZE
msg_length: .asciiz "string length is: "
prompt:     .asciiz "enter a string: "
idx_tail:   .word   0
idx_front:  .word   0

.text
    li  $v0, PRINT_STRING_SERVICE
    la  $t0, prompt
    add $a0, $t0, $zero
    syscall

    li  $v0, READ_STRING_SERVICE
    la  $t0, input
    add $a0, $t0, $zero
    li  $a1, MAX_STRING_SIZE
    syscall

    # find the length of input string:
    la $a0, input
    jal string_length
    
    # length is ready
    # at this point $t3 has the length of input
    move $s3, $t3 # preserve the length of input
    
    li  $v0, PRINT_STRING_SERVICE
    la  $t0, msg_length
    add $a0, $t0, $zero
    syscall
    
    # at this point $a0 has the length of input

    li  $v0, SERVICE_PRINT_INT
    add $a0, $s3, $zero  # load $a0
    syscall
    
    beqz $s3, exit_the_prog # empty input causes the prog to exit
                        # reverse characters in the string:
                        # 0123456789
                        # abcdef
                        # |    |
                        # |    idx_tail = input.length() - 1
                        # idx_front = 0    
    move $t0, $s3       # input.length()
    move $t1, $zero     # idx_front     
    addu $t2, $t1, $t0  # idx_tail 
    la   $t4, input     # location of character buffer
    
swap_characters:
    lb   $t5, input( $t1 ) # save front character in $t5
    lb   $t6, input( $t2 ) # save tail character in $t6
    sb   $t6, input( $t1 ) # store tail character as new front character
    sb   $t5, input( $t2 ) # store front character as new tail character
    addi $t1, $t1, 1       # increment front index
    addi $t2, $t2, -1      # decrement tail index
    slt  $t7, $t1, $t2     # if ( $t1 < $t2 ) $t7 = 1, zero otherwise
    bnez $t7, swap_characters
    
    # print the result:
    li  $v0, PRINT_STRING_SERVICE
    la  $t0, input
    add $a0, $t0, $zero
    syscall
        
exit_the_prog:
    li  $v0, SERVICE_EXIT
    syscall

# procedures


# find the length of input string:
# $a0 contains the address of the string
# $ returns result in $t3

string_length:
    addiu $sp, $sp, -20 # to preserve 5 4-byte regs
    sw $ra, 0($sp)
    sw $t1, 4($sp)
    sw $a0, 8($sp)
    sw $t2, 12($sp)
    sw $t4, 16($sp)

    move $t4, $a0       # $t4 = address of the string
    move $t3, $zero     # $t3 = index of character
    li   $t1, NEWLINE
    
compare_char_2_newline:
    addu $a0, $t4, $t3 # addr of a char = address of the string + index of character
    lb   $t2, 0($a0)   # load next char from input string
    beq  $t1, $t2, length_is_ready # compare char with \n
    addi $t3, $t3, 1 # increment index
    j compare_char_2_newline
    
length_is_ready:
    lw $ra, 0($sp)
    lw $t1, 4($sp)
    lw $a0, 8($sp)
    lw $t2, 12($sp)
    lw $t4, 16($sp)
    addiu $sp, $sp, 20
   jr $ra # return back to the caller
# string_length ends