反向波兰表示法mips算法

时间:2016-01-17 21:30:54

标签: mips

作为一名初学者,我在使用mips语言时遇到困难。 最近,我检查了一个MIPS反向抛光记谱程序,我在互联网上找到了爱丁堡大学,我几乎没有问题。

以下代码不是我的。爱丁堡大学的财产

# ======================================================
# Reverse Polish Notation Calculator
# ===================================================================
# RPN calculator in MIPS
#
# Inf2C-CS Coursework 1. Task B
# SOLUTION
#
# Paul Jackson
# 10 Oct 2012

    #==================================================================
    # DATA SEGMENT
    #==================================================================
    .data
                    # // Global variables in memory
                    # int stack[STACK_SIZE] ;
    .align 2        # // Ensure stack array starts on word boundary
stack:  .space 20       # // Allocate STACK_SIZE * 4 byte words for stack
                    # // where STACK_SIZE = 5.
stack_end:

                    # // String constants
prompt: .asciiz "> "    # char* prompt = "> " ;
newline:
    .asciiz "\n"    # char* newline = "\n" ; 

empty:                  # char* empty = "(EMPTY)\n" // Stack empty message
    .asciiz "(EMPTY)\n" 
colonsp:
    .asciiz ": "    # char* colonsp = ": " // For stack print formatting

    #==================================================================
    # TEXT SEGMENT  
    #==================================================================
    .text

    # // Register usage.
    # //
    # int* stackp ;   // $s0.  Stack pointer
    # int* stack  ;   // $s1.  &stack[0] - Start address of stack 
    # int* stack_end ;// $s2.  &stack[STACK_SIZE] - First address after
    #                 //                            end of stack
    # int  c          // $s3.  Input character (coerced to int)

    # int  s4 // $s4 Temporary var preserved across function calls
    # int  s5 // $s5 Temporary var preserved across function calls

    #------------------------------------------------------------------
    # PUSH FUNCTION
    #------------------------------------------------------------------
                          # void push (int i) 
                          # i in $a0
push:                         # {
                          #     if (stackp < stack_end) 
    slt  $t1, $s0, $s2    #         // $t1 = stackp < stack_end
    beqz $t1, push_end    #         // b push_end if $t1 == 0
                          #     {
    sw   $a0, 0($s0)      #         *stackp = i ;
    addi $s0, $s0, 4      #         ++stackp ;
                          #     }
push_end:       
    jr $ra                #     return ;
                          # }


    #------------------------------------------------------------------
    # POP FUNCTION
    #------------------------------------------------------------------
                            # int pop() {

pop:                            #     if (stack < stackp) 
    slt  $t1, $s1, $s0      #         // $t1 = stack < stackp
    beqz  $t1, pop1         #         // branch to pop1 if $t1 == 0
                            #     {
    addi $s0, $s0, -4       #         stackp-- ;
                            #         return *stackp ;
    lw   $v0, 0($s0)        #         // $v0 = *stackp
    jr   $ra                #         // return $v0

                            #     } else {
                            #         return 0 ;
pop1:   li   $v0, 0             #         // $v0 = 0
    jr $ra                  #         // return $v0
                            # }


    #------------------------------------------------------------------
    # MAIN BODY
    #------------------------------------------------------------------
main:
    # Initialisation of registers holding constant values

    la  $s1, stack            # // $s1 = &stack[0];
    la  $s2, stack_end        # // $s2 = &stack[STACK_SIZE];

    # Initialisation of registers for main program variable
    move $s0, $s1             # stackp = stack ;

    li $v0, 4                 # print_string("> ")
    la $a0, prompt
    syscall

    #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    # READ LOOP
    #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

mainloop:                         # while (1) {


    li $v0, 12                #    c = read_char()
    syscall                 
    move $s3, $v0           

    #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    # CASE SWITCH ON INPUT CHAR
    #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

maincase1:  # TEST FOR NEWLINE

    li  $t2, 0x0a             #    if (c == '\n') 
    beq $s3, $t2, print_stack #        break ;

maincase2:  # TEST FOR ENTER NEW NUMBER

    li  $t2, 'e'              #    if (c == 'e')
    bne $s3, $t2, maincase3
                              #    {
    move $a0, $zero           #       push(0) ;
    jal push
    j maincases_end           #    } else


maincase3:      
    # TEST FOR DIGIT
                              # if ('0' <= c && c <= '9') 

    li   $t1, '0'             # // $t1 = '0'
    slt  $t2, $s3, $t1        # // $t2 = c < '0'
    bnez $t2, maincase4       # // Skip case if c < '0'

    li   $t2, '9'             # // $t2 = '9'
    slt  $t3, $t2, $s3        # // $t3 = '9' < c
    bnez $t3, maincase4       # // Skip case if '9' < c
                              # {

                            #    push (10 * pop() + (c - '0'));

    sub $s4, $s3, $t1       #    // $s4 = c - '0'
    jal pop                 #    // $v0 = pop()
    sll $t2, $v0, 1         
    sll $t3, $v0, 3
    add $t3, $t2, $t3       #    // $t3 = 10 * $v0
    add $t3, $t3, $s4       #    // $t3 = $t3 + (c - '0')
    move $a0, $t3
    jal push                #    // push $t3

                            # }
    j maincases_end         # else

maincase4:  # TEST FOR NEGATE

    li  $t2, 'n'            # if (c == 'n') 
    bne $s3, $t2, maincase5
                            # {
                            #    push(-pop());
    jal pop
    sub $a0, $zero, $v0
    jal push
    j maincases_end         # } else 

maincase5:  # TEST FOR + OPERATION

    li  $t2, '+'            # if (c == '+')
    bne $s3, $t2, maincase6
                            # {
                            #    push(pop() + pop());
    jal pop                 #    // $s4 = pop()
    move $s4, $v0
    jal pop                 #    // $v0 = pop()
    add  $a0, $s4, $v0      #    // $a0 = pop() + pop()
    jal push
    j maincases_end         # } else 

maincase6:  # TEST FOR - OPERATION

    li  $t2, '-'            # if (c == '-')
    bne $s3, $t2, maincase7
                            # {
                            #    int arg2 = pop(); // 2nd arg for -
    jal pop                 #    // $s4 = pop()  
    move $s4, $v0
                            #    int arg1 = pop(); // 1st arg for -
    jal pop                 #    // $v0 = pop()

                            #    push(arg1 - arg2);
    sub  $a0, $v0, $s4      #    // $a0 = arg1 - arg2
    jal push                #    // push($a0)

    j maincases_end         # } else 

maincase7:  # TEST FOR * OPERATION

    li  $t2, '*'            # if (c == '*')
    bne $s3, $t2, maincases_end
                            # {
                            #    push(pop() * pop());
    jal pop                 #    // $s4 = pop()
    move $s4, $v0
    jal pop                 #    // $v0 = pop()
    mul  $a0, $s4, $v0      #    // $a0 = pop() * pop()
    jal push                #    // push($a0)
                            # }        

maincases_end:
    j mainloop

    #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    # PRINT_STACK 
    #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

print_stack:
    li    $v0, 4            #    print_string("\n") ;
    la    $a0, newline
    syscall

                            #    // This test for the stack being
                            #    // empty was not required in the     submitted
                            #    // solutions.  Indeed the print code
                            #    // in the else case below functions
                            #    // correctly also when stack == stackp.

    bne  $s1, $s0, print1   #    if (stack == stackp) {

    # Uncomment following code to print a message on the stack being empty
    # 
    # li $v0, 4               #       print_string("EMPTY\n")
    # la $a0, empty
    # syscall

    j print_end
print1:                         #    else {
                            #       int * pp; // Use $s4 for pp (print ptr)
    move $s4, $s1           #       pp = stack ;

print2: beq  $s4, $s0, print_end#       while (pp != stackp) {

    li   $v0, 1             #          print_int(pp - stack) ;
    sub  $a0, $s4, $s1      # 
    srl  $a0, $a0, 2        # 
    syscall

    li    $v0, 4            #          print_string(": ") ;
    la    $a0, colonsp
    syscall

    li    $v0, 1            #          print_int(*pp) ;
    lw    $a0, 0($s4)
    syscall

    li    $v0, 4            #          print_string("\n") ;
    la    $a0, newline
    syscall

    add $s4, $s4, 4         #          pp++ ;
    j print2
                            #       }
                            #    }
print_end:

    li $v0, 10      # exit()#    exit() ;
    syscall

    #----------------------------------------------------------------
    # END OF CODE
    #----------------------------------------------------------------

我有以下问题

为什么stack_end:标签为空,而程序有效?

为什么move $a0, $zero?为什么我必须push(0)而不是push(character)

我无法理解push (10 * pop() + (c - '0'));的概念。为什么我需要所有这些操作而不是简单地推送,弹出到堆栈。

我有点困惑,任何帮助都会受到赞赏。

1 个答案:

答案 0 :(得分:2)

它可能对您没有帮助,但此程序在其状态下无法正常工作。如果我们希望使用反向波兰表示法,则代码不正确。但是,无论如何我都会尝试回答。

Stack_end基本上作为一个空地址,它里面没有任何东西,程序员想要使用它来找到堆栈结束后的第一个位置。

每次遇到号码时我们推(0)。如果您正在考虑高级语言而言它没有意义,但在mips中我们确实会移动$ a0,$ 0,这意味着我们为下一个输入的数字让路。所以我们基本上&#34;转移&#34;向上堆栈中的元素和第一个位置的新0元素将被我们的输入替换。

最后,行推(10 * pop()+(c - &#39; 0&#39;))仅在汇编时才有意义。让我们从&#34;(c - &#39; 0&#39;)&#34;开始。这意味着您的角色将被字符&#39; 0&#39;减去在其ASCII等效数字中。如果你减去48就会一样。 例如假设您的字符为9,其中ASCII为57.因此,57 - 48 = 9。

至于行(10 * pop())是跟踪实际数字。基本上,mips不能使用toInt()方法单独读取每个字符。例如 比如说,我们输入32,我们有一个变量x = 0。

Step 1: In ASCII 51(3) - 48 = 3;
Step 2: x * 10 =0
Step 3: x + 3 = 3
Step 4: In ASCII 50(2) -48 = 2
Step 5: x *10 = 30
Step 6: x + 2 = 32

你去吧。希望有所帮助。