# # Autor(s) : Jordi Ferrer Plana # e-mail : jferrerp@eia.udg.es # Branch : - # # Working Group : Departament d'Electrònica, Informàtica i Automàtica # Project : Examen d'ETIS/ETIG d'Estructura i Tecnologia de Computadors, # 2ona convocatòria, any 2004. # Homepage : http://eia.udg.es/etc/ # # Module : Problema 5. La Piràmide de MIPS. # # File : piramide.s # Date : 04/07/2004 - 10/07/2004 # # Compiler : Spim 6.3 # Libraries : - # # Notes : - # # ---------------------------------------------------------------------------- # # 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. # # ---------------------------------------------------------------------------- # .data # # Reservar espai per 25 Files (n = 24 -> [0..24] = 25 Files) # Per n = 0 => ( n + 1 )^2 * 3 = 1 * 3 = 3 Bytes # n = 1 => ( n + 1 )^2 * 3 = 4 * 3 = 12 Bytes # ... # n = 24 => ( n + 1 )^2 * 3 = 25 * 25 * 3 = 1875 Bytes # Piramide: .space 1875 .end .text # # emplenar_cel_la ( Base : Enter, Columna : Enter, Fila : Enter, # D1 : Byte, D2 : Byte, D3 : Byte ); # # NOTES: # En conveni MIPS: # Es pot utilitzar $t0 - $t9 dins la funció sense guardar-los. # Els paràmetres estaran a: # a0: Base : Enter # a1: Columna : Enter # a2: Fila : Enter # a3: D1 : Byte # A partir del 4art estaran a la pila (tot i que són bytes, es # reserven paraules enteres per mantenir-la alineada a "word"): # 4($sp): D2 : Byte # 0($sp): D3 : Byte # # No es guardarà res a la pila ja que no cal. # emplenar_cel_la: # Comprovar el rang vàlid de Columna [0..Fila * 2] sll $t0, $a2, 1 # Fila = 0 -> Rang Columna = [0..0] bltz $a1, Fi_C # Fila = 1 -> Rang Columna = [0..2] bgt $a1, $t0, Fi_C # ... # Fila = Fila => Rang Columna = [0..Fila * 2] # Adreça de la cel.la = # Base + ( Fila * Fila * 3 + Columna * 3 ) = # Base + ( Fila^2 + Columna ) * 3 mul $t0, $a2, $a2 # $t0 = Fila * Fila = Fila^2 add $t0, $t0, $a1 # $t0 = Fila^2 + Columna sll $t1, $t0, 1 # $t1 = ( Fila^2 + Columna ) * 2 add $t0, $t0, $t1 # $t0 = ( Fila^2 + Columna ) * 3 add $t0, $a0, $t0 # $t0 = Base + ( Fila^2 + Columna ) * 3 sb $a3, 0($t0) # Escriure la dada D1 a l'offset +0 lw $t1, 4($sp) # Paràmetre D2 de la Pila sb $t1, 1($t0) # Escriure la dada D2 a l'offset +1 lw $t1, 0($sp) # Paràmetre D3 de la Pila sb $t1, 2($t0) # Escriure la dada D3 a l'offset +2 Fi_C: jr $ra # Retornar a l'invocador d'emplenar_cel_la .end .text # # emplenar_perimetre ( Base : Enter, Fila : Enter, # D1 : Byte, D2 : Byte, D3 : Byte ); # # NOTES: # En conveni MIPS: # Es pot utilitzar $t0 - $t9 dins la funció sense guardar-los. # Els paràmetres estaran a: # a0: Base : Enter # a1: Fila : Enter # a2: D1 : Byte # a3: D2 : Byte # A partir del 4art estaran a la pila (tot i que és un byte, es # reserva tota una paraula per mantenir-la alineada a "word"): # 0($sp): D3 : Byte # emplenar_perimetre: subu $sp, $sp, 8 # Establir bloc d'activació de la funció sw $ra, 0($sp) # Guardar adreça de retorn sw $fp, 4($sp) # Guardar el Frame Pointer addi $fp, $sp, 8 # $fp ara apunta a la base dels paràmetres # d'emplenar_perimetre que hi ha a la pila subu $sp, $sp, 20 # Fer espai a la pila (20 Bytes) sw $a1, 0($sp) # Guardar ($a1, $a2, $a3) ja que es sw $a2, 4($sp) # modificaran. sw $a3, 8($sp) # $a0 no es guarda ja que no canviarà. sw $s0, 12($sp) # Salvar ($s0, $s1) ja que són "calle-save" sw $s1, 16($sp) # i es modificaran. move $s0, $a1 # $s0 = Fila (Abans que es modifiqui $a1) sll $s1, $a1, 1 # $s1 = Fila * 2 (Guardar Fila i Fila * 2) lw $t2, 0($fp) # Recuperar D3 de la pila subu $sp, $sp, 8 # Fer espai per passar D2 i D3 a emplenar_cel_la sw $a3, 4($sp) # Guardar ordenadament D2 sw $t2, 0($sp) # i D3 a la pila move $a3, $a2 # $a3 = D1 # Primer emplenar les diagonals del perímetre li $a2, 0 # Fila = 0 LoopD: bgt $a2, $s0, Fi_P # Mentre ( FilaActual <= Fila ) li $a1, 0 # Primera Columna = 0 jal emplenar_cel_la # Cridar a emplenar_cel_la sll $a1, $a2, 1 # Darrera Columna = FilaActual * 2 jal emplenar_cel_la # Cridar a emplenar_cel_la addi $a2, $a2, 1 # Propera Fila j LoopD Fi_P: # Emplenar la Fila Horitzontal del perímetre li $a1, 0 # Començar a la Columna 0 move $a2, $s0 # Fila LoopH: bgt $a1, $s1, Fi_H # Mentre ( Columna <= Fila * 2 ) jal emplenar_cel_la # Cridar a emplenar_cel_la addi $a1, $a1, 1 # Propera Columna j LoopH Fi_H: addi $sp, $sp, 8 # Eliminar paràmetres D2 i D3 de la Pila lw $a1, 0($sp) # Restaurar ($a1, $a2, $a3) lw $a2, 4($sp) lw $a3, 8($sp) lw $s0, 12($sp) # Restaurar ($s0, $s1) ja que són lw $s1, 16($sp) # calle-save. addi $sp, $sp, 20 # Desempilar-los lw $ra, 0($sp) # Restaurar l'adreça de retorn lw $fp, 4($sp) # Restaurar el Frame Pointer addi $sp, $sp, 8 # Eliminar bloc d'activació de la funció jr $ra # Retornar a l'invocador de emplenar_perimetre .end .text # # Exemple de crida a emplenar_perimetre: # # emplenar_perimetre ( Piramide, 24, 1, 2, 3 ); # main: subu $sp, $sp, 4 # Fer espai a la pila per guardar l'adreça sw $ra, 0($sp) # de retorn a la invocadora de "main". la $a0, Piramide # Paràmetre 1er: Adreça Base li $a1, 24 # Paràmetre 2on: Fila li $a2, 1 # Paràmetre 3er: D1 li $a3, 2 # Paràmetre 4rt: D2 li $t0, 3 # Paràmetre 5è : D3 subu $sp, $sp, 4 # Fer espai a la pila sw $t0, 0($sp) # Passar el paràmetre 5è per la Pila. jal emplenar_perimetre # Cridar a "emplenar_perimetre". addi $sp, $sp, 4 # Desempilar el paràmetre. li $v0, 0 # Valor de retorn a la invocadora de "main". lw $ra, 0($sp) # Recuperar adreça de retorn de la Pila. addu $sp, $sp, 4 # Desempilar adreça de retorn de "main". jr $ra # Retornar a l'invocador (Spim). .end