汇编MIPS:检查字符串是否是回文符号

时间:2016-11-14 11:16:40

标签: assembly mips

Palindromic是一个可以双向阅读的字符串。比如“雷达”,“哇”等。

从C我们知道我们可以使用“for”循环和“if”表达式检查给定字符串:

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

我有一个问题,我应该知道我应该有EXIT和ELSE标签,我认为这就是为什么它总是返回字符串是回文的,即使它不是。

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

是否需要多个标签?

1 个答案:

答案 0 :(得分: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行,但它可以让您在编写/调试时专注于更短更简单的代码部分