2016-11-14 47 views
0

Palindromic是一个可以同时读取的字符串。像“雷达”,“哇”等Assembly MIPS:检查一个字符串是否回文

由C我们知道,我们可以检查一个给定的字符串与“for”循环和“如果”的表达:

for(i=0; i<length; i++) 
    if(str[i] == str[length-i-1]) 
     printf("Palindromic"); 
    else 
     print("Non Palindromic"); 

使我们所能到达双方的弦的中心。

此代码要求我们计算字符以知道字符串的长度。

在MIPS上,这个“for”循环看起来相当复杂。

这里就是我给自己买了:

.data 
str: .space 20 
isntpal: .asciiz "it is not palindromic!" 
ispal: .asciiz "it is palindromic!" 

.text 
.globl main 
main: 

add $t0, $zero, $zero #t0 = i counter for the loops 
add $t1, $zero, $zero #t1 = j counter for length of the string 

li $v0, 8   #gets(str) 
la $a0, str 
la $a1, 20 
syscall 

length: 
    lb $s0, str($t0) #load each character to s0 

    beq $s0, '\0', NEXTCHECK 

    add $t0, $t0, 1 #i++ to scan all the characters of the string 

    add $t1, $t1, 1 #j++ for the total length of the string 

j length 

NEXTCHECK: 


add $t0, $zero, $zero #clean the t0 register from the length loop 


pal: 
    sub $t4, $t1, $t0 #length - i - 1 
    sub $t4, $t4, 1 

    lb $s0, str($t0) #str[i] 
    lb $s1, str($t4) #str[length-i-1] 

    slt $t3, $t0, $t1  #for(i=0; i<length; i++) 
    beq $t3, $zero, EXIT 

    add $t0, $t0, 1   #i++ 

    beq $s0, $s1, ELSE  #if (str[i] == str[length-i-1]) 


    li $v0, 4   #printf("It is palindromic"); 
    la $a0, ispal 
    syscall 
    j EXIT 


    ELSE: 

    li $v0, 4    #else printf("It is not palindromic"); 
    la $a0, isntpal 
    syscall 

    j EXIT 

j pal 

EXIT: 

li $v0, 10 
syscall 

我有一个问题的理解,我应该有退出,ELSE标签,我想这就是为什么它总是返回的字符串是回文,即使不是。

什么是放置标签的正确方法?

是否需要多个标签?

+1

没有必要''我一路去'长度1'。有两个指针,其中一个以'str'开始,另一个以'str + length-1'开头。然后使用这两个指针读取一对字符,并比较字符。如果字符不相等,则字符串不是回文。如果字符相同,则增加第一个指针并递减第二个指针。如果第一个指针现在大于第二个指针,那么这个字符串就是一个回文并且完成了,否则你继续前进。 – Michael

+0

如果第一个指针大于*或等于第二个指针,则它是回文 - 对于奇数长度的字符串,它将在1之前退出1个字符,而不是测试'(str [middle] == str [middle])'。 – Ped7g

+0

@迈克尔听起来更复杂,我的大脑接近烤面包。 – Coursal

回答

0

正确和有效的C版:

bool is_palindrome(const char * str, const size_t length) { 
    const char * frontptr = str;   // front pointer: points at the very first character of string 
    const char * backptr = str + length-1; // back pointer: points at the very last character of string 
    while (frontptr < backptr) {   // while front pointer points ahead of back pointer 
     if (*frontptr != *backptr) return false; // characters differ => not a palindrome 
     ++frontptr;  // move front pointer at next character in string 
     --backptr;  // move back pointer at "next" character toward start of string 
    } 
    // front pointer points at/beyond back pointer 
    // all chars were compared (except middle one for odd length string, which is "palindromic" always) 
    // and all were equal, thus the input string is a palindrome, if this point is reached 
    return true; 
} 

这种C代码以这样的方式有意写入,这将使转换它非常简单的ASM(如每C线1-2的说明)。


如何从内存中加载一个值,如果你知道它的地址(在C指针):

la $a0,some_address # a0 = address (pointer) 
lb $t0,($a0)   # t0 = byte loaded from memory at a0 

如何递增ASM /递减指针:你添加到当前指针的大小指向元素的大小。

用ASCII字符串的元素是单字节,所以移动一个字符往/返就得+ 1/-1添加到指针,如:

addi $a0,$a0,1 # ++byte_ptr 
addi $a1,$a1,-1 # --byte_ptr 

如果你将与字阵列工作,你会想要做+ -4来将指针向前/向后移动一个元素。


,并学习如何使用"procedures" in MIPS ASM,这样你就可以创造出一些通用的普遍采用的“字符串长度”代码,然后再通过简单的复制/粘贴重新使用它(除非你创建你自己的,最终一些库)。

此外,如果您遵循C++示例,回文测试可以作为单独的过程完成。

的主,你会有一点简单的代码维护+调试+推理:

# input string 
# prepare arguments for get_length 
# call get_length 
# process result and prepare arguments for is_palindrome 
# call is_palindrome 
# set a0 to one of the two result strings based on return value 
# display string 
# exit 

可能有点长的指令总数,你将有更多的jaljr $ra线,但它可以让你在编写/调试时专注于更短,更简单的代码部分。

相关问题