R a s p b e r e d

Usando o Raspberry Pi

1 + 2 + 3 + 4 + ⋯ + N

Programa para calcular o somatório dos números naturais de 1 a N

Recebe como parâmetro o último número da série e mostra este número e o valor do somatório.

/**
 * @file    somatorio_1_n.s
 * @author  Halley Pacheco de Oliveira
 * @version 1.0
 * 
 * @section DESCRIPTION
 *
 * Programa para calcular o somatório dos números naturais de 1 a N.
 *
 * Usa as funções 'strtoi' e 'itostr' descritas no GitHub Gist
 * seenaburns/strtoi-add-argv.s
 * https://gist.github.com/seenaburns/70019f3217ab6392c3c245976e336978
 *
 * @param  Último número da série (N)
 * @output Número fornecido e o valor do somatório
 *
 * @see: Wikipedia 1 + 2 + 3 + 4 + ⋯
 *       https://en.wikipedia.org/wiki/1_%2B_2_%2B_3_%2B_4_%2B_%E2%8B%AF
 */

// 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

// Dados

.data

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

.align
txt_erro:       .string "Erro: Informe o último número do somatório.\n"
.set            TAM_ERRO, (. - txt_erro)    // Tamanho da mensagem de erro

.align
txt_over:       .string "Erro: valor máximo para o somatório excedido.\n"
.set            TAM_OVER, (. - txt_over)    // Tamanho da mensagem de overflow

.align
result:         .space 32       // Texto com o resultado do somatório

// Código

.text
.global _start

nova_linha:                     // Escreve o caractere 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
endnl:  MOV     PC, LR          // Retornar: PC (Program Counter) = LR (Link Register)

msg_erro:                       // Escreve a mensagem de erro na saída padrão
        MOV     R7, SYS_WRITE   // Número da chamada do sistema em R7 (escrever)
        MOV     R0, STDERR      // Descritor do arquivo em R0 (saída de erro padrão, 2)
        LDR     R1, =txt_erro   // R1 -> texto da mensagem de erro
        MOV     R2, TAM_ERRO    // Tamanho da string da mensagem de erro em R2
        SVC     0               // Chamar o sistema operacional
enderr: MOV     PC, LR          // Retornar: PC (Program Counter) = LR (Link Register)

strsize:                        // Calcula o tamanho da string e retorna em R2
        MOV     R4, R1          // R4 aponta para o 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)

overflow:                       // Escreve a mensagem de overflow na saída padrão
        MOV     R7, SYS_WRITE   // Número da chamada do sistema em R7 (escrever)
        MOV     R0, STDERR      // Descritor do arquivo em R0 (saída de erro padrão, 2)
        LDR     R1, =txt_over   // R1 -> texto da mensagem de erro
        MOV     R2, TAM_OVER    // Tamanho da string da mensagem de erro em R2
        SVC     0               // Chamar o sistema operacional
        B       end             // Terminar a execução do programa

_start:

        LDR     R0, [SP]        // Número de argumentos (argc)
        CMP     R0, 1           // Número de argumentos = 1 ? (só o nome do programa?)
        BGT     argv0           // Se for maior continuar a execução do programa
        BL      msg_erro        // Se não for maior mostrar a mensagem de erro
        B       end             // e terminar o programa
        
argv0:                          // Mostra argv[0] (nome do programa)
        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, [SP, 4]     // argv[0] -> nome do programa
        BL      strsize         // Armazenar o tamanho do argumento em R2
        SVC     0               // Chamar o sistema operacional
        BL      nova_linha      // Avançar uma linha na saída padrão

argv1:                          // Mostra argv[1] (N)
        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, [SP, 8]     // argv[1] -> string contendo N
        BL      strsize         // Armazenar o tamanho do argumento em R2
        SVC     0               // Chamar o sistema operacional
        BL      nova_linha      // Avançar uma linha na saída padrão

somatorio:                      // R1 = Somatório de 1 a N
        LDR     R0, [SP, 8]     // R0 -> limite do somatório (N)
        BL      strtoi          // Converter a string em um número inteiro
        MOV     R1, 0           // Inicializar o somatório como 0 em R1
somar:  ADDS    R1, R1, R0      // SOMA += N
        BVS     overflow        // Capacidade excedida
        SUBS    R0, R0, 1       // N -= 1
        BNE     somar           // Se N for diferente de zero então continuar

converter:                      // Converter o somatório em string e mostrar
        MOV     R0, R1          // R0 = Somatório
        LDR     R1, =result     // R1 -> Valor convertido
        BL      itostr          // Converter inteiro em string

mostrar_convertido:             // Mostrar o somatório convertido 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, =result     // R1 -> string contendo o somatório em ASCII
        BL      strsize         // Armazenar o tamanho do resultado em R2
        SVC     0               // Chamar o sistema operacional
        BL      nova_linha      // Avançar uma linha na saída padrão

end:

        MOV     R7, 1           // Número da chamada do sistema em R7 (terminar)
        SVC     0               // Chamar o sistema operacional

Makefile:

somatorio_1_n: somatorio_1_n.o strtoi.o itostr.o
        ld -o somatorio_1_n somatorio_1_n.o strtoi.o itostr.o
somatorio_1_n.o: somatorio_1_n.s
        as -o somatorio_1_n.o somatorio_1_n.s
strtoi.o: strtoi.s
        as -o strtoi.o strtoi.s
itostr.o: strtoi.s
        as -o itostr.o itostr.s
clean:
        rm *.o  somatorio_1_n

Construção e execução:

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

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

pi@raspberrypi:~/raspbered/assembly/somatorio_1_n $ ./somatorio_1_n 
Erro: Informe o último número do somatório.

pi@raspberrypi:~/raspbered/assembly/somatorio_1_n $ ./somatorio_1_n 65535
./somatorio_1_n
65535
2147450880

pi@raspberrypi:~/raspbered/assembly/somatorio_1_n $ ./somatorio_1_n 131071
./somatorio_1_n
131071
Erro: valor máximo para o somatório excedido.
Última atualização em 2019-07-28
Publicado em 2019-07-28