/*
 * @topic T0M296 Reverse string demo
 * @brief Reverse characters in MIPS assembly
*/

# define constants
.eqv print_string_service 4
.eqv read_string_service 8
.eqv exit_program_service 10
.eqv buffer_size 80

# data segment begins
    .data
# reserve some space for the prompts and user input
prompt_4_input:
   .asciiz "Enter text to reverse\n"

prompt_input_is_empty:
   .asciiz "Input is empty, nothing to do."

user_input:
    .space buffer_size

# code segment begins
    .text
# get user input
    addi $v0, $zero, print_string_service
    la $a0, prompt_4_input
    syscall

    addi $v0, $zero, read_string_service
    la $a0, user_input
    addi $a1, $zero, buffer_size
    syscall

# the head of the input is user_input
    la $s0, user_input # head of input

# find the tail of the input
    la $s1, user_input # tail of input
    addi $t2, $zero, '\n' # $t2 has encoding of newline
SEARCH_4_NULL_CHAR:
    lb $t1, 0($s1)     # load tail byte $t1
    beq $t1, $zero, NULL_CHAR_FOUND
    beq $t1, $t2, NEWLINE_CHAR_FOUND
    addi $s1, $s1, 1 # increment the tail pointer
    j SEARCH_4_NULL_CHAR

NEWLINE_CHAR_FOUND:
NULL_CHAR_FOUND:
    # $s0 is the head
    # $s1 is the tail ( pointing to null character )

# check whether the input is empty
    bne $s0, $s1, INPUT_IS_NON_EMPTY
    # yes, the input is an empty string:
    addi $v0, $zero, print_string_service
    la $a0, prompt_input_is_empty
    syscall
    j EXIT_PROGRAM
    
INPUT_IS_NON_EMPTY:    
# in a loop, swap characters using registers $s0 and $s1 as
# memory addresses of the characters at the head and tail:
#       $s0->head
#       $s1->tail

    subi $s1, $s1, 1 # step back from end of input to the last char

START_REVERSE_LOOP:
    bgeu $s0, $s1, REVERSE_DONE # if ( $s0 >= $s1) no more chars to swap
    lb $t0, 0($s0)      # get head character
    lb $t1, 0($s1)      # get tail character
    # swap characters:
    sb $t0, 0($s1)      # store head character at tail
    sb $t1, 0($s0)      # store tail character at the head
    
    addi $s0, $s0, 1    # move forward the head
    subi $s1, $s1, 1    # move the tail backward
    
    j START_REVERSE_LOOP
    
REVERSE_DONE:
# show the result
    addi $v0, $zero, print_string_service
    la $a0, user_input
    syscall
    
EXIT_PROGRAM:
    addi $v0, $zero, exit_program_service
    syscall