如何处理存储在 MIPS 程序集堆栈指针中的三个或更多值?
How do I deal with three or more values being stored in stack pointer for MIPS Assembly?
该程序旨在允许用户使用破折号(“-”和“|”)形成框,连接 3x3 网格的顶点。
因此,如果您愿意,可以将此称为初级汇编程序员问题,但我在将三个或更多值存储在堆栈指针上时遇到了问题。我想通过从堆栈指针中弹出 return 地址,从 loop1 return 到 main;但是,在 checkMove 中,堆栈指针被添加到两次。
如何解决我的问题,以便我可以从 loop1 return 进入 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, $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, 4
sw $ra, ($sp) #Store $ra into $sp
#Push $t0 onto stack pointer
subu $sp, $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, $sp, 4
lw $ra, ($sp) #Pop $t0 off of stack pointer
addu $sp, $sp, 4
jr $ra #Return to return address; jump register
你的问题是你在每次从用户那里读取数字的迭代中推动 $ra
(根据你评论的代码,6 loops/moves)。
每次输入新的 function/procedure 时,您只应存储一次 return 地址,并在从中 return 之前恢复它。
因此,在保存上下文并在控制循环中使用它之后,您将添加另一个标签。在这个例子中我使用了 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
...
该程序旨在允许用户使用破折号(“-”和“|”)形成框,连接 3x3 网格的顶点。
因此,如果您愿意,可以将此称为初级汇编程序员问题,但我在将三个或更多值存储在堆栈指针上时遇到了问题。我想通过从堆栈指针中弹出 return 地址,从 loop1 return 到 main;但是,在 checkMove 中,堆栈指针被添加到两次。
如何解决我的问题,以便我可以从 loop1 return 进入 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, $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, 4
sw $ra, ($sp) #Store $ra into $sp
#Push $t0 onto stack pointer
subu $sp, $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, $sp, 4
lw $ra, ($sp) #Pop $t0 off of stack pointer
addu $sp, $sp, 4
jr $ra #Return to return address; jump register
你的问题是你在每次从用户那里读取数字的迭代中推动 $ra
(根据你评论的代码,6 loops/moves)。
每次输入新的 function/procedure 时,您只应存储一次 return 地址,并在从中 return 之前恢复它。
因此,在保存上下文并在控制循环中使用它之后,您将添加另一个标签。在这个例子中我使用了 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
...