Mips:返回错误的返回地址
我写了一个迷你银行程序,在子程序存款中调用多个函数,这是子程序Mips:返回错误的返回地址,mips,mips32,mips64,smips,Mips,Mips32,Mips64,Smips,我写了一个迷你银行程序,在子程序存款中调用多个函数,这是子程序 deposit: addi $sp, $sp, -8 #save space on stack addi $s3, $0, 1 #trigger s3 sw $s3, 0($sp) sw $ra, 4($sp) ..... jal AsciiConvert #convert ascii of deposited amount to integer beq $v0, $0, Er
deposit:
addi $sp, $sp, -8 #save space on stack
addi $s3, $0, 1 #trigger s3
sw $s3, 0($sp)
sw $ra, 4($sp)
.....
jal AsciiConvert #convert ascii of deposited amount to integer
beq $v0, $0, Err_ACC #if no value to be deposited was inputed print error message
beq $t0, $0, deposit_checking #if check exists returns a 0
beq $t0, 1, deposit_saving #if check exists returns a 1
jal printarray
lw $s3, 0($sp)
lw $ra, 4($sp) # reload $ra so we can return to caller
addi $sp, $sp, 8 # restore $sp, freeing the allocated space
jr $ra
deposit_checking:
... arithmetic operations...
jr $ra
ascii转换子例程:
AsciiConvert:
...normal arithemtics...
j ConvertOP
ConvertOP:
lb $s0, 0($a1)
beq $s0, $0, endConvert #end at null terminating
beq $s0,32,endConvert #if found a space
addi $s0, $s0, -48 #convert to int
mul $s2, $s1, 10 #multiply sum by 10
add $s2, $s2, $s0 #sum = sum + previous number
add $s1, $s2, $0 #s1 holds previous value
addi $a1, $a1, 1 #increment adress
add $v0, $s2, $0 #store the number in the return adress
j ConvertOP
endConvert:
jr $ra
当我进入存款时,我jal ASCICONVERT,然后进入存款检查子例程,但是该存款检查的返回地址将我返回到jal ASCICONVERT行,而不是我调用存款检查子例程的行,导致Ascii转换子例程和存款检查子例程之间出现无限循环…有人能帮我吗?
存款检查
看起来像一个子例程,您在帖子中将它标识为一个子例程,但是,我们不使用beq
指令输入子例程,您应该使用jal
调用子例程
在机器代码中,MIPS的返回地址,$ra
实际上是子例程的一个参数-它告诉子例程在调用者中恢复执行的位置,返回到哪里。有几种方法可以使用有意义的返回地址设置$ra
寄存器,当然,到目前为止,日航是最常见的方式
beq
通过更改程序计数器(pc)将处理器的控制权转移到目标标签(当eq为真时),但不提供(新的)$ra
值
通过不将$ra
设置为新值,它的旧值将被保留。由于$ra
寄存器上次是由jal asciconvert
设置的,因此另一个函数的jr$ra
返回到那里,没有人知道这不是正确的调用-因为正确设置该参数是调用方的工作
虽然有些指令集允许调用条件,但我们不一定希望所有的beq
s都捕获返回地址,因为使用beq
的任何函数都必须考虑保留$ra
我们还要注意,这些行为在调试期间都是可见的。jr$ra
,例如,将控制权转移到由$ra
寄存器中的值寻址的任何机器指令。当您第一次输入子例程/函数时,在$ra
寄存器中应该提供一个正确的返回地址参数,并且当您使用其最终指令jr$ra
到达函数末尾时,如果$ra
寄存器的值已从输入值更改,然后它就不会返回到调用它的地方——因此我们将在这两个更改之间寻找某个地方,$ra
,而不将其还原回来