2010-02-19 4 views
2

Je comprends que chaque fois que j'ai une fonction qui a plus de quatre arguments dans MIPS, je devrais utiliser la pile. Cependant dans mon code ci-dessous après avoir enregistré le cinquième argument à sw $t0, 4($sp) et faire un jal sad, puis au début de la fonction sad j'ajuste à nouveau le pointeur de pile pour enregistrer les registres $sx qui est utilisé par l'appelant. Est-ce que je fais quelque chose de mal ici?Appel de fonction MIPS avec plus de quatre arguments

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

Je ne vois pas comment le titre se rapporte à la question. – Tom

+1

Il fait, je me demande comment obtenir le cinquième argument de la fonction triste – aherlambang

Répondre

4

Voici comment cela est fait par gcc. Pour plus d'informations, vous (pourriez) devriez lire le Mips ABI. Certaines choses peuvent différer.

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

Par convention, le cinquième argument devrait aller sur le cinquième mot de la pile.

Vous devez

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 

Pour stocker le 5ème argument dans la pile, vous devez savoir ceci:

Si vbsme va appeler une autre fonction, puis le fond 4 mots de la pile devrait être sauvegardé pour l'appelé pour y stocker les valeurs d'argument. Si plus de 4 arguments sont passés, un mot supplémentaire doit être enregistré pour chaque argument.

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

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

En outre, le registre $ ra doit être enregistré au sommet de la pile, depuis son registre 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 

En réponse à

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? 

Oui, $ sp + 24 points à la base de la pile de l'appelant. Cependant, ce n'est pas où j'ai placé le cinquième argument. Le cinquième argument est placé sur le cinquième mot de la pile des appelants, c'est pourquoi j'ajoute 16.

+0

pourquoi est-ce que vous faites: $ pv t0,40 (sp $) # 40: 24 + 16 pour obtenir le 5 arguments , pourquoi avez-vous ajouté 24 à 16? quand vous faites sub $ sp, $ sp, 24 ne déplacez-vous pas déjà le SP 24 place? – aherlambang

+0

Pourquoi ai-je besoin d'économiser $ a0 - $ a4 à la pile? – aherlambang

+0

Sa convention pour l'appelé de stocker les arguments dans la pile. GCC génère l'assemblage de cette façon quand il est utilisé sans optimisations, mais accéder aux arguments des registres avec -01 – Tom

Questions connexes