Search code examples
assemblymipspalindromemars-simulator

How to pass an input string from user to a MIPS program


I'm trying to solve a problem to write assembly language program to detect if a phrase or characters entered by the user is a palindrome.

I've gotten this far, and I believe everything should work, but I'm wondering how I can implement this so that it takes an actual word to test. When I run in MARS, there's simply no input option.

.data
string_space: .space 1024
is_palin_msg: .asciiz "The string is a palindrome.\n"
not_palin_msg: .asciiz "The string is not a palindrome.\n"

.text
main: 
la $a0, string_space
li $a1, 1024
li $v0, 8
syscall

la $t1, string_space
la $t2, string_space

length_loop:
lb $t3, ($t2)
beqz $t3, end_length_loop
addu $t2, $t2, 1 
b length_loop

end_length_loop:
subu $t2, $t2, 2

test_loop:
bge $t1, $t2, is_palin

lb $t3, ($t1)
lb $t4, ($t2)
bne $t3, $t4, not_palin

addu $t1, $t1, 1
subu $t2, $t2, 1
b test_loop

is_palin: 
la $a0, is_palin_msg
li $v0, 4
syscall
b exit

not_palin:
la $a0, not_palin_msg
li $v0, 4
syscall
b exit

exit: 
li $v0, 10
syscall

I've tried

string_space: .asciiz "Enter your word:\n"

and also

string_space: .asciiz "racecar"

but I haven't quite been able to get it yet.

Any tips?


Solution

  • So - taking also as template this question here [you are strongly invited to check similar questions before posting] - you need to introduce in your code a .data section with an input string to ask the user to enter the string to check

    .data
    string_space: .space 1024
    
    input:  .asciiz "Enter a string: "
    is_palin_msg: .asciiz "The string is a palindrome.\n"
    not_palin_msg: .asciiz "The string is not a palindrome.\n"  
    # other strings you may need
    

    Then you can start setting the logic to push them out

    .text
    
    main:
        li $v0, 4              # system call code for print_str
        la $a0, input          # address of string to print
        syscall                # print the input
    
        li $v0, 8              # code for syscall read_string
        la $a0, string_space   # tell syscall where the buffer is
        li $a1, 1024           # tell syscall how big the buffer is
        syscall    
    
        # double check the buffer content [see the next snippet]
    
    # rest of the code to test      
    

    You will start asking the user a string [in this case limited to 1024 bytes/characters]. Reading the "System Calls and I/O" section of this link you will find the same prompt used in the snippet above [search "Print out string (useful for prompts)" within the page]

    The table in the same section will explain you the meaning of the li $v0, 4 and li $v0, 8 instructions. This is another good read. The same table will make you understand that before calling a print string you have to set one argument [$a0] while for the read string operation you will need two [$a0 and $a1]

    In your code the main begins with a read string operation. But please notice that string_space is used both to allocate the size of the buffer where to read from [in .data section] and for asking to enter the word [you are trying to call string_space: .asciiz "Enter your word:\n"]. This issue has been fixed by the snippets above

    In case of troubles don't forget to double check the content of your string_space buffer:

    la $a0, string_space  # move buffer into a0
    li $v0, 4             # print buffer
    syscall
    

    Complete code tested and working in MARS 4.5:

    .data
    string_space: .space 1024
    
    input:  .asciiz "Enter a string: "
    is_palin_msg: .asciiz "The string is a palindrome.\n"
    not_palin_msg: .asciiz "The string is not a palindrome.\n"
    
    .text
    main: 
    
    li $v0, 4              # system call code for print_str
    la $a0, input          # address of string to print
    syscall                # print the input
    
    la $a0, string_space
    li $a1, 1024
    li $v0, 8
    syscall
    
    #la $a0, string_space  # move buffer into a0
    #li $v0, 4             # print buffer
    #syscall
    
    la $t1, string_space
    la $t2, string_space
    
    length_loop:
    lb $t3, ($t2)
    beqz $t3, end_length_loop
    addu $t2, $t2, 1 
    b length_loop
    
    end_length_loop:
    subu $t2, $t2, 2
    
    test_loop:
    bge $t1, $t2, is_palin
    
    lb $t3, ($t1)
    lb $t4, ($t2)
    bne $t3, $t4, not_palin
    
    addu $t1, $t1, 1
    subu $t2, $t2, 1
    b test_loop
    
    is_palin: 
    la $a0, is_palin_msg
    li $v0, 4
    syscall
    b exit
    
    not_palin:
    la $a0, not_palin_msg
    li $v0, 4
    syscall
    b exit
    
    exit: 
    li $v0, 10
    syscall
    

    MARS 4.5 output

    IMPORTANT: this code logic has a bug. If you enter palindromes whose length is odd it will give the wrong result [e.g. civic is detected as a non-palindrome but actually it is]