# # 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, # 1era convocatòria, any 2003. # Homepage : http://eia.udg.es/etc/ # # Module : Exercici 5. Transposta d'una matriu. # # File : transextes.s # Date : 11/06/2003 - 30/06/2003 # # Compiler : Spim 6.3 # Libraries : - # # Notes : - Càlcul de la transposta d'una Matriu de dimensions N x M. # - Problema extès: llegir les dades i escriure els resultats # per testejar que l'algoritme funciona. # # ---------------------------------------------------------------------------- # # 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 N=3 # Matriu d'N Files M=2 # per M Columnes S=24 # S = N * M * 4 ( L'Spim 6.3 no precompila # expressions p.e. N * M * 4 ) # Un 'float' ocupa 4 bytes * N Files * M Columnes Matriu: .space S # Reservar espai per la matriu origen Resultat: .space S # Reservar espai per la matriu resultant # Cadenes de caràcters que s'escriuran per pantalla TextMatriuOriginal: .asciiz "\nMatriu Original:\n" TextMatriuTransposta: .asciiz "\nMatriu Transposta:\n" .end .text # Primer segment de text (codi) main: # Funció principal 'main' subu $sp, $sp, 4 # Reservar espai pels registres a salvar sw $ra, 0($sp) # Salvar l'adreça de retorn ja que es modificarà # No s'utilitza el 'Frame Pointer', no cal # 3 paràmetres passats per registre la $a0, Matriu # 1er paràmetre (adreça de la matriu) li $a1, N # 2on paràmetre (número de files) li $a2, M # 3er paràmetre (número de columnes) jal llegirMatriu # Cridar la funció per obtenir la matriu de teclat li $t0, N # $t0 = N (total de files) li $t1, M # $t1 = M (total de columnes) li $t2, 0 # $t2 = i <- 0 for ( i = 0; Fori: # For exterior ( i ) slt $t5, $t2, $t0 # $t5 <- i < N ; i < N; beq $t5, $0, ExitFori # Si $t5 == 0 -> Acabar les iteracions de i li $t3, 0 # $t3 = j <- 0 for ( j = 0; Forj: # For interior ( j ) slt $t5, $t3, $t1 # $t5 <- j < M ; j < M; beq $t5, $0, ExitForj # Si $t5 == 0 -> Acabar les iteracions de j # Copiar el valor Mij a Rji # L'origen és a i * M + j # $t2 * $t1 + $t3 mul $t5, $t2, $t1 # $t5 <- $t2 * $t1 (i * M) add $t5, $t5, $t3 # $t5 <- $t5 + $t3 (i * M + j) sll $t5, $t5, 2 # $t5 <- $t5 * 4 (i * M + j) * 4 (floats) lw $t4, Matriu($t5) # $t4 <- Matriu[ ( i * M + j ) * 4 ] # El destí es a j * N + i # $t3 * $t0 + $t2 mul $t5, $t3, $t0 # $t5 <- $t3 * $t0 (j * N) add $t5, $t5, $t2 # $t5 <- $t5 + $t2 (j * N + i) sll $t5, $t5, 2 # $t5 <- $t5 * 4 (j * N + i) * 4 (floats) sw $t4, Resultat($t5) # Resultat[ ( j * N + i ) * 4 ] <- $t4 addi $t3, $t3, 1 # $t3 <- $t3 + 1 ; j++ ) j Forj ExitForj: addi $t2, $t2, 1 # $t2 <- $t2 + 1 ; i++ ) j Fori ExitFori: li $v0, 4 # Escriure text per pantalla la $a0, TextMatriuOriginal syscall # 3 paràmetres passats per registre la $a0, Matriu # 1er paràmetre (adreça de la matriu incial) li $a1, N # 2on paràmetre (número de files) li $a2, M # 3er paràmetre (número de columnes) jal escriureMatriu # Cridar la funció per escriure la matriu a pantalla li $v0, 4 # Escriure text per pantalla la $a0, TextMatriuTransposta syscall # 3 paràmetres passats per registre la $a0, Resultat # 1er paràmetre (adreça de la matriu resultat) li $a1, M # 2on paràmetre (número de files) li $a2, N # 3er paràmetre (número de columnes) jal escriureMatriu # Cridar la funció per escriure la matriu a pantalla or $v0, $0, $0 # Retornar un 0 al Sistema Operatiu (Spim) lw $ra, 0($sp) # Restaurar l'adreça de retorn salvada addu $sp, $sp, 4 # Eliminar espai de pila reservat j $ra # Retorn al Sistema Operatiu (Spim) .end .data # Segment de dades per les funcions # llegirMatriu i escriureMatriu TextEntraMatriuA: .asciiz "Entra la matriu de " TextEntraMatriuB: .asciiz " files per " TextEntraMatriuC: .asciiz " columnes per teclat" TextEntraFila: .asciiz "Entra els elements de la fila " TextEntraElementColumna: .asciiz " Element de la columna " TextDosPunts: .asciiz ":" TextEspai: .asciiz " " TextEnter: .asciiz "\n" .end .text # Segment de codi per la funció llegirMatriu llegirMatriu: # Funció llegirMatriu # Els arguments es passen per registre (menys de 5) # $a0, $a1 i $a2: l'adreça de la matriu, el número # de files i el número de columnes respectivament move $t7, $a0 # $t7 <- adreça inicial de la matriu move $t0, $a1 # $t0 <- número de files move $t1, $a2 # $t1 <- número de Columnes li $v0, 4 # Escriure text per pantalla la $a0, TextEntraMatriuA syscall li $v0, 1 # Escriure el número de files per pantalla move $a0, $t0 syscall li $v0, 4 # Escriure text per pantalla la $a0, TextEntraMatriuB syscall li $v0, 1 # Escriure el número de columnes per pantalla move $a0, $t1 syscall li $v0, 4 # Escriure text per pantalla la $a0, TextEntraMatriuC syscall li $v0, 4 # Escriure dos punts (':') per pantalla la $a0, TextDosPunts syscall li $v0, 4 # Escriure un espai en blanc per pantalla la $a0, TextEspai syscall li $v0, 4 # Escriure un salt de linia per pantalla la $a0, TextEnter syscall li $t2, 0 # $t2 = i <- 0 for ( i = 0; lMFori: # For exterior ( i ) slt $t5, $t2, $t0 # $t5 <- i < N ; i < N; beq $t5, $0, lMExitFori # Si $t5 == 0 -> Acabar les iteracions de i li $v0, 4 # Escriure el text per pantalla la $a0, TextEntraFila syscall li $v0, 1 # Escriure número de fila actual per pantalla move $a0, $t2 addi $a0, $a0, 1 # Escriure el número de fila [1..n] enlloc [0..n-1] syscall li $v0, 4 # Escriure dos punts ':' per pantalla la $a0, TextDosPunts syscall li $v0, 4 # Escriure un salt de linia per pantalla la $a0, TextEnter syscall li $t3, 0 # $t3 = j <- 0 for ( j = 0; lMForj: # For interior ( j ) slt $t5, $t3, $t1 # $t5 <- j < M ; j < M; beq $t5, $0, lMExitForj # Si $t5 == 0 -> Acabar les iteracions de j # Obtenir l'offset segons fila i columna # Offset es a i * M + j # $t2 * $t1 + $t3 mul $t5, $t2, $t1 # $t5 <- $t2 * $t1 (i * M) add $t5, $t5, $t3 # $t5 <- $t5 + $t3 (i * M + j) sll $t5, $t5, 2 # $t5 <- $t5 * 4 (i * M + j) * 4 (floats) add $t5, $t5, $t7 # $t5 <- Adreça de la matriu + offset de l'element li $v0, 4 # Escriure el text per pantalla la $a0, TextEntraElementColumna syscall li $v0, 1 # Escriure número de columna actual per pantalla move $a0, $t3 addi $a0, $a0, 1 # Escriure el número de fila [1..n] enlloc [0..n-1] syscall li $v0, 4 # Escriure dos punts (':') per pantalla la $a0, TextDosPunts syscall li $v0, 4 # Escriure un espai en blanc per pantalla la $a0, TextEspai syscall li $v0, 6 # Llegir un 'float' pel teclat syscall mfc1 $t4, $f0 # $t4 <- el 'float' llegit (a $0) sw $t4, 0($t5) # Matriu[ ( i * M + j ) * 4 ] <- $t4 addi $t3, $t3, 1 # $t3 <- $t3 + 1 ; j++ ) j lMForj lMExitForj: addi $t2, $t2, 1 # $t2 <- $t2 + 1 ; i++ ) j lMFori lMExitFori: jr $ra # Retornar a l'invocador .end .data # Segment de dades per les funcions # llegirMatriu i escriureMatriu TextPipe: .asciiz "|" .end .text # Segment de codi per la funció escriureMatriu escriureMatriu: # Funció escriureMatriu # Els arguments es passen per registre (menys de 5) # $a0, $a1 i $a2: l'adreça de la matriu, el número # de files i el número de columnes respectivament move $t7, $a0 # $t7 <- adreça inicial de la matriu move $t0, $a1 # $t0 <- número de files move $t1, $a2 # $t1 <- número de Columnes li $t2, 0 # $t2 = i <- 0 for ( i = 0; eMFori: # For exterior ( i ) slt $t5, $t2, $t0 # $t5 <- i < N ; i < N; beq $t5, $0, eMExitFori # Si $t5 == 0 -> Acabar les iteracions de i li $v0, 4 # Escriure el text per pantalla la $a0, TextPipe syscall li $v0, 4 # Escriure una pipe ('|') per pantalla la $a0, TextEspai syscall li $t3, 0 # $t3 = j <- 0 for ( j = 0; eMForj: # For interior ( j ) slt $t5, $t3, $t1 # $t5 <- j < M ; j < M; beq $t5, $0, eMExitForj # Si $t5 == 0 -> Acabar les iteracions de j # Obtenir l'offset segons fila i columna # Offset es a i * M + j # $t2 * $t1 + $t3 mul $t5, $t2, $t1 # $t5 <- $t2 * $t1 (i * M) add $t5, $t5, $t3 # $t5 <- $t5 + $t3 (i * M + j) sll $t5, $t5, 2 # $t5 <- $t5 * 4 (i * M + j) * 4 (floats) add $t5, $t5, $t7 # $t5 <- Adreça de la matriu + offset de l'element lw $t4, 0($t5) # Obtenir l'element li $v0, 2 # Escriure el 'float' per pantalla mtc1 $t4, $f12 syscall li $v0, 4 # Escriure un espai en blanc per pantalla la $a0, TextEspai syscall addi $t3, $t3, 1 # $t3 <- $t3 + 1 ; j++ ) j eMForj eMExitForj: li $v0, 4 # Escriure una pipe ('|') per pantalla la $a0, TextPipe syscall li $v0, 4 # Escriure un salt de linia per pantalla la $a0, TextEnter syscall addi $t2, $t2, 1 # $t2 <- $t2 + 1 ; i++ ) j eMFori eMExitFori: jr $ra # Retornar a l'invocador .end