# # Autor(s) : Jordi Ferrer Plana # e-mail : jferrerp@eia.udg.es # Branch : Estructura i Tecnologia de Computadors (ETIS/ETIG) # # Working Group : Departament d'Electrònica, Informàtica i Automàtica # Project : Exemples # # Homepage : http://eia.udg.es/etc/ # # Module : Càlcul del factorial recursivament en assemblador # de MIPS (SPIM). # # File : fact_mips.s # Date : 16/05/2003 - 18/05/2006 # Encoding : ISO-8859-1 (Latin-1) # # Compiler : SPIM >= ver. 6.5 # Libraries : - # # Notes : - Realitza el factorial d'un valor d'entrada utilitzant # una funció recursiva. # - Es passa l'únic paràmetre pel registre $a0 seguint el # conveni dels compiladors de MIPS i del compilador gcc. # - El compilador de MIPS sempre reserva un espai de 32 # bytes pel "bloc d'activació de les funcions" a on es # guarden els registres $ra i $fp, tot i que no s'ocupi # del tot ($ra es guarda). # - Com que aquest codi és generat a ma, es reserva l'espai # just (8 bytes). # # ---------------------------------------------------------------------------- # # Copyright (C) 2002-2003, Jordi Ferrer Plana # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # See the GNU General Public License (http://www.gnu.org/copyleft/) # for more details. # # ---------------------------------------------------------------------------- # .text # Primer segment de text (codi) main: # Funcio principal 'main' subu $sp, $sp, 8 # Reservar espai pels registres a salvar sw $ra, 0($sp) # Salvar l'adreça de retorn ja que es modificarà sw $fp, 4($sp) # Salvar el Frame Pointer ja que es modificarà addu $fp, $sp, 8 # Establir el Frame Pointer per 'main' la $a0, Cadena # Adreça de la cadena a $a0 li $v0, 4 # Funció escriure cadena (print_string) syscall # Crida al sistema # Cridar 'Fact' per calcular el factorial de 10 li $a0, 10 # Paràmetre de 'Fact': 10 jal Fact # Crida a 'Fact' # 'Fact' ha retornat el resultat a $v0 move $a0, $v0 # El resultat és el paràmetre de print_int li $v0, 1 # Funció escriure enter (print_int) syscall # Crida al sistema or $v0, $0, $0 # Retornar un 0 al Sistema Operatiu (Spim) lw $ra, 0($sp) # Restaurar l'adreça de retorn salvada lw $fp, 4($sp) # Restaurar l'antic Frame Pointer salvat addu $sp, $sp, 8 # Eliminar espai de pila reservat j $ra # Retorn al Sistema Operatiu (Spim) .end .text # Segon segment de text (codi) Fact: # Funció 'Fact ( n )' que calcula el factorial subu $sp, $sp, 8 # Reservar espai pels registres a salvar sw $ra, 0($sp) # Salvar l'adreça de retorn ja que es modificarà sw $fp, 4($sp) # Salvar el Frame Pointer ja que es modificarà addu $fp, $sp, 8 # Establir el Frame Pointer per 'Fact' bgtz $a0, Recursiu # Si n > 0 => Crida recursiva li $v0, 1 # n == 1 => fact ( 0 ) = 1 j FiFact # Sortir de la funcio 'Fact' Recursiu: addi $sp, $sp, -4 # Fer espai per guardar un registre sw $a0, 0($sp) # Guardar el paràmetre 'n' a la pila addi $a0, -1 # Calcular n - 1 a $a0 => Nou paràmetre de 'Fact' jal Fact # Crida recursiva # 'Fact' ha retornat el resultat a $v0 lw $t0, 0($sp) # Obtenir 'n' guardat a la pila a $t0 mul $v0, $v0, $t0 # Calcular Fact ( n - 1 ) * n addi $sp, $sp, 4 # Eliminar 'n' guardat a la pila FiFact: lw $ra, 0($sp) # Restaurar l'adreça de retorn salvada lw $fp, 4($sp) # Restaurar el Frame Pointer salvat addu $sp, $sp, 8 # Eliminar espai de pila reservat j $ra # Retornar de 'Fact' .end .data # Segment de dades: La cadena Cadena: .asciiz "El factorial de 10 és " .end