2.1.10 Função Asm Puts

Função para escrever uma cadeia de caracteres na saída padrão

int asm_puts(const char *str);

Escreve uma cadeia de caracteres na saída padrão até, mas sem incluir, o caractere nulo (0). Um caractere de nova linha é adicionado ao final da saída. Retorna o número de caracteres escritos, incluindo o caractere de nova linha (\n) no final da saída.

Função análoga à função “puts” da linguagem C, codificada para ser chamada por um programa escrito na linguagem C, ou em outra linguagem com chamada de função compatível.

/**
 * @file    asm_puts.s
 * @author  Reficio
 * @version 1.0
 *
 * @section DESCRIPTION
 *
 * Função para escrever uma cadeia de caracteres na saída padrão
 *
 * Função análoga à função "puts" da linguagem C, codificada para
 * ser chamada por um programa escrito na linguagem C, ou em outra
 * linguagem com chamada de função compatível.
 *
 * A função da biblioteca C "int puts(const char *str)" escreve uma
 * cadeia de caracteres na saída padrão até, mas sem incluir, o caractere
 * nulo (0). Um caractere de nova linha é adicionado ao final da saída.
 *
 * @param  Endereço da cadeia de caracteres a ser escrita na saída padrão.
 * @return Número de caracteres escritos, incluindo o caractere de
 *         nova linha (\n) no final da saída.
 */

// Nova sintaxe unificada

.syntax unified

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

// Código

.text
.global asm_puts
.type asm_puts, %function

strsize:                        // Calcula o tamanho da string e retorna em R10
        MOV     R8, R1          // R8 -> início da string apontada por R1
        MOV     R10, #0         // R10 = tamanho da string = 0
loop:   LDRB    R9,[R8], #1     // Carrega o byte apontado por R8 em R9; R8 += 1
        CMP     R9, #0          // Compara o valor em R9 com 0 (fim da string)
        BEQ     endl            // Se for igual sai do loop e retorna
        ADD     R10, #1         // Senão incrementa o tamanho da string em R10
        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)

asm_puts:

        PUSH    {R4-R11, LR}    // Salvar R4 a R11 e LR (Link Register) na pilha.

        MOV     R1, R0          // R1 = Endereço da string passada como parâmetro.
        BL      strsize         // Retorna o tamanho da string apontada por R1 em R10.
        MOV     R2, R10         // R2 = Tamanho da string.
        MOV     R7, #SYS_WRITE  // R7 = Número da chamada do sistema (escrever).
        MOV     R0, #STDOUT     // R0 = Descritor do arquivo (Saída padrão, 1)
        SVC     0               // Chamar o sistema operacional.
        
        BL      nova_linha      // Avançar uma linha na saída padrão

end:

        ADD     R0, R10, #1     // R0 = Valor retornado = Número de caracteres escritos.
        POP     {R4-R11, PC}    // Trazer R4 a R11 e PC (Program Counter) da pilha.

Programa em C para testar a função:

/**
 * @file    call_asm_puts.c
 * @author  Reficio
 * @version 1.0
 * 
 * @section DESCRIPTION
 * 
 * Este programa tem por finalidade chamar a função "asm_puts",
 * equivalente à função "int puts(const char *str)" da biblioteca C,
 * para fins de teste e comparação.
 * 
 */

#include <stdio.h>
#include <string.h>

extern int asm_puts(const char *str);

int main () {
        int n;

        n = puts("Vou voltar!");
        printf("%d\n",n);
        n = asm_puts("Dando um alô do C para o Assembly");
        printf("%d\n",n);
        n = puts("Estou de volta!");
        printf("%d\n",n);
   
        return(0);
}

Makefile:

call_asm_puts: call_asm_puts.c asm_puts.s
        gcc -o call_asm_puts call_asm_puts.c asm_puts.s
clean:
        rm call_asm_puts

Construção e execução:

pi@raspberrypi:~/raspbered/assembly/asm_puts $ make clean
rm call_asm_puts

pi@raspberrypi:~/raspbered/assembly/asm_puts $ make
gcc -o call_asm_puts call_asm_puts.c asm_puts.s

pi@raspberrypi:~/raspbered/assembly/asm_puts $ ./call_asm_puts ; echo $?
Vou voltar!
12
Dando um alô do C para o Assembly
35
Estou de volta!
16
0