2012-04-15 63 views
0

我在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標籤,從堆棧中恢復返回地址並將返回值傳遞給我的main函數。

問題是參數$ 5上的值未定義。它可以是任何給定的值。我相信我的程序存在的問題是,我的main函數的返回地址丟失,程序無法返回到它。我相信文程序達到jal func指令,其main返回地址將其替換爲jal func指令的返回地址。

我該如何解決這個問題? (不問代碼,但只是一些方向)

回答

1

[...]我相信,我的程序問題,那就是從我main函數的返回地址丟失和程序無法返回。我相信文程序達到jal func指令,其main返回地址將其替換爲jal func指令的返回地址。

非常多。您在函數的開始處遞減堆棧指針($29/$sp)以創建空間來保存返回地址($31/$ra),但在重新加載最後的返回地址後,缺少相應的增量堆棧指針 - 您正在查看該值,但實際上並未從堆棧中彈出。

+0

@MathewS謝謝。在我的'func'上添加'addi \t $ 29,$ 29,4'就在'j \t fim'之前,並且按照預期工作。不知道這是否是正確的方式,但它的工作原理應該如下:) – Favolas 2012-04-15 20:27:29

+0

@Favolas:即使在添加該指令後,程序也不會在MARS中輸出正確的結果。 – blackcompe 2012-04-15 21:52:15

+0

@blackcompe你是對的。忘了告訴我,把$ 9,1,fim' \t更改爲'ble $ 9,0,fim'。使用此代碼的Offtopic,你如何在MARS中傳遞參數? – Favolas 2012-04-15 22:36:52

1

評論你的代碼會有很大的幫助。您使用臨時寄存器可能會使事情更加複雜。你只需要使用一個臨時寄存器。以下是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: 
+0

謝謝。我有我的代碼評論,但因爲它是在另一種語言刪除之前發佈在這裏。相對於將參數傳遞給火星上的某個函數,並不是在設置菜單上的「強制」設置$ a0和$ a1,而是使用「提供給MIPS程序的程序參數」。還沒搞清楚它是如何工作的... – Favolas 2012-04-16 07:45:22

+0

@Favolas:我從來沒有使用過程序參數。 – blackcompe 2012-04-16 17:35:22