Assembly 程序集返回地址不工作

Assembly 程序集返回地址不工作,assembly,mips,Assembly,Mips,我在C中有这个函数: int func(int n0, int n){ if (n > 1){ int nFinal = func(n0, --n); return (nFinal*nFinal) + n0; } return n0; } 并希望在汇编中对其进行编程。 我有以下代码: .data .text .globl func func: addi $29,$29, -4

我在C中有这个函数:

int func(int n0, int n){
    if (n > 1){
        int nFinal = func(n0, --n);
        return (nFinal*nFinal) + n0;
    }
    return n0;
}
并希望在汇编中对其进行编程。 我有以下代码:

    .data
    .text
    .globl  func
func:
    addi            $29,$29, -4
    sw      $ra,0($29)
    move            $8,$4       
    move            $9,$5       
    ble     $9,1,fim
    sub     $9,$9,1
    move            $5,$9
    jal     func
    move            $4,$11
    jal     quadrado
    add     $11,$2,$8
    j       fim
quadrado:
    mul     $2,$4,$4
    jr      $31
fim:    
    lw      $31,0($29)  
    move            $2,$11
    jr      $31
如果$4和$5中传递的参数分别是2和1,我可以看到程序达到了
ble
指令,它可以按预期工作。它跳转到
fim
标签,从堆栈中恢复返回地址,并将返回值传递给my
main
函数

问题是参数$5上的值未定义。它可以是任何给定的值。我相信我的程序的问题在于,我的
main
函数的返回地址丢失,程序无法返回。我相信wen程序到达了
jal func
指令,
main
返回地址被
jal func
指令返回地址所替代

func:
        #push rtn. addr. onto stk
        sw $ra, 0($sp)
        subi $sp, $sp, 4

        #result = arg0
        move $t0, $a0

        #if arg1 <= 1 return arg0           
        ble $a1, 1, rtn

        #call func(arg0, arg1-1)
        subi $a1, $a1, 1
        jal func

        #result = func(arg0, arg1-1)^2 + arg0
        mul $t0, $v0, $v0
        add $t0, $t0, $a0

rtn:
我怎样才能解决这个问题?(不是问代码,只是问一些方向)

[…]我认为我的程序的问题在于,我的
main
函数的返回地址丢失,程序无法返回到它。我相信wen程序到达了
jal func
指令,
main
返回地址被
jal func
指令返回地址所替代

func:
        #push rtn. addr. onto stk
        sw $ra, 0($sp)
        subi $sp, $sp, 4

        #result = arg0
        move $t0, $a0

        #if arg1 <= 1 return arg0           
        ble $a1, 1, rtn

        #call func(arg0, arg1-1)
        subi $a1, $a1, 1
        jal func

        #result = func(arg0, arg1-1)^2 + arg0
        mul $t0, $v0, $v0
        add $t0, $t0, $a0

rtn:

差不多。您在函数开始时递减堆栈指针(
$29
/
$sp
),以创建空间来保存返回地址(
$31
/
$ra
),但在最后重新加载返回地址后,您缺少堆栈指针的相应增量--您正在查看值,但实际上并不是从堆栈中弹出它。

对代码进行注释将非常有帮助。使用临时寄存器可能会使事情更加复杂。您只需要使用一个临时寄存器。下面是有关
func
例程的一些帮助。我想你可以完成剩下的。当弹出返回地址时,请记住移动堆栈指针

func:
        #push rtn. addr. onto stk
        sw $ra, 0($sp)
        subi $sp, $sp, 4

        #result = arg0
        move $t0, $a0

        #if arg1 <= 1 return arg0           
        ble $a1, 1, rtn

        #call func(arg0, arg1-1)
        subi $a1, $a1, 1
        jal func

        #result = func(arg0, arg1-1)^2 + arg0
        mul $t0, $v0, $v0
        add $t0, $t0, $a0

rtn:
func:
#按rtn。地址。上stk
西南$ra,0($sp)
subi$sp$sp,4
#结果=arg0
移动$t0,$a0

#如果arg1@MathewS,谢谢。在my
func
上的
j fim
之前添加了
addi$29、$29、4
,并按预期工作。不知道这是否是正确的方法,但它的工作方式应该是:)@Favolas:即使添加了该指令,您的程序也不会在MARS中输出正确的结果。@blackcompe您是对的。忘了告诉我把'ble$9,1,fim'改为'ble$9,0,fim'。Offtopic使用此代码,如何在MARS中传递参数?@Favolas:我明白了。你的意思是向函数传递参数吗?如果是这样,只需设置$a0和$a1。谢谢。我有我的代码注释,但因为它是在另一种语言删除后才张贴在这里。相对于将参数传递给mars上的函数,我们并没有讨论“强制”设置$a0和$a1,而是使用“设置”菜单上的“提供给MIPS程序的程序参数”。我还没弄明白它是怎么工作的…@Favolas:我从来没用过程序参数。