# # 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, # 2era convocatòria, any 2003. # Homepage : http://eia.udg.es/etc/ # # Module : Problema 5. Producte d'un vector columna per un vector fila. # # File : prodextes.s # Date : 30/06/2003 - 01/07/2003 # # Compiler : Spim 6.3 # Libraries : - # # Notes : - Càlcul del producte d'un vector columna (n,1) per un vector # fila (1,n). El resultat és una matriu quadrada de (n,n). # # M(n,n) = x(n,1) * y(1,n) # # - El càlcul de cada un dels a elements de la màtriu és # # aij = xi * yj # # - La matriu resultant estarà contigua per files a memòria. # # - 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 # Segment de dades N=3 # Matriu resultant d'N files per N columnes Sv=12 # S = N * 4 ( L'Spim 6.3 no precompila Sm=36 # S = N * N * 4 expressions p.e. N * 4 ) x: .space Sv # Reservar espai pel vector columna x y: .space Sv # Reservar espai pel vector fila y M: .space Sm # Reservar espai per la matriu M = x * y TextCalculA: .asciiz "Calcul de M(" TextComa: .asciiz ", " TextIgual: .asciiz ") = x(" TextProducte: .asciiz ", 1) * y(1, " TextFinalFrase: .asciiz ")\n\n" TextLlegirVector: .asciiz "Entra els " TextLlegirVectorx: .asciiz " elements del vector columna x:\n" TextLlegirVectory: .asciiz " elements del vector fila y:\n" TextMatriuResultat: .asciiz "\nMatriu resultant:\n" .end .text # 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 li $v0, 4 # Escriure capçalera per pantalla la $a0, TextCalculA # 'Calcul de M(N, N) = x(N, 1) * y(1, N)' syscall # on 'N' és la constant predefinida amb el número li $v0, 1 # d'elements dels vectors li $a0, N syscall li $v0, 4 la $a0, TextComa syscall li $v0, 1 li $a0, N syscall li $v0, 4 la $a0, TextIgual syscall li $v0, 1 li $a0, N syscall li $v0, 4 la $a0, TextProducte syscall li $v0, 1 li $a0, N syscall li $v0, 4 la $a0, TextFinalFrase syscall # Entrada de dades li $v0, 4 # Escriure el text per pantalla la $a0, TextLlegirVector syscall li $v0, 1 # Funció escriure enter li $a0, N # Escriure el número de columnes del vector syscall li $v0, 4 # Escriure el final de la frase pel vector x la $a0, TextLlegirVectorx syscall # 2 paràmetres passats per registre la $a0, x # 1er paràmetre (adreça del vector) li $a1, N # 2on paràmetre (número d'elements) jal llegirVector # Cridar la funció per obtenir el vector x per teclat li $v0, 4 # Escriure el text per pantalla la $a0, TextLlegirVector syscall li $v0, 1 # Funció escriure enter li $a0, N # Escriure el número de columnes del vector syscall li $v0, 4 # Escriure el final de la frase pel vector y la $a0, TextLlegirVectory syscall # 2 paràmetres passats per registre la $a0, y # 1er paràmetre (adreça del vector) li $a1, N # 2on paràemtre (número d'elements) jal llegirVector # Cridar la funció per obtenir el vector y per teclat # Algorisme per calcular el producte dels vectors li $t0, N # $t0 <- N (total de files o columnes) li $t1, 0 # $t1 = i <- 0 for ( i = 0; Fori: # For exterior ( i ) slt $t5, $t1, $t0 # $t5 <- i < N ; i < N; beq $t5, $0, ExitFori # Si $t5 == 0 -> Acabar les iteracions de i li $t2, 0 # $t2 = j <- 0 for ( j = 0; Forj: # For interior ( j ) slt $t5, $t2, $t0 # $t5 <- j < N ; j < N; beq $t5, $0, ExitForj # Si $t5 == 0 -> Acabar les iteracions de j # Calcular l'adreça origen de x sll $t5, $t1, 2 # $t5 <- i * 4 lw $t4, x($t5) # $t4 <- x(i) # Calcular l'adreça origen de y sll $t5, $t2, 2 # $t5 <- j * 4 lw $t6, y($t5) # $t6 <- y(j) # Realitzar el càlcul de xi * yj mul $t4, $t4, $t6 # $t4 <- x(i) * y(j) # Calcular l'offset destí de M, # que és a i * N + j # $t1 * $t0 + $t2 mul $t5, $t1, $t0 # $t5 <- $t1 * $t0 (i * N) add $t5, $t5, $t2 # $t5 <- $t5 + $t2 (i * N + j) sll $t5, $t5, 2 # $t5 <- $t5 * 4 (i * N + j) * 4 (word) sw $t4, M($t5) # M[ ( i * N + j ) * 4 ] <- $t4 addi $t2, $t2, 1 # $t2 <- $t2 + 1 ; j++ ) j Forj ExitForj: addi $t1, $t1, 1 # $t1 <- $t1 + 1 ; i++ ) j Fori ExitFori: li $v0, 4 # Escriure text per pantalla la $a0, TextMatriuResultat syscall la $a0, M # 1er paràmetre (adreça de la matriu resultat) li $a1, N # 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 la funció llegirVector TextEntraVectorA: .asciiz " Entra l'element " TextEntraVectorB: .asciiz " del vector: " .end .text # Segment de codi per la funció llegirVector llegirVector: # Funció llegirVector # Els arguments es passen per registre (menys de 5) # $a0 i $a1: l'adreça del vector i el número # d'elements d'aquest move $t0, $a0 # $t0 <- adreça inicial del vector move $t1, $a1 # $t1 <- número d'elements del vector li $t2, 0 # $t2 = i <- 0 for ( i = 0; lVFori: # For ( i ) slt $t5, $t2, $t1 # $t5 <- i < N ; i < N; beq $t5, $0, lVExitFori # Si $t5 == 0 -> Acabar les iteracions de i li $v0, 4 # Escriure el text per pantalla la $a0, TextEntraVectorA syscall li $v0, 1 # Funció escriure enter addi $a0, $t2, 1 # Escriure l'index de l'element actual + 1 syscall li $v0, 4 # Escriure el final de la frase la $a0, TextEntraVectorB syscall li $v0, 5 # Llegir un enter pel teclat syscall sw $v0, 0($t0) # Vector(i) <- $v0 (escriure valor a memòria) addi $t0, $t0, 4 # Offset del següent element dins el vector addi $t2, $t2, 1 # $t2 <- $t2 + 1 ; i++ ) j lVFori lVExitFori: jr $ra .end .data # Segment de dades per la funció escriureMatriu TextPipe: .asciiz "|" TextEspai: .asciiz " " TextEnter: .asciiz "\n" .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 li $v0, 1 # Escriure l'enter de $a0 per pantalla lw $a0, 0($t7) # $a0 <- element que cal escriure syscall li $v0, 4 # Escriure un espai en blanc per pantalla la $a0, TextEspai syscall # La matriu es troba contigua per files a memòria addi $t7, $t7, 4 # $t7 <- offset del següent element 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