2010-02-19 5 views
1

J'essaie d'avoir la fonction vbsme appeler une autre fonction appelée triste ... est la procédure suivante correcte sur la sauvegarde des registres et l'adresse de retour ?? l'appelant est censé enregistrer le registre $ t0- $ t7, mais où et comment dois-je faire?MIPS fonction à l'intérieur d'une fonction

vbsme: li $v0, 0 # reset $v0 
    li $v1, 0 # reset $v1 
    li $t0, 1 # i(row) = 1 
    li $t1, 1 # j(col) = 1 
    lw $t2, 0($a0) # row size 
    lw $t3, 4($a0) # col size 
    mul $t4, $t2, $t3 # row * col 
    li $t5, 0 # element = 0 
    loop: bgeq $t5, $t4, exit # if element >= row * col then exit 

    addi $sp, $sp, -16 # create space on the stack pointer 
    sw $ra, -12($sp) # save return address 
    sw $s6, -8($sp) # save return address 
    sw $s7, -4($sp) # save return address 
    subi $s7, $t0, 1 # 1st parameter: i-1 
    subi $s6, $t1, 1 # 2nd parameter: j-1 
    jal sad # calculate the sum of absolute difference using the frame starting from row a0 and col a1 
    lw $ra, -12($sp) # restore return address 
    lw $s6, -8($sp) 
    lw $s7, -4($sp) 
    addi $sp, $sp, 16 # restore stack pointer 
    jr $ra 
+0

J'ai re écrit ma réponse, $ s0 .. $ s7 sont appelant registres – Tom

Répondre

2

sx $ registres sont garantis inchangés les appels de fonction accross, de sorte que son la callee (fonction somme) la responsabilité de les sauver, que si sa va changer leur valeur.

$ Les registres tx, d'autre part, ne sont pas garantis d'être inchangés par rapport aux appels de fonction, c'est donc la responsabilité de l'appelant (vbsme) de les enregistrer.

Vous devriez enregistrer $ sx dans la pile callee.

Ainsi, lorsque vous commencez à coder la fonction de somme, vous devez économiser de l'espace dans la pile Si vous souhaitez enregistrer n registres, enregistrez n * 4.

L'espace dans la pile est sauvegardé en soustrayant sur le registre $ sp, qui pointe vers la base de la pile. Avant votre code de fonction, vous devez créer la pile pour cette fonction, l'enregistrement tous les registres sauvegardés par l'appelant, le retour des registres d'adresse et de pointeur global lorsque neccesary

sum: 
     #stack frame creation. Caller registers saved, 
     # return address and frame pointer 

     subu $sp,$sp,36 #Save space in the stack for registers $s0, $s7 + $ra 
     sw $ra,32($sp) 
     sw $s0,0($sp) 
     sw $s1,4($sp) 
     #and so on. Note that also you should save the $ra register only if you are 
     # going to call another function 

     #do something with $sx 

     #stack frame destruction 
     #restore $sx and $ra registers 
     lw $ra,32($sp) 
     lw $s0,0($sp) 
     lw $s1,4($sp) 
     ... 
     lw $s7,28($sp) 

     jr $ra 

Par ailleurs, par convention, les registres a0 $, a3 $ devrait Conservez les arguments de la fonction que vous appelez. Notez également que, parce que vous utilisez les registres $ s0, $ s7, vous devez faire un peu plus de travail. La Convention dit que si vous ne les utilisez pas, vous ne devriez pas les sauvegarder, alors peut-être pourriez-vous utiliser les registres $ tx (temporaires) à la place.

+0

doit épargné pas l'appelant sauvegarde de registre t0- $ t7 $ au lieu des registres de $? – aherlambang

+0

vbsme voici l'appelant à la fonction de somme droite? – aherlambang

+0

vbsme appelant, somme callee – Tom

1

Alexander,

Qu'est-ce que Tom dit est à peu près la chose importante corriger de prendre note avec la programmation faire dans l'assemblage est tout est par convention. Tandis que dans MIPS la convention commune est ce que Tom a noté ce n'est pas la seule convention. Par exemple, si vous utilisez des macros (qui, si vous allez écrire plus de 1 ou 2 fonctions dans l'assemblage, il est beaucoup plus facile d'utiliser des macros), vous pouvez définir votre convention d'appel dans la macro. La façon la plus simple de faire cela est de faire en sorte que l'appelant conserve la pile pour que l'appelant sauvegarde la pile. C'est moins efficace parce que parfois (peut-être plusieurs fois) les registres inutilisés seront sauvegardés, mais cela vous épargnera beaucoup de chagrin parce que votre convention est appliquée de manière cohérente.

appelant Stack Economie:

sw $fp 0($sp) # save the old frame pointer 
    addu $fp $sp $0 # move the frame pointer to point at top of frame 
    subu $sp $sp 44 # move the stack pointer down 44 
    sw $fp 40($sp) # save the old stack pointer 
    sw $ra 36($sp) # save the return address 
    sw $s0 32($sp) # save registers $s0 - $s7 
    sw $s1 28($sp) 
    sw $s2 24($sp) 
    sw $s3 20($sp) 
    sw $s4 16($sp) 
    sw $s5 12($sp) 
    sw $s6 8($sp) 
    sw $s7 4($sp) 

appel Fonction

jal my_func 

appelant Stack Restaurez

subu $sp $fp 44 # move the stack pointer to the orginal unmodified bottom 
    lw $ra 36($sp) # load the return address 
    lw $s0 32($sp) # load registers $s0 - $s7 
    lw $s1 28($sp) 
    lw $s2 24($sp) 
    lw $s3 20($sp) 
    lw $s4 16($sp) 
    lw $s5 12($sp) 
    lw $s6 8($sp) 
    lw $s7 4($sp) 
    lw $fp 44($sp) # load the old frame pointer 
    lw $sp 40($sp) # load the old stack pointer 

Votre fonction:

my_func: 
    do some stuff 
    jr $ra    # return to the previous function 

Comme je l'ai dit, la meilleure façon d'appliquer cette convention est d'utiliser des macros. J'ai fait un projet dans SPIM (que vous utilisez peut-être ou vous ne pouvez pas) pour un cours. Dans le cadre du projet, nous avons écrit un moteur de macro (il fait aussi d'autres choses cool) pour SPIM vous pouvez l'obtenir ici: http://github.com/timtadh/mpp Je vous recommande également de vérifier http://github.com/timtadh/jist qui est un système d'exploitation de jouet écrit au-dessus de SPIM. Cela vous donnera une idée de la façon d'utiliser le moteur de macro.

acclamations

Questions connexes