【问题标题】:Assembly MIPS: Checking if a string is palindromic or not汇编 MIPS:检查字符串是否为回文
【发布时间】:2017-03-28 00:22:05
【问题描述】:

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 标签,我认为这就是为什么它总是返回字符串是回文的,即使不是。

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

它需要多个标签吗?

【问题讨论】:

  • i 不需要一直到length-1。有两个指针,一个从str 开始,另一个从str+length-1 开始。然后使用这两个指针读取一对字符,并比较字符。如果字符不相等,则字符串不是回文。如果字符相等,则增加第一个指针并减少第二个指针。如果现在第一个指针大于第二个,则字符串是回文并且你完成了,否则你继续。
  • 如果第一个指针大于或等于第二个指针,它是回文 - 对于奇数长度的字符串,这将提前 1 个字符退出,而不是测试 (str[middle] == str[middle])
  • @Michael 听起来更复杂,我的大脑快要烤熟了。
  • @Ped7g 我该如何改变呢?
  • 首先在抽象级别清理你的算法步骤,例如检查你的length计算,你有相同的值$t0和$t1,整个循环。一个用作索引,另一个用作长度计数器。如果你先在更高的层次上看它,你可能会意识到它们是平等的,只需要其中一个。通过类似的方式,您可以生成更短的 asm 程序。如果你只是写下你得到的第一个想法,你可能会得到很多重复的代码,比如在代码末尾显示字符串。如果您将a0 设置为想要的字符串,则可以使用单个代码路径显示并退出

标签: assembly mips


【解决方案1】:

正确高效的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 行,但它可以让您在编写/调试时专注于更短和更简单的代码部分。

【讨论】:

    猜你喜欢
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多