С вашим кодом много проблем.
Во-первых, выбранное вами отношение повторения очень неэффективно и намного сложнее, чем необходимо.Даже Википедия имеет несколько лучших рекуррентных отношений, например
n over k = (n-1 over k-1) * (n/k)
избегает повторного ввода в функцию несколько раз (таким образом, позволяя функции быть записанной хвостово-рекурсивно).
У повторения, которое вы используете, есть дополнительный недостаток, который вы оба должны проверить для k==0
и k==n
.
. Это подводит нас к вашей реализации, чтоне удается правильно проверить оба условия:
##base case
bne $a0, $a1, gen #if (a==b)
addi $v0, $0, 1 #$v0 (1)
j rtn
bne $a1, $0, gen #if (b==0)
addi $v0, $0, 1 #$v0 (1)
j rtn
Первый из этих тестов перепрыгивает через второй тест, если a!=b
, независимо от того, b==0
, поэтому второй тест недоступен.Вам придется изменить код на
##base case
bne $a0, $a1, isbzero #if (a==b)
addi $v0, $0, 1 #$v0 (1)
j rtn
isbzero:
bne $a1, $0, gen #if (b==0)
addi $v0, $0, 1 #$v0 (1)
j rtn
Наконец, вы не сохраняете значения аргументов функции перед рекурсивными вызовами.Если вы хотите быть совместимым с ABI, вы не можете предполагать, что значения в регистрах аргументов функции сохраняются во время вызова.
В частности после
##recursive call
gen:
addi $a0, $a0, -1 #$a0 (a-1)
addi $a1, $a1, -1 #$a1 (b-1)
jal comb #call comb(a-1, b-1)
следующие
add $s0, $v0, $0 #$s0 comb(a-1, b-1)
addi $a1, $a1, 1 #$a1 (b)
jal comb #call comb(a-1, b)
будет иметь неверные значения для $a0
и $a1
.
Если соответствие ABI для вас не имеет значения, вы можете восстановить значения перед возвратом, снова увеличив аргументы.