如何处理存储在 MIPS 程序集堆栈指针中的三个或更多值?

问题描述

该程序旨在允许用户使用破折号(“-”和“|”)来形成框,连接 3x3 网格的顶点。

因此,如果您愿意,可以将其称为初学汇编程序员问题,但是我在将三个或更多值存储在堆栈指针上时遇到了问题。我想通过从堆栈指针中弹出返回地址来从 loop1 返回到 main;然而,在 checkMove 中,堆栈指针被添加了两次。

如何解决我的问题,以便我可以从 loop1 返回 main?

    .data #Data declaration segment
board: .ascii   "\n\n   . . .          . 0 . 1 ."
       .ascii     "\n                  2   3   4"
       .ascii     "\n   . . .          . 5 . 6 ."
       .ascii     "\n                  7   8   9"
       .asciiz    "\n   . . .          . a . b .\n"
offset: .byte     6,8,33,35,37,62,64,89,91,93,118,120
marker: .byte    '-','-','|','-'

    .text #Text declaration statement

main:
    li $t0,6 #Number of loops/moves to make
    jal loop1
    
    #Print game board
    li $v0,4
    la $a0,board
    syscall
    
    #Exit Program
    li $v0,10
    syscall
    
loop1:
    #Load return address onto stack pointer
    subu $sp,$sp,4 
    sw $ra,($sp) #Store $ra into $sp
    
    #Read integer for marking excluding a and b
    li $v0,5
    syscall
    
    move $a0,$v0 #Set $v0 to $a0
    jal markMove #Jump to markMove; return address is set in $ra
    sub $t0,$t0,1 #Decrement counter by 1
    bnez $t0,loop1 #Return to L1 if counter not 0
    
    #Once counter is 0,pop return address off stack pointer
    lw $ra,($sp)
    addu $sp,4
    
    jr $ra
    
#Mark a move on the game board
#Input : $a0 (Integer move 0-9)
markMove:
    ##Prepare to pass necessary variables ($v0,$ra) into function.
    
    #Push return address ($ra) onto stack pointer
    subu $sp,($sp) #Store $ra into $sp
    #Push $t0 onto stack pointer
    subu $sp,4

    sw $t0,($sp) #Store $t0 into $sp
    
    lb $t0,offset($a0)
    
    #Actually mark Now
    lb $t1,marker($a0) #Find the marker
    sb $t1,board($t0) #Place the marker at spot in board

#Clear stack pointer ($sp) and return to $ra
loop2:
    ##Prepare to take the variables ($v0,$ra) from above.
    lw $t0,($sp) #Pop $t0 off of stack pointer
    addu $sp,4
    lw $ra,4
    
    jr $ra #Return to return address; jump register

解决方法

您的问题是您在每次从用户读取数字的迭代中都推送 $ra(根据您注释的代码进行 6 次循环/移动)。

每次进入一个新的函数/过程时,你应该只存储一次返回地址,并在从它返回之前恢复它。

因此,您可以在保存上下文并在控制循环中使用它后添加另一个标签。在这个例子中,我使用了 inner_loop:

...
loop1:
    #Load return address onto stack pointer
    subu $sp,$sp,4 
    sw $ra,($sp) #Store $ra into $sp
    
inner_loop:
    #Read integer for marking excluding a and b
    li $v0,5
    syscall
    
    move $a0,$v0 #Set $v0 to $a0
    jal markMove #Jump to markMove; return address is set in $ra
    sub $t0,$t0,1 #Decrement counter by 1
    bnez $t0,inner_loop #Return to L1 if counter not 0
    
    #Once counter is 0,pop return address off stack pointer
...

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...