Ваш код push/pop в findX
в порядке и соответствует ABI. И, предварительный вычет $sp
всегда работает независимо от ABI.
Вы не показываете evaluate
, но это вероятный подозреваемый. Если бы у вас было, было бы довольно легко изучить код и диагностировать проблему.
После возвращения истинного, evaluate
либо изменилось $sp
или имеет перезаписаны части рамы findX
стека.
Вы можете добавить контрольную точку в evaluate
для истинного случая. Большинство симуляторов сохраняют историю последних N инструкций, поэтому вы можете посмотреть изменения на sp
или сохранить их по отношению к ним. Этого может быть достаточно.
Но, еще один способ - добавить код отладки в findX
, который работает совместно с отладчиком. То есть условие отказа может быть слишком сложным, чтобы отладчик остановился (т. Е. Он не имеет сложных часов таких условий, как gdb
), поэтому мы можем добавить некоторый «вспомогательный» код.
Я добавил некоторые дополнительные значения в кадр findX
стека, которые позволяют для некоторых консистенции и перекрестная проверка и дополнительный код, чтобы проверить эти значения
Ниже код изменен для отладки.
Использование отладчика, положить точки останова на всеnop
инструкции. Когда вы нажмете один, изучите историю, значения и т. Д. Это должно помочь изолировать вашу проблему.
# recursive debug
findX:
addi $sp,$sp,-12 # make room on stack
sw $ra,8($sp) # save ra
sw $sp,4($sp) # save sp
li $t7,0xdeadbeef # save a "magic" number
sw $t7,0($sp) # we want this at the old offset for sp
# a series of calculations that are not part of the problem
# gives an output based on the calculations before that triggers various
# branches
jal evaluate
# NOTE/BUG: if this returns "true", then one of two things happened:
# (1) evaluate changed the sp register contents
# (2) evaluate overwrote the the return value we stored above
bc1t matchfound
jal findX
x_return:
li $t7,0xdeadbeef # get the expected magic number
lw $t6,0($sp) # get the stored value
bne $t6,$t7,badnews1 # did it get trashed? if yes, fly
ignore1:
# the sp value must be the same as when we called the function
lw $t6,4($sp) # get the stored value
bne $t6,$sp,badnews2 # did it get trashed? if yes, fly
ignore2:
# NOTE: we take advantage of the fact that evaluate is called from only
# _one_ place within findX, so we _know_ the ra value
la $t7,x_return # get the expected return value
bne $ra,$t7,badnews3 # did it get trashed? if yes, fly
ignore3:
# NOTE: we take advantage of the fact that evaluate is called from only
# _one_ place within findX, so we _know_ the ra value
la $t7,x_return # get the expected return value
lw $t6,8($sp) # get the saved return value
bne $t6,$t7,badnews4 # did it get trashed? if yes, fly
ignore4:
mov.s $f0,$f17 # holds the value to return
lw $ra,8($sp) # restore $ra
addi $sp,$sp,12 # restore stack pointer
jr $ra
# trap for success
matchfound:
nop # put a breakpoint here
j x_return
# trap for error
badnews1:
nop # put a breakpoint here
j ignore1
# trap for error
badnews2:
nop # put a breakpoint here
j ignore2
# trap for error
badnews3:
nop # put a breakpoint here
j ignore3
# trap for error
# NOTE: this one is special
# we may get a false positive on the first call to findX
# that is, (e.g.) main does "jal findX" and so we'd fail here
# for that case, just continue
badnews4:
nop # put a breakpoint here
j ignore4
Имеет ли ваш ABI указатель стека на первый пустой слот в стеке или последний использованный слот? – EOF
Что такое ABI? –
* Application Binary Interface *. Помимо прочего, он указывает, как функции называют друг друга, который регистрируется, чтобы сохранить, как передать слишком большие для регистров аргументы. – EOF