R a s p b e r e d

Usando o Raspberry Pi

Transposição de matriz de inteiros

Wolfram Mathematica Matriz Transposta

Programa para realizar a transposição de uma matriz de inteiros

A matriz transposta é obtida trocando-se as linhas pelas colunas de uma dada matriz

/**
 * @file    mat_transp_int.s
 * @author  Halley Pacheco de Oliveira
 * @version 1.0
 * 
 * @section DESCRIPTION
 *
 * Programa para realizar a transposição de uma matriz de inteiros.
 *
 * A matriz transposta é obtida trocando-se as linhas pelas colunas
 * de uma dada matriz.
 *
 * Matriz original    Matriz Transposta
 *    | 1 2 |          | 1 3 5 7 |
 *    | 3 4 |          | 2 4 6 8 |
 *    | 5 6 |
 *    | 7 8 |
 *
 * Usa a função 'itostr' descritas no GitHub Gist
 * seenaburns/strtoi-add-argv.s
 * https://gist.github.com/seenaburns/70019f3217ab6392c3c245976e336978
 *
 * @output Matriz original e matriz transposta.
 */

// Raspberry Pi 3 Modelo A+
.cpu    cortex-a53
.fpu    neon-fp-armv8
.syntax unified         // Sintaxe moderna (UAL=Unified Assembler Language)

// Definições

.set    SYS_EXIT, 1
.set    SYS_WRITE, 4
.set    STDIN, 0
.set    STDOUT, 1
.set    STDERR, 2
.set    LINHAS, 4
.set    COLUNAS, 2

// 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 0, 0, 0, 0        // t = Matriz transposta de m (2x4)
        .word 0, 0, 0, 0

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

.align
tab:            .string "\t"    // Caractere 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
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     found           // 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
found:  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)

_start:

#       Mostrar a matriz original
        BL      msg_orig        // Mostrar a mensagem de matriz original
        mostrar_matriz m, LINHAS, COLUNAS

#       Transposição da matriz
        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
prox:                           // Loop nos elementos da matriz original
        MOV     R5, COLUNAS     // R5 = número de colunas da matriz original
        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, =m          // R0 -> Início da matriz original
        ADD     R0, R0, R6      // R0 -> Posição do elemento na matriz original
        LDR     R0, [R0]        // R0 = Valor do elemento da matriz original
                                // Matriz Transposta
        MOV     R5, LINHAS      // R5 = número de colunas da matriz transposta
        MLA     R6, R9, R5, R8  // R6 = Posição na matriz = I + (J x LINHAS)
        MUL     R6, R10         // R6 = Deslocamento na matriz em bytes
        LDR     R1, =t          // R1 -> Início da matriz transposta
        ADD     R1, R1, R6      // R1 -> Posição do elemento na matriz
        STR     R0, [R1]        // Armanenar o valor na matriz transposta
                                // Próximo elemento da matriz original
        ADD     R9, 1           // Próxima coluna da matriz original
        CMP     R9, COLUNAS     // Comparar o nº da coluna com o nº de colunas
        BLT     prox            // Se for menor processar a próxima coluna
        MOV     R9, 0           // R9 = Número da coluna = 0 = Primeira coluna
        ADD     R8, 1           // R8 = Próxima linha
        CMP     R8, LINHAS      // Comparar o nº da linha com o nº de linhas
        BLT     prox            // Se for menor processar para a próxima linha

#       Mostrar a matriz transposta
        BL      msg_transp      // Mostrar a mensagem de matriz transposta
        mostrar_matriz t, COLUNAS, LINHAS

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_transp_int: mat_transp_int.o itostr.o
    ld -o mat_transp_int mat_transp_int.o itostr.o
mat_transp_int.o: mat_transp_int.s
    as -o mat_transp_int.o mat_transp_int.s
itostr.o: itostr.s
    as -o itostr.o itostr.s
clean:
    rm *.o  mat_transp_int

Construção e execução:

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

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

pi@raspberrypi:~/raspbered/assembly/mat_transp_int $ ./mat_transp_int 
Matriz original:
1   2   
3   4   
5   6   
7   8   
Matriz transposta:
1   3   5   7
2   4   6   8
Última atualização em 2019-07-30
Publicado em 2019-07-30