# # program to check whether line of text is a palindrome, # ignoring all non-alphabetic characters and ignoring case. # (so, "abcba", "ab cba" and "AB cba" are all palindromes.) # .text .globl main main: # # opening linkage (save return address) # addi $sp, $sp, -4 sw $ra, 0($sp) # # prompt # la $a0, prompt li $v0, 4 # "print string" syscall syscall # # get input # la $a0, input li $a1, 100 li $v0, 8 # "read string" syscall syscall # # find newline in input and replace with '\0' # # register usage: # # $s0 pointer to start of input # $s1 pointer to end of input # la $s0, input la $s1, input # use $t0 to hold newline character li $t0, '\n' find_nl_loop: lb $t2, 0($s1) # $t2 <- next character beq $t2, $t0, find_nl_end addi $s1, $s1, 1 j find_nl_loop find_nl_end: sb $zero, 0($s1) addi $s1, $s1, -1 # $s1 now points to last character # # echo input, enclosed in double quotes # li $a0, '"' li $v0, 11 # "print character" syscall syscall la $a0, input li $v0, 4 # "print string" syscall syscall li $a0, '"' li $v0, 11 # "print character" syscall syscall # # check for palindrome: # # in semi-C-like pseudocode: # char *b = address of first character # char *e = address of last character # while (b < e) { # move b right to point to next alpha char (go to print_yes if none) # move e left to point to next alpha char (go to print_yes if none) # if (uppercase(*b) != uppercase(*e) go to print_no # ++b, --e; # } # /* if we get here, is palindrome */ # # register usage: # $s2 for b # $s3 for e addi $s2, $s0, 0 addi $s3, $s1, 0 # while (b < e) main_loop: slt $t0, $s2, $s3 # b < e ? beq $t0, $zero, print_yes # # move b right as described, setting $s4 to lowercase of character found # move_b_loop: slt $t0, $s1, $s2 # b > address of last character? bne $t0, $zero, print_yes lb $s4, 0($s2) addi $a0, $s4, 0 jal check_alpha # check and convert addi $s4, $v0, 0 bne $s4, $zero, move_b_loop_end # found alpha addi $s2, $s2, 1 # ++b j move_b_loop move_b_loop_end: # # move e left as described, setting $s5 to lowercase of character found # move_e_loop: slt $t0, $s3, $s0 # e < address of first character? bne $t0, $zero, print_yes lb $s5, 0($s3) addi $a0, $s5, 0 jal check_alpha # check and convert addi $s5, $v0, 0 bne $s5, $zero, move_e_loop_end # found alpha addi $s3, $s3, -1 # --e j move_e_loop move_e_loop_end: # # compare *b, *e # bne $s4, $s5, print_no # # ++b; --e; # addi $s2, $s2, 1 addi $s3, $s3, -1 # end of main loop j main_loop # # # print "yes" result # print_yes: la $a0, yes_string li $v0, 4 # "print string" syscall syscall j end # # print "no" result # print_no: la $a0, no_string li $v0, 4 # "print string" syscall syscall # # closing linkage (get return address and restore stack pointer) # end: lw $ra, 0($sp) addi $sp, $sp, 4 jr $ra .end main # # area for variables and constants # .data # input string input: .space 100 prompt: .asciiz "Enter a line of text:\n" yes_string: .asciiz " is a palindrome\n" no_string: .asciiz " is not a palindrome\n" # # function to check for alphabetic character and convert to lowercase # in C: # char check_alpha(char a) { # if (isalpha(a)) return to_lower(a); # else return '\0'; # } .text check_alpha: # # opening linkage (save return address and registers) # addi $sp, $sp, -4 sw $ra, 0($sp) addi $sp, $sp, -32 sw $s0, 0($sp) sw $s1, 4($sp) sw $s2, 8($sp) sw $s3, 12($sp) sw $s4, 16($sp) sw $s5, 20($sp) sw $s6, 24($sp) sw $s7, 28($sp) # use $s0 to hold argument (could probably just use $a0, but better style?) addi $s0, $a0, 0 # check for lowercase li $t0, 'a' slt $t1, $s0, $t0 # char < 'a'? bne $t1, $zero, check_alpha_not_lc li $t0, 'z' slt $t1, $t0, $s0 # char > 'z'? bne $t1, $zero, check_alpha_not_lc # lowercase found -- return it addi $v0, $s0, 0 j check_alpha_end check_alpha_not_lc: # check for uppercase li $t0, 'A' slt $t1, $s0, $t0 # char < 'A'? bne $t1, $zero, check_alpha_not_uc li $t0, 'Z' slt $t1, $t0, $s0 # char > 'Z'? bne $t1, $zero, check_alpha_not_uc # uppercase found -- return lowercase equivalent li $t0, 'A' sub $t1, $s0, $t0 # $t1 <- char - 'A' li $t0, 'a' add $s0, $t0, $t1 # $s0 <- (char - 'A') + 'a' addi $v0, $s0, 0 j check_alpha_end check_alpha_not_uc: # not alphabetic -- return null addi $v0, $zero, 0 # # closing linkage # check_alpha_end: lw $s7, 28($sp) lw $s6, 24($sp) lw $s5, 20($sp) lw $s4, 16($sp) lw $s3, 12($sp) lw $s2, 8($sp) lw $s1, 4($sp) lw $s0, 0($sp) addi $sp, $sp, 32 lw $ra, 0($sp) addi $sp, $sp, 4 # return to caller jr $ra .end check_alpha