我正在上一个计算机组织课程,通过MIPS Assembly教授计算机的低级功能。家庭作业的一个问题是回文检查。这是:
写一个MIPS函数(称为“回文”),如果是,则返回1 输入字符串是回文并且否则返回0。的地址 字符串将在$ a0中传递,值应返回 $ V0。这里的字符串是回文,如果它在向前或者中读取相同的字符串 向后方向(包括空格,标点符号等) on,但不区分大小写(即“A”和“a”被认为是 相同))。请注意,字符串以“\ 0”结尾(C / C ++约定)。您 需要使用“test_palindrome.s”来测试你的程序
我写了一个简单的c ++程序来解决这个问题,包括一个基本的tolower函数。然后我手动将其翻译为mips。我已经让它运行,但是使用我的c ++程序对mips程序检查回文测试字符串,我得不到相同的结果。
为了测试mips功能,我正在使用教授提供的程序。它说没有一个是回文。这是MIPS代码,有一个注释部分显示我原来的c ++代码。
# Program to test if a palindrome function works properly or not
# Written by Xiuwen Liu for CDA 3100 - Homework #3, problem #2
# Register usage
# $s7 - save $ra
# $s2 - current address of the string to be tested
# $s3 - the next of the last string to be tested
# $a0 - for function parameter / syscall parameter
# $v0 - syscall number / function return value
.text
.globl main
main:
addu $s7, $ra, $zero, # Save the ra
la $s2, test_str # Load the starting address of the array
la $s3, is_pali_msg, # the next of last address
pali_test_loop:
lw $a0, 0($s2) # $a0 is the address of the string
li $v0, 4 # system call to print a string
syscall # print string
li $v0, 4 # print a new line
la $a0, newline
li $v0, 4
syscall
lw $a0, 0($s2) # $a0 is the address of the string
jal palindrome # call palindrome
beq $v0, $zero, pali_no #if $v0 is 0, it is not a palindrome
li $v0, 4 #it is a palindrome
la $a0, is_pali_msg
syscall
j pali_test_end
pali_no: #it is not a palindrome
li $v0, 4
la $a0, not_pali_msg
syscall
pali_test_end:
li $v0, 4
la $a0, newline
syscall
addiu $s2, $s2, 4
lw $a0, 0($s2)
beq $a0, $s3, pali_done
j pali_test_loop
pali_done:
li $v0, 10
syscall
addu $ra, $zero, $s7 #restore $ra since the function calles
#another function
jr $ra
add $zero, $zero, $zero
add $zero, $zero, $zero
########## End of main function #########
所以这是我的代码:
# My working c++ code
# int arrayLen ( char s[]) {
# int counter = 0;
# while(s[counter] != '\0'){
# if (s[counter] > 64 && s[counter] < 91)
# s[counter] = s[counter] + 32;
# counter++;
# }
# return counter;
# }
#
# int palindrom(char s[]){
# int i;
# int l = arrayLen(s);
# for(i=0;i<=l/2;i++)
# if(s[i]!=s[l-i-1]) return 0;
# return 1;
# }
palindrome:
addu $s4, $ra, $zero # save $ra
jal arrayLen # get string length and set to lowercase
move $t0, $zero # i = 0
move $t1, $v1 # l = arrayLen(s)
srl $t2, $t1, 1 # divide l by 2
palinFor:
bgt $t0, $t2, palinForExit # end for loop when i > l/2
sub $t3, $t1, $t0 # l - i
addi $t3, $t3, -1 # l - i - 1
add $t4, $a0, $t0 # s[i]
add $t5, $a0, $t3 # s[l-i-1]
addi $t0, $t0, 1 # i++
lbu $t4, ($t4) # load s[i]
lbu $t5, ($t5) # load s[l-i-1]
sne $t6, $t4, $t5 # if not equal, set $t6 to 1
beq $t6, 1, palinForExit # leave loop if not equal
j palinFor # loop again
palinForExit:
sne $v0, $t6, $zero # set return value: 0 for not palindrome, 1 for palindrome
addu $ra, $zero, $s4 # restore $ra
jr $ra # return to function caller
arrayLen:
li $t0, 0 # counter = 0
sll $t1, $t0, 2 # counter * 4
add $t1, $t1, $a0 # address of s[counter] in $t1
lbu $t2, ($t1) # load s[counter]
while:
beq $t2, 0, whileEnd # skip to end of while loop if s[counter] == \0
blt $t2, 64, breakIf # skip if not uppercase range
bgt $t2, 91, breakIf # skip if not uppercase range
addi $t2, $t2, 32 # add 32 to make character lowercase
sw $t2, ($t1) # save change to memory
breakIf:
addi $t0, $t0, 1 # counter++
whileEnd:
move $v1, $t0 # return value of arrayLen is counter
jr $ra # return to function caller
这是我的代码停止的地方,测试代码的.data部分如下:
.data
#The following examples were copied from
# http://en.wikipedia.org/wiki/Palindrome
pali1:
.asciiz "Socorram me subi no on ibus em Marrocos" #Brazilian Portuguese
pali2:
.asciiz "Ein Neger mit Gazelle zagtim Regen nie" #German
pali3:
.asciiz "stressed desserts"
pali4:
.asciiz "palindromes"
pali5:
.asciiz "tattarrattat"
is_pali_msg:
.asciiz " The string is a palindrome."
not_pali_msg:
.asciiz " The string is not a palindrome."
newline:
.asciiz "\n"
test_str:
.word pali1, pali2, pali3, pali4, pali5, is_pali_msg
我的大脑因学习这些东西而受伤。为什么它不起作用的一些方向将不胜感激,谢谢:D
答案 0 :(得分:1)
试试这个:
.text
strlen:
# ------------
# arguments:
# a0 = string
# ------------
li $v0, 0 #set return value to 0
strlen_loop:
lb $t0, 0($a0) #load byte from beginning of the string
beq $t0, $0, strlen_exit #when character value is 0 we have
#reached the end of the string
addi $a0, $a0, 1 #shift pointer to string one space right
addi $v0, $v0, 1 #increment return value by one
j strlen_loop
strlen_exit:
# ------------
# returns:
# INTEGER (string length)
# ------------
jr $ra #return
palindrom:
# ------------
# arguments:
# a0 = string
# ------------
sub $sp, $sp, 8 #allocate memory on stack
sw $ra 0($sp) #save return address
sw $a0 4($sp) #save argumrnt value
jal strlen #call strlen
move $t0, $v0 #save result
lw $a0 4($sp) #load argument
move $t1, $a0 #save its value to t1
li $t2, 1 #set counter to 1
li $v0, 1 #prepare return value
div $t3, $t0, 2 #calculate string length / 2
addi $t3, $t3, 1 #add one more in case of even number
palindrom_loop:
bge $t2, $t3 palindrom_exit #when counter reaches half of the string length - exit
lb $t4, 0($a0) #get character from beginning
sub $t5, $t0, $t2 #subtract counter from the string length
add $t6, $t5, $t1 #add index from the end of the string to start address
lb $t7, 0($t6) #get corresponding character from the end of the string
beq $t4, $t7, palindrom_continue #check to determine are the characters exact match
li $v0, 0 #if not return 0, immediately
j palindrom_exit
palindrom_continue:
addi $a0, $a0, 1 #shift pointer to string one space right
addi $t2, $t2, 1 #increment counter by one
j palindrom_loop
palindrom_exit:
# ------------
# returns:
# TRUE (1) or FALSE (0)
# ------------
lw $ra 0($sp) #load return address
addi $sp, $sp, 8 #free stack
jr $ra #return
main:
#entry point
la $a0, str #load string
jal palindrom #call palindrom
move $a0, $v0 #set a0 to palindrom return value
li $v0, 1 #set 1 to v0 - as this is system call for print int
syscall #make the call
li $v0, 10 #set 10 to v0 - as this is system call for exit program
syscall #make the call
.data
str: .asciiz "thiispalindrome_emordnilapsiiht"
方法是从头开始获取字符,从字符串末尾获取相应的字符。如果它们完全匹配,则在计数器达到字符串长度的一半时继续执行。如果发现任何一对字符不同,请立即停止执行并返回FALSE。
还有一件事,我没有实现大写字母与小写字母没有区别的部分。但这并不难。你可以自己添加它。这个想法是测试每个加载的字符,如果它的ascii在A(65)和Z(90)之间。如果是这样,您将为ascii值添加32,并且您将获得小写字母。