2010-02-19 103 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