# # 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 : Multiplicació de matrius en assemblador de MIPS. # MIPS (SPIM). # # File : matmult.s # Date : 19/05/2005 - 24/05/2005 # Encoding : ISO-8859-1 (Latin-1) # # Compiler : SPIM >= ver. 6.5 # Libraries : - # # Notes : - Realitza la multiplicació de dues matrius A i B de # A = M files x N columnes i B = N files x O Columnes. # - El resultat s'emmagatzema en una matriu C de # N files x O columnes. # - Les matrius A, B i C es defineixen com a vectors i # s'indexen de la mateixa forma. # - S'ha implementat una acció per imprimir els resultats. # # ---------------------------------------------------------------------------- # # Copyright (C) 2002-2004, 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. # # ---------------------------------------------------------------------------- # M=2 # Constants amb les mides de les matrius N=3 O=4 .data # Les dades A: .word 1, 2, 3, # Matriu constant A d'enters .word 4, 5, 6 # d'M files x N columnes B: .word 1, 2, 3, 4 # Matriu constant B d'enters .word 5, 6, 7, 8 # d'N files x O columnes .word 9, 10, 11, 12 C: .space 32 # Reservar espai per la Matriu C # resultant d'M files x O columnes. # Espai = M * O * 4 (Words) = 2 * 4 * 4 = 32 # Cadenes "asciiz" per presentar els resultats Space: .asciiz " " # Cadena amb l'"Espai en blanc" Enter: .asciiz "\n" # Cadena amb el "Salt de línia" .text # El programa principal main: subu $sp, $sp, 16 # Fer espai a la pila per guardar registres sw $ra, 0($sp) # Guardar $ra (Adreça de retorn) sw $fp, 4($sp) # Guardar $fp (Frame pointer) sw $a0, 8($sp) # S'utilitzen $a0 i $a1 temporalment sw $a1, 12($sp) addu $fp, $sp, 16 # Apuntar $fp a la base dels paràmetres li $t4, M # $t4 <- M (Files d'A i C) li $t5, N # $t5 <- N (Columnes d'A i Files de B) li $t6, O # $t6 <- O (Columnes de B i C) li $t0, 0 # $t0 <- i = 0 fori: bge $t0, $t4, exitfi # Iteració per recórrer Files de C li $t1, 0 # $t1 <- j = 0 forj: bge $t1, $t6, exitfj # Iteració per recórrer Columnes de C li $t3, 0 # $t3 <- s = 0 li $t2, 0 # $t2 <- k = 0 fork: bge $t2, $t5, exitfk # Iteració per Columnes d'A i Files de B # Multiplicar elements: A[i][k] i B[k][j] # Cercar A[i][k] mul $a0, $t0, $t5 # i * N add $a0, $a0, $t2 # i * N + k sll $a0, $a0, 2 # ( i * N + k ) * 4 lw $a0, A($a0) # $a0 <- A[( i * N + k ) * 4] = A[i][k] # Cercar B[k][j] mul $a1, $t2, $t6 # k * O add $a1, $a1, $t1 # k * O + j sll $a1, $a1, 2 # ( k * O + j ) * 4 lw $a1, B($a1) # $a1 <- B[( k * O + j ) * 4] = B[k][j] mul $a0, $a0, $a1 # Fer la multiplicació dels dos elements add $t3, $t3, $a0 # $t3 <- $t3 + A[( i * N + k ) * 4] * # B[( k * O + j ) * 4] addi $t2, $t2, 1 # Propera iteració del for i j fork exitfk: # Guardar resultat a l'element C[i][j] mul $a0, $t0, $t6 # i * O add $a0, $a0, $t1 # i * O + j sll $a0, $a0, 2 # ( i * O + j ) * 4 sw $t3, C($a0) # C[( i * O + j )] = C[i][j] <- $t3 addi $t1, $t1, 1 # Propera iteració del for j j forj exitfj: addi $t0, $t0, 1 # Propera iteració del for i j fori exitfi: # Escriure la matriu C # Passar els paràmetres: la $a0, C # $a0 <- Adreça de la Matriu C li $a1, M # $a1 <- Número de Files li $a2, O # $a2 <- Número de Columnes jal printm # Cricar a imprimir Matriu # Acció printm no retorna res lw $ra, 0($sp) # Recuperar els valors guardats a la pila lw $fp, 4($sp) # pels registres modificats lw $a0, 8($sp) lw $a1, 12($sp) addu $sp, $sp, 16 # Deixar la pila com estava abans d'entrar li $v0, 0 # Retornar un 0 a l'invocador jr $ra # Retornar de main .end .text .ent printm # Cal passar paràmetres a la funció: printm: # $a0 = Adreça de la Matriu # $a1 = Files # $a2 = Columnes subu $sp, $sp, 12 # Fer espai a la pila per guardar registres sw $ra, 0($sp) # Guardar $ra (Adreça de retorn) sw $fp, 4($sp) # Guardar $fp (Frame pointer) sw $v0, 8($sp) # Guardar $v0 (Registre valor de retorn) add $fp, $sp, 12 # Apuntar $fp a la base dels paràmetres move $t2, $a0 # Guardar temporalment ja que s'ha # d'utilitzar $a0 pel syscall li $t0, 0 # $t0 <- i forip: bge $t0, $a1, extfip # Mentre i < Número de Files li $t1, 0 # $t1 <- j forjp: bge, $t1, $a2, extfjp # Mentre j < Número de Columnes mul $v0, $t0, $a2 # Cercar element [i][j] de la matriu add $v0, $v0, $t1 # que estarà a Mat[i * Columnes + j] sll $v0, $v0, 2 # Multiplicar per 4 (accedir a matriu de words) add $v0, $v0, $t2 # @Matriu = $a0 + Offset element i, j lw $a0, 0($v0) # Carregar l'element [i][j] de la matriu li $v0, 1 # Funció escriure enter syscall # Crida al sistema li $v0, 4 # Funció escriure cadena la $a0, Space # Adreça de la cadena "Espai en blanc" syscall # Crida al sistema addi $t1, $t1, 1 # j++ j forjp # Propera iteració extfjp: li $v0, 4 # Funció escriure cadena la $a0, Enter # Adreça de la cadena "Salt de línia" syscall # Crida al sistema addi $t0, $t0, 1 # i++ j forip # Propera iteració extfip: move $a0, $t2 # Recuperar adreça de la matriu guardada a $t2 lw $ra, 0($sp) # Recuperar registres empilats lw $fp, 4($sp) lw $v0, 8($sp) addu $sp, $sp, 12 # Deixar la pila com estava inicialment jr $ra # Tornar a l'invocador .end printm .end