【问题标题】:Palindrome Checker in MipsMips 中的回文检查器
【发布时间】:2015-04-17 15:44:02
【问题描述】:

我正在参加一个计算机组织课程,该课程通过 MIPS 汇编教授计算机的低级功能。作业中的一个问题是回文检查器。这里是:

编写一个 MIPS 函数(称为“回文”),如果 输入字符串是回文,否则返回 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

【问题讨论】:

    标签: mips


    【解决方案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) 之间。如果是这样,您将 32 添加到 ascii 值,您将得到小写字母。

    【讨论】:

      猜你喜欢
      • 2022-11-10
      • 1970-01-01
      • 2017-03-28
      • 1970-01-01
      • 1970-01-01
      • 2014-12-23
      • 1970-01-01
      • 1970-01-01
      • 2012-03-30
      相关资源
      最近更新 更多