2010-02-19 106 views
2

我明白,只要我有一個函數在MIPS中有四個以上的參數,我應該使用堆棧。然而,在保存第五個參數sw $t0, 4($sp)並執行jal sad之後,在我的代碼中,在sad函數的開始處,我再次調整堆棧指針以保存調用者使用的$sx寄存器。我在這裏做錯了什麼?帶有四個以上參數的MIPS函數調用

vbsme: subu $sp, $sp, 8  # create space on the stack pointer 
    sw $ra, 0($sp)  # save return address 

    li $v0, 0   # reset $v0 
    li $v1, 0   # reset $v1 
    li $s0, 1   # i(row) = 1 
    li $s1, 1   # j(col) = 1 
    lw $s2, 0($a0)  # row size 
    lw $s3, 4($a0)  # col size 
    mul  $s4, $s2, $s3  # row * col 
    li $s5, 0   # element = 0 
loop: bgeq $s5, $s4, exit  # if element >= row * col then exit 

    subi $a3, $s0, 1  # 4th parameter: i-1 
    subi $t0, $s1, 1  
    sw $t0, 4($sp)  # 5th parameter: j-1 

    jal  sad   # calculate the sum of absolute difference using the frame starting from row a3 and col 4($sp) 

    add $s6, $s0, $s1 
    andi $s7, $s6, 1 
if: bneq $s7, $zero, else 
inif: bge $s1, $s2, inelse 
    addi $s1, $s1, 1 
    j inif1 
inelse: addi $s0, $s0, 2 
inif1: subi $s7, $s0, 1 
    beq $s7, $zero, loop_back 
    subi $s0, $s0, 1 
    j loop_back 
else: bge $s0, $s2, inelse1 
    addi $s0, $s0, 1 
    j inif2 
inelse1:addi $s1, $s1, 2 
inif2: subi $s7, $s1, 1 
    beq $s7, $zero, loop_back 
    subi $s1, $s1, 1 
    j loop_back 
loop_back: addi $s5, $s5, 1 
     j loop 
exit: lw $ra, 0($sp)  # restore return address 
    addi $sp, $sp, 8  # restore stack pointer 
    jr $ra    # return  

.globl sad 
sad: subu $sp, $sp, 32  # allocate stack space for largest function 
    sw $s7, 28($sp)   # save $s7 value  
    sw $s6, 24($sp)   # save $s6 value 
    sw $s5, 20($sp)   # save $s5 value 
    sw $s4, 16($sp)   # save $s4 value 
    sw $s3, 12($sp)   # save $s3 value 
    sw $s2, 8($sp)   # save $s2 value 
    sw $s1, 4($sp)   # save $s1 value 
    sw $s0, 0($sp)   # save $s0 value 


    #some code to be filled later 



    lw $s7, 28($sp)   # restore original value of $s7 for caller 
    lw $s6, 24($sp)   # restore original value of $s6 for caller 
    lw $s5, 20($sp)   # restore original value of $s5 for caller 
    lw $s4, 16($sp)   # restore original value of $s4 for caller 
    lw $s3, 12($sp)   # restore original value of $s3 for caller 
    lw $s2, 8($sp)   # restore original value of $s2 for caller 
    lw $s1, 4($sp)   # restore original value of $s1 for caller 
    lw $s0, 0($sp)   # restore original value of $s0 for caller 
    addiu $sp, $sp, 32  # restore the caller's stack pointer 
    jr $ra    # return to caller's code 
+0

我看不出標題如何與問題相關。 – Tom 2010-02-19 19:11:53

+1

是這樣,我是問如何獲得在該函數的第五個參數傷心 – aherlambang 2010-02-19 19:19:49

回答

4

這是如何由gcc完成的。欲瞭解更多信息,您(可以)應該閱讀Mips ABI 。有些事情可能不同。

http://math-atlas.sourceforge.net/devel/assembly/mipsabi32.pdf

按照慣例,第五個參數應該在棧上的第五個字。

所以,你應該

sad: 
    sub $sp,$sp,24 #24 byte stack frame 
    ... some code ... 
    #Convention indicates to store $a0..$a3 in A..D (see below) 
    sw $a0,0(sp) 
    sw $a1,4(sp) 
    sw $a2,8(sp) 
    sw $a3,12(sp) 

    #Get the 5th argument 
    lw $t0,40($sp) #40 : 24 + 16 

要存儲在堆棧中的第5說法,你應該知道這一點:

如果vbsme會調用另一個函數,那麼堆棧底部4個字應被保存以供被調用者在那裏存儲參數值。如果超過4個參數傳遞,則應爲每個參數保存一個額外的單詞。

vbsme's stack frame bottom part (Argument building area) 

    | ...  | 
    --------------- 
    | 5th arg | <---- sw  $t5,16($sp)  
    --------------- 
    |  D  | 
    --------------- 
    |  C  | 
    --------------- 
    |  B  | 
    --------------- 
    |  A  | 
    --------------- <--sp (of vbsme stack frame) 

此外,$ RA寄存器應在堆棧的頂部被保存,因爲它的寄存器31

vbsme: 
    subu $sp, $sp, 20+N # 20: space for 5 arguments, 
          #N space for other stuff (ra,$tx, etc) 


    #Set arguments (assumes 5th parameter value is in register $t5) 
    subi $a3, $s0, 1  # 4th parameter: i-1 
    sw  $t5,16($sp)  # 

    ... 
.end 

針對

Why is it that you do: 
lw $t0,40($sp) 
to get the 5th argument, why did you add 24 to 16? when you do 
sub $sp,$sp,24 
don't you already move 
the sp 24 place? 

是,$ SP + 24分給主叫方的基地。但是,那不是我放置第五個參數的地方。第五個參數是放在呼叫者堆棧的第五個字,這就是爲什麼我加16。

+0

那爲什麼你這樣做: LW $ t0,40($ SP)#40:24 + 16 獲得第五參數,爲什麼你加24到16?當你做 sub $ sp,$ sp,24你不移動sp 24的地方嗎? – aherlambang 2010-02-19 22:02:56

+0

爲什麼我需要保存$ a0 - $ a4以及堆棧? – aherlambang 2010-02-19 22:03:18

+0

其被調用者將參數存儲在堆棧中的約定。 GCC在彙編這樣,當它與沒有優化使用,但接入參數從登記到-01 – Tom 2010-02-19 22:22:52