【问题标题】:MIPS palindrome checkerMIPS 回文检查器
【发布时间】:2022-11-10 13:30:03
【问题描述】:

我很难弄清楚从哪里开始这个项目。我需要在作为回文检查器的 PLP 中编写代码。 任务是编写一个程序,通过 UART 接收字符串,检查该字符串是否为回文,然后使用打印函数打印“是”或“否”。我已经获得了一个模板,我在创建程序时要遵循该模板。

模板项目文件包含六个需要实现的函数存根。五个从主循环调用,第六个从“period_check:在模板文件中包含每个函数需要做什么以及应该如何实现的描述。我试图填写一些,但我不认为我在正确的轨道上。请帮助。

***** 我已经输入了这么多代码,但它没有打印出正确的输出**** 它对所有内容都打印 no,而对非回文则打印 no,而对回文则打印 yes。

.org 0x10000000

# Initializations
# NOTE: You may add initializations after line 10, but please do not
# remove or change the initializations to $sp, $s0, $s1, or $s2

li $sp, 0x10fffffc  # Starting address of empty stack
li $s0, 0xf0000000  # UART base address
li $s1, array_ptr   # Array head pointer
li $s2, array_ptr   # Array tail pointer


####################################################################
# Do not make changes to the jump to main, the allocation of
# memory for the array, or the main loop
####################################################################
    j main
    nop

array_ptr:          # Label pointing to 100 word array
    .space 100

main:
    jal poll_UART
    nop
    jal period_check
    nop
    jal space_check
    nop
    jal case_check
    nop
    jal array_push
    nop
    j main
    nop
####################################################################
# ******************************************************************
####################################################################


# The "poll_UART" function should poll the status register of the UART.
# If the 2^1 bit position (ready bit) is set to 1 then it
# should copy the receive buffer's value into $v0 and send
# a clear status command (2^1) to the command register before
# returning (a return statement is already included). In order to
# receive full credit, $s0 must contain the base address of the UART
# and must be used with the appropriate offsets to access UART
# registers and buffers

poll_UART:


    lw $t1, 4($s0)
    li $t2, 0b10
    and $t3, $t1, $t2
    beq $t3, $0, main
    nop
    lw $v0, 8($s0)
    sw $t2, 0($s0)
    jr $ra
    nop


 


# The "period_check" function should check if the current character ($v0)
# is a period ("."). If it is a period then the function should go to the
# label, "palindrome_check". If the character is not a period then it
# should use the included return.

period_check:

    li $t0, 0x2E
    beq $v0, $t0, palindrome_check
    nop

# The "space_check" function should check if the current character ($v0)
# is a space (" "). If it is then it should jump to "main" so
# that it skips saving the space character. If not it should
# use the included return.

space_check:

    li $t4, 0x20
    beq $t4, $v0, main
    jr $ra
    nop

# The "case_check" function should perform a single inequality check.
# If the current character ($v0) is greater than the ASCII value of 'Z',
# which indicates the current character is lowercase, then it should convert
# the value of $v0 to the uppercase equivalent and then return. If the
# current character ($v0) is already uppercase (meaning the inequality
# mentioned before was not true) then the function should return without
# performing a conversion.

case_check:

   li $t5, 0x5A
   slt $t6, $v0, $t5
  li $t7, 1
   beq $t6, $t7, convert

convert:
    addiu $v0, $v0, -32
    jr $ra
    nop


# The "array_push" function should save the current character ($v0) to the
# current location of the tail pointer, $s2. Then it should increment the
# tail pointer so that it points to the next element of the array. Last
# it should use the included return statement.

array_push:

     sw $v0, 0($s2)
     addiu, $s2, $s2, 4
     jr $ra
     nop


# The "palindrome_check" subroutine should be jumped to by the period
# check function if a period is encountered. This subroutine should contain 
# a loop that traverses the array from the front towards the back (using the
# head pointer, $s1) and from the back towards the front(using the tail
# pointer, $s2). If the string is a palindrome then as the array is traversed
# the characters pointed to should be equal. If the characters are not equal
# then the string is not a palindrome and the print function should be used
# to print "No". If the pointers cross (i.e. the head pointer's address is
# greater than or equal to the tail pointer's address) and the compared
# characters are equal then the string is a palindrome and "Yes" should be
# printed. 
# 
# Remember to restore the head and tail pointers to the first element
# of the array before the subroutine jumps back to main to begin processing the
# next string. Also, keep in mind that because the tail pointer is updated at
# the end of "array_push" it technically points one element past the last
# character in the array. You will need to compensate for this by either
# decrementing the pointer once at the start of the array or using an offset
# from this pointer's address.

palindrome_check:


    addiu $s2, $s2, -8 
    move $s3, $s1
    subu $s6, $s2, $s3
    beq $s6, $0, palindrome
    nop
check_loop:
    lw $s4, 0($s3)
    lw $s5, 0($s2)
    bne $s5, $t0, not_palindrome
    nop
adjust_pointers:
    addiu $s2, $s2, -4
    addiu $s3, $s3, 4 
    slt $t8, $s3, $s2
    bne $t8, $t0, check_loop
    nop
    j palindrome
    nop
palindrome:
    li $a0, 1
    call project3_print
    move $s2, $s1
    j main 
not_palindrome:
    li $a0, 0
    call project3_print 
    move $s2, $s1
    j main 
    nop

【问题讨论】:

    标签: mips palindrome


    【解决方案1】:

    好吧,这只是我的意见,但你绝对不是在正确的轨道上。

    您显示的控制流有问题。

    要了解其中一个原因,请尝试用 C 或您知道的任何其他语言编写相同的代码。由于使用了非本地 goto,您将无法执行此操作,其中一个过程跳转(不调用)到另一个过程。

    此外,查找输入是否为回文并不是对每个输入字符执行的一次性步骤的固定序列。

    您将 (1) 需要存储字符以供以后比较,并且 (2) 需要一个决策点,您可以在其中确定(并打印)是,或者不是。你没有任何控制结构。

    它通过 UART 接收字符串,检查该字符串是否为回文,然后使用打印函数打印“是”或“否”。

    是的,您的main 应该反映您所获得的上述描述:

    • 接收一串字符
    • 检查此字符串是否为回文
    • 打印“是”或“否”

    换句话说,你可能有类似的东西:

    int len = input_string();
    if ( check_palindrome(len) ) {
        print "yes";
    else
        print "no"
    

    建议您用 C 或您知道的其他语言编写它,然后将其翻译成汇编。

    还要考虑我们编程的一些东西是返回值的函数而不是不返回值的过程。返回一个值以便main 可以采取不同的行动(例如打印是与否)比使用非本地 goto 从子例程中更改控制流要好得多。

    如果您的指导/课程给了您main,并且推荐非本地 goto,那将是非常可悲的。


    我很同情你和你的同学,因为这是我很长时间以来见过的最糟糕的集会教学案例之一。

    array_ptr:          # Label pointing to 100 word array
        .space 100
    

    标签名称具有误导性。该空间用作单词数组,而不是指向数组的指针。保留的存储空间为 25 个字,因为.space 以字节为单位进行操作,每个字为 4 个字节。所以,评论完全是错误的。

    使用jal 调用的各种“函数”都是一次性函数,所以在这个赋值中根本不需要函数。 “函数”也会相互访问并返回 main,而不是像结构化编程那样正确返回。所以,这就是我们所说的意大利面条代码——这样的代码很难推理,也是其他语言甚至懒得提供这种流控制的原因之一。

    当输入元素只是字符时,正在使用的数组存储整个单词,所以这是无害的,但没有必要。


       beq $t6, $t7, convert
    
    convert:
    

    这种控制结构永远不会在两个选项之间进行选择,它总是会转换。为什么?因为在 $t6 为真的情况下,它将分支到 convert:,而在 $t6 不为真的情况下,它将落到convert:,因此相同的位置在任何一种情况下都将运行相同的代码。

    您应该能够在调试期间观察到这一点。


    调试技巧

    了解您的数据。您应该在调试时知道数组的地址。您可以在执行期间找到它,例如查看li ... array_ptr 之后的寄存器(顺便说一句,该操作码应该是la,但不管它是否有效)。否则,您可以在运行第一条指令之前观察数据部分及其布局以找出答案。

    每行单步调试任何其他语言的代码,验证每行之间的程序状态。在 MIPS 汇编中,行之间的程序状态变化不大,所以通常这很简单——通常每条指令只改变一个寄存器或一个内存位置——但你必须验证这种变化是否符合你的预期。一旦程序的第一部分正确地将字符存储到数组中,您就可以使用断点功能在回文检查例程处停止,并从那里单步执行。

    首先使用尽可能小的输入,(在最退化的情况下,这将是一个空字符串,但您可能不会处理这些)可能会尝试单个字母输入(应该是回文)。一旦工作正常,请尝试输入两个字母。正如我所说,首先确保字符值被正确地放入数组中,并且只有当你验证它工作正常时,才能继续调试回文检查代码。

    【讨论】:

    • 这就是教练基本上给我们的主要方式。到目前为止,我已将代码更新为我输入的内容,但是现在它为我放入程序中的所有内容都打印了 no。关于如何进行调试和找出我离开的地方或地方的任何建议?
    【解决方案2】:

    你有没有想过这个?你终于让它输入是和否了吗?

    【讨论】:

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