2.3.2 Multiplicação de matrizes de inteiros

Programa para realizar a multiplicação de uma matriz de inteiros pela sua transposta

Wolfram Mathematica Matriz Multiplicada pela Transposta
Wolfram Mathematica Matriz Multiplicada pela Transposta
/**
 * @file    mat_mult_transp_int.s
 * @author  Reficio
 * @version 1.0
 * 
 * @section DESCRIPTION
 *
 * Programa para realizar a multiplicação de uma matriz de inteiros
 * pela sua transposta.
 *
 * Cij = Somatório de k igual a 1 até m de Aik.Bkj
 *
 * ou seja, o elemento Cij do produto é obtido multiplicando-se
 * individualmente os elementos da i-ésima linha de A pelo elemento
 * correspondente da j-ésima coluna de B e somando estes produtos.
 *
 * Matriz original x Matriz Transposta =  Matriz Resultado
 *    | 1 2 |         | 1 3 5 7 |        |  5  11  17  23 |
 *    | 3 4 |         | 2 4 6 8 |        | 11  25  39  53 |
 *    | 5 6 |                            | 17  39  61  83 |
 *    | 7 8 |                            | 23  53  83 113 |
 *
 * Usa a função 'itostr' descritas no GitHub Gist
 * seenaburns/strtoi-add-argv.s
 * https://gist.github.com/seenaburns/70019f3217ab6392c3c245976e336978
 *
 * @output Matriz original, transposta e o resultado da multiplicação.
 */

// Nova sintaxe unificada

.syntax unified

// Definições

.set    SYS_EXIT, 1
.set    SYS_WRITE, 4
.set    STDIN, 0
.set    STDOUT, 1
.set    STDERR, 2
.set    L1, 4                   // Linhas da matriz original
.set    C1, 2                   // Colunas da matriz original
.set    L2, 2                   // Linhas da matriz transposta
.set    C2, 4                   // Colunas da matriz transposta
.set    L3, 4                   // Linhas da matriz resultado = L1
.set    C3, 4                   // Colunas da matriz resultado = C2

// Macro

.macro mostrar_matriz matriz, linhas, colunas
        MOV     R8, 0           // R8 = Número da Linha = i
        MOV     R9, 0           // R9 = Número da Coluna = j
        MOV     R10, 4          // R10 = Tamanho em bytes do número inteiro
giro\@: PUSH    {R8, R9}        // Loop nos elementos da matriz
        MOV     R5, \colunas    // R5 = número de colunas
        MLA     R6, R8, R5, R9  // R6 = Posição na matriz = j + (i x COLUNAS)
        MUL     R6, R10         // R6 = Deslocamento na matriz em bytes
        LDR     R0, =\matriz    // R0 -> Início da matriz
        ADD     R0, R0, R6      // R0 -> Posição do elemento na matriz
        LDR     R0, [R0]        // R0 = Valor do elemento da matriz
        LDR     R1, =valor      // R1 -> String contendo o valor convertido
        BL      itostr          // Converter inteiro em string
        MOV     R7, SYS_WRITE   // Número da chamada do sistema em R7 (escrever)
        MOV     R0, STDOUT      // Descritor do arquivo em R0 (saída padrão, 1)
        LDR     R1, =valor      // R1 -> String contendo o valor convertido
        BL      strsize         // Armazenar o tamanho do resultado em R2
        SVC     0               // Chamar o sistema operacional
        BL      tabular         // Tabular a saída padrão
        POP     {R8,R9}         // Restaurar o nº da linha e o nº da coluna
        ADD     R9, 1           // Próxima coluna
        CMP     R9, \colunas    // Comparar o nº da coluna com o nº de colunas
        BLT     giro\@          // Se for menor mostrar a próxima coluna
        BL      nova_linha      // Senão avançar uma linha na saída padrão
        MOV     R9, 0           // R9 = Número da coluna = Primeira coluna
        ADD     R8, 1           // R8 = Próxima linha
        CMP     R8, \linhas     // Comparar o nº da linha com o nº de linhas
        BLT     giro\@          // Se for menor mostrar a próxima linha
.endm

// Dados

.data

.align

m:      .word 1, 2              // m = Matriz original (4x2)
        .word 3, 4
        .word 5, 6
        .word 7, 8

t:      .word 1, 3, 5, 7        // t = Matriz transposta de m (2x4)
        .word 2, 4, 6, 8

r:      .word 0, 0, 0, 0        // r = m . t (4x4)
        .word 0, 0, 0, 0
        .word 0, 0, 0, 0
        .word 0, 0, 0, 0

.align
new_line:       .string "\n"    // Caracter de nova linha

.align
tab:            .string "\t"    // Caracter de tabulação

.align
txt_orig:       .string "Matriz original:\n"
.set            TAM_ORIG, (. - txt_orig)        // Tamanho da mensagem

.align
txt_transp:     .string "Matriz transposta:\n"
.set            TAM_TRANSP, (. - txt_transp)    // Tamanho da mensagem

.align
txt_result:     .string "Matriz com o resultado da multiplicação:\n"
.set            TAM_RESULT, (. - txt_result)    // Tamanho da mensagem

.align
valor:          .space 32       // Espaço para o valor formatado

// Código

.text
.global _start

strsize:                        // Calcula o tamanho da string e retorna em R2
        MOV     R4, R1          // R4 -> início da string apontada por R1
        MOV     R2, 0           // Inicializa o tamanho da string com 0
loop:   LDRB    R3,[R4], 1      // Carrega o byte apontado por R4 em R3; R4 += 1
        CMP     R3, 0           // Compara o valor em R3 com 0 (fim da string)
        BEQ     endl            // Se for igual sai do loop e retorna
        ADD     R2, 1           // Senão incrementa o tamanho da string em R2
        B       loop            // e continua o loop
endl:   MOV     PC, LR          // Retornar: PC (Program Counter) = LR (Link Register)

nova_linha:                     // Escreve o caracter de nova linha na saída padrão
        MOV     R7, SYS_WRITE   // Número da chamada do sistema em R7 (escrever)
        MOV     R0, STDOUT      // Descritor do arquivo em R0 (saída padrão, 1)
        LDR     R1, =new_line   // R1 -> string de nova linha
        MOV     R2, 1           // Tamanho da string em R2 (um)
        SVC     0               // Chamar o sistema operacional
        MOV     PC, LR          // Retornar: PC (Program Counter) = LR (Link Register)

tabular:                        // Escreve o caracter de tabulação na saída padrão
        MOV     R7, SYS_WRITE   // Número da chamada do sistema em R7 (escrever)
        MOV     R0, STDOUT      // Descritor do arquivo em R0 (saída padrão, 1)
        LDR     R1, =tab        // R1 -> string de tabulação
        MOV     R2, 1           // Tamanho da string em R2 (um)
        SVC     0               // Chamar o sistema operacional
        MOV     PC, LR          // Retornar: PC (Program Counter) = LR (Link Register)

msg_orig:                       // Escreve a mensagem de matriz original na saída padrão
        MOV     R7, SYS_WRITE   // Número da chamada do sistema em R7 (escrever)
        MOV     R0, STDOUT      // Descritor do arquivo em R0 (saída padrão, 1)
        LDR     R1, =txt_orig   // R1 -> texto da mensagem
        MOV     R2, TAM_ORIG    // Tamanho da string da mensagem em R2
        SVC     0               // Chamar o sistema operacional
        MOV     PC, LR          // Retornar: PC (Program Counter) = LR (Link Register)

msg_transp:                     // Escreve a mensagem de matriz transposta na saída padrão
        MOV     R7, SYS_WRITE   // Número da chamada do sistema em R7 (escrever)
        MOV     R0, STDOUT      // Descritor do arquivo em R0 (saída padrão, 1)
        LDR     R1, =txt_transp // R1 -> texto da mensagem
        MOV     R2, TAM_TRANSP  // Tamanho da string da mensagem em R2
        SVC     0               // Chamar o sistema operacional
        MOV     PC, LR          // Retornar: PC (Program Counter) = LR (Link Register)

msg_result:                     // Escreve a mensagem de matriz com resultado
        MOV     R7, SYS_WRITE   // Número da chamada do sistema em R7 (escrever)
        MOV     R0, STDOUT      // Descritor do arquivo em R0 (saída padrão, 1)
        LDR     R1, =txt_result // R1 -> texto da mensagem
        MOV     R2, TAM_RESULT  // Tamanho da string da mensagem em R2
        SVC     0               // Chamar o sistema operacional
        MOV     PC, LR          // Retornar: PC (Program Counter) = LR (Link Register)

_start:

#       Mostrar a matriz original
        BL      msg_orig        // Mostrar a mensagem de matriz original
        mostrar_matriz m, L1, C1

#       Mostrar a matriz transposta
        BL      msg_transp      // Mostrar a mensagem de matriz transposta
        mostrar_matriz t, L2, C2

#       Multiplicação das matrizes
        MOV     R11, 4          // R11 = Tamanho em bytes do número inteiro
        MOV     R8, 0           // R8 = i = Número da Linha
giroI:                          // Loop nas linhas da matriz original
        MOV     R9, 0           // R9 = j = Número da Coluna
giroJ:                          // Loop nas colunas da matriz original
        MOV     R7, 0           // R7 = Soma m(i,k) x t(k,j)
        MOV     R10, 0          // R10 = Número da Coluna/Linha = K
giroK:                          // Loop nas colunas/linhas para a multiplicação
        MOV     R5, C1          // R5 = número de colunas da matriz original
        MLA     R6, R8, R5, R10 // R6 = Posição na matriz = k + (i x COLUNAS M)
        MUL     R6, R11         // R6 = Deslocamento na matriz em bytes
        LDR     R0, =m          // R0 -> Início da matriz original
        ADD     R0, R0, R6      // R0 -> Posição do elemento na matriz original
        LDR     R3, [R0]        // R3 = m(i,k)
                                // Matriz Transposta
        MOV     R5, C2          // R5 = número de colunas da matriz transposta
        MLA     R6, R10, R5, R9 // R6 = Posição na matriz = j + (k x COLUNAS T)
        MUL     R6, R11         // R6 = Deslocamento na matriz em bytes
        LDR     R0, =t          // R0 -> Início da matriz transposta
        ADD     R0, R0, R6      // R0 -> Posição do elemento na matriz
        LDR     R4, [R0]        // R4 = t(k,j)
                                // Multiplicar e acumular
        MUL     R3, R4          // R3 = m(i,k) x t (k,j)
        ADD     R7, R3          // R7 = Soma += m(i,k) x t (k,j)
                                // Próxima multiplicação
        ADD     R10, 1          // k++
        CMP     R10, L2         // k < L2 ?
        BLT     giroK           // Se for menor processar a próxima multiplicação
                                // Armazenar o valor acumulado
        MOV     R5, C3          // R5 = número de colunas da matriz transposta
        MLA     R6, R8, R5, R9  // R6 = Posição na matriz = j + (i x COLUNAS T)
        MUL     R6, R11         // R6 = Deslocamento na matriz em bytes
        LDR     R0, =r          // R0 -> Início da matriz de resultado
        ADD     R0, R0, R6      // R0 -> Posição do elemento na matriz resultado
        STR     R7, [R0]        // r(i,j) = Soma
                                // Próximo elemento
        ADD     R9, 1           // j++
        CMP     R9, C2          // j < C2 ?
        BLT     giroJ           // Se for menor processar a próxima coluna
        ADD     R8, 1           // i++
        CMP     R8, L1          // i < L1 ?
        BLT     giroI           // Se for menor processar a próxima linha

#       Mostrar a matriz contendo o resultado da multiplicação
        BL      msg_result      // Mostrar a mensagem de matriz resultado
        mostrar_matriz r, L3, C3

end:

        MOV     R7, SYS_EXIT    // Número da chamada do sistema em R7 (terminar)
        MOV     R0, 0           // Código de retorno igual a zero
        SVC     0               // Chamar o sistema operacional

Makefile:

mat_mult_transp_int: mat_mult_transp_int.o itostr.o
	ld -o mat_mult_transp_int mat_mult_transp_int.o itostr.o
mat_mult_transp_int.o: mat_mult_transp_int.s
	as -o mat_mult_transp_int.o mat_mult_transp_int.s
itostr.o: itostr.s
	as -o itostr.o itostr.s
clean:
	rm *.o  mat_mult_transp_int

Construção e execução:

pi@raspberrypi:~/raspbered/assembly/mat_mult_transp_int $ make clean
rm *.o  mat_mult_transp_int

pi@raspberrypi:~/raspbered/assembly/mat_mult_transp_int $ make
as -o mat_mult_transp_int.o mat_mult_transp_int.s
as -o itostr.o itostr.s
ld -o mat_mult_transp_int mat_mult_transp_int.o itostr.o

pi@raspberrypi:~/raspbered/assembly/mat_mult_transp_int $ ./mat_mult_transp_int 
Matriz original:
1	2	
3	4	
5	6	
7	8	
Matriz transposta:
1	3	5	7	
2	4	6	8	
Matriz com o resultado da multiplicação:
5	11	17	23	
11	25	39	53	
17	39	61	83	
23	53	83	113