# 6. Print e Formatacoes de Impressao

## Introdução

O **Assembly** é uma linguagem de programação de baixo nível que traduz instruções de máquina diretamente executáveis pelo processador, específica para arquiteturas como x86, MIPS ou ARM. Esta documentação cobre os fundamentos do Assembly, com ênfase em **impressão no terminal** e **formatações de impressão**, detalhando sua implementação, características, boas práticas e uma comparação com linguagens de alto nível como **Python**, **Bash** e **C**. Em Assembly, a impressão no terminal geralmente envolve chamadas ao sistema operacional ou bibliotecas como `libc`, e a formatação requer manipulação manual de strings.

## Estrutura Básica de um Programa Assembly

Um programa Assembly é um arquivo de texto (extensão `.asm` ou `.s`) com instruções traduzidas por um assembler (e.g., NASM para x86, mips-as para MIPS) em código de máquina. Abaixo, um exemplo em x86-64 que imprime uma string formatada:

```nasm
; programa.asm - Impressão com printf
section .text
    global _start
    extern printf       ; Função da libc

_start:
    mov rdi, fmt        ; Formato
    mov rsi, 42         ; Argumento
    xor rax, rax        ; Sem argumentos de ponto flutuante
    call printf         ; Imprime
    mov rax, 60         ; Syscall sair
    xor rdi, rdi
    syscall

section .data
    fmt db "Número: %d", 0xa, 0
```

* `section .text`: Contém o código executável.
* `section .data`: Define dados inicializados (e.g., strings de formato).
* `;`: Inicia um comentário.

## Instruções Básicas

### Operações com Registradores

| Instrução | Descrição          | Exemplo (x86) | Exemplo (MIPS) |
| --------- | ------------------ | ------------- | -------------- |
| `MOV`     | Copia dados        | `mov rax, 42` | `li $t0, 42`   |
| `CALL`    | Chama função       | `call printf` | `jal printf`   |
| `SYSCALL` | Chamada ao sistema | `syscall`     | `syscall`      |

### Manipulação de Memória

| Arquitetura | Leitura          | Escrita          |
| ----------- | ---------------- | ---------------- |
| x86-64      | `mov eax, [rbx]` | `mov [rbx], eax` |
| MIPS        | `lw $t0, 0($t1)` | `sw $t0, 0($t1)` |

***

## Impressão no Terminal em Assembly

### Definição e Implementação

Em Assembly, a impressão no terminal é feita via **chamadas ao sistema** (syscalls) ou funções de bibliotecas como `libc`. Syscalls são mais diretas, mas limitadas em formatação, enquanto `libc` (e.g., `printf`) oferece formatação avançada.

***

## 1. Usando Syscalls (x86-64)

### Syscall `write` - Imprime String Bruta

A syscall `write` (número 1) imprime uma string sem formatação:

```nasm
section .text
    global _start

_start:
    ; Syscall write
    mov rax, 1          ; sys_write
    mov rdi, 1          ; stdout (file descriptor)
    mov rsi, msg        ; Endereço da string
    mov rdx, len        ; Comprimento
    syscall
    
    ; Syscall exit
    mov rax, 60
    xor rdi, rdi
    syscall

section .data
    msg db "Olá, mundo!", 0xa   ; String com newline
    len equ $ - msg              ; Calcula tamanho
```

**Tabela de Syscalls para Impressão (x86-64 Linux):**

| Syscall  | Número | Parâmetros                  | Descrição         |
| -------- | ------ | --------------------------- | ----------------- |
| `write`  | 1      | rdi=fd, rsi=buf, rdx=count  | Escreve bytes     |
| `writev` | 20     | rdi=fd, rsi=iov, rdx=iovcnt | Escrita com vetor |

### Imprimindo Múltiplas Strings

```nasm
section .data
    msg1 db "Parte 1: ", 0
    msg2 db "Parte 2", 0xa, 0

section .text
imprimir_multiplas:
    mov rax, 1
    mov rdi, 1
    mov rsi, msg1
    mov rdx, 8          ; "Parte 1: " tem 8 bytes
    syscall
    
    mov rax, 1
    mov rdi, 1
    mov rsi, msg2
    mov rdx, 7          ; "Parte 2\n" tem 7 bytes
    syscall
    ret
```

***

## 2. Usando Syscalls (MIPS)

### Syscall `print_string` (MIPS)

```nasm
.data
    msg: .asciiz "Olá, mundo!\n"   # .asciiz adiciona null terminator

.text
    .globl main
main:
    li $v0, 4           # syscall print_string
    la $a0, msg         # endereço da string
    syscall
    
    li $v0, 10          # syscall exit
    syscall
```

### Syscall `print_int` (MIPS)

```nasm
.data
    numero: .word 42

.text
    li $v0, 1           # syscall print_int
    lw $a0, numero      # valor a imprimir
    syscall
```

**Tabela de Syscalls MIPS para Impressão:**

| Syscall        | Número | Parâmetro       | Descrição         |
| -------------- | ------ | --------------- | ----------------- |
| `print_int`    | 1      | $a0 = inteiro   | Imprime inteiro   |
| `print_float`  | 2      | $f12 = float    | Imprime float     |
| `print_double` | 3      | $f12 = double   | Imprime double    |
| `print_string` | 4      | $a0 = endereço  | Imprime string    |
| `print_char`   | 11     | $a0 = caractere | Imprime caractere |

***

## 3. Formatação com Syscalls (Manual)

Syscalls não suportam formatação diretamente. Para formatar números, é necessário conversão manual.

### Conversão de Inteiro para String (x86-64)

```nasm
; Função: int_to_str
; Parâmetros: RDI = número (32 bits), RSI = buffer
; Retorno: RAX = comprimento da string
int_to_str:
    push rbx
    push rcx
    push rdx
    
    mov eax, edi        ; Número a converter
    mov rbx, rsi        ; Buffer
    mov rcx, 10         ; Base decimal
    mov rdi, rbx        ; Salva início do buffer
    
    ; Verifica número zero
    test eax, eax
    jnz .convert
    mov byte [rbx], '0'
    inc rbx
    jmp .done

.convert:
    ; Empilha dígitos
    xor rdx, rdx
    div rcx             ; EAX = quociente, RDX = resto
    add dl, '0'         ; Converte para ASCII
    push rdx            ; Empilha dígito
    test eax, eax
    jnz .convert
    
    ; Desempilha e escreve no buffer
.pop_digits:
    pop rax
    mov [rbx], al
    inc rbx
    cmp rbx, rsp
    jne .pop_digits

.done:
    mov byte [rbx], 0   ; Null terminator
    mov rax, rbx
    sub rax, rdi        ; Comprimento
    pop rdx
    pop rcx
    pop rbx
    ret
```

### Uso da Função de Conversão

```nasm
section .bss
    buffer resb 32

section .text
    global _start

_start:
    ; Converte número 12345 para string
    mov rdi, 12345
    mov rsi, buffer
    call int_to_str
    
    ; Imprime usando syscall
    mov rax, 1
    mov rdi, 1
    mov rsi, buffer
    mov rdx, rax        ; RAX tem o comprimento
    syscall
    
    ; Imprime newline
    mov rax, 1
    mov rdi, 1
    mov rsi, newline
    mov rdx, 1
    syscall
    
    mov rax, 60
    xor rdi, rdi
    syscall

section .data
    newline db 0xa
```

***

## 4. Usando printf (libc)

A função `printf` da libc oferece formatação avançada e é mais simples de usar.

### x86-64 com printf

```nasm
extern printf

section .data
    fmt_int db "Inteiro: %d", 0xa, 0
    fmt_hex db "Hexadecimal: 0x%x", 0xa, 0
    fmt_str db "String: %s", 0xa, 0
    fmt_float db "Float: %.2f", 0xa, 0
    fmt_multiple db "Valores: %d, %s, 0x%x", 0xa, 0
    
    texto db "Assembly", 0
    numero dd 255
    flt dq 3.14159

section .text
    global _start

_start:
    ; Inteiro
    mov rdi, fmt_int
    mov esi, 42
    xor rax, rax
    call printf
    
    ; Hexadecimal
    mov rdi, fmt_hex
    mov esi, [numero]
    xor rax, rax
    call printf
    
    ; String
    mov rdi, fmt_str
    mov rsi, texto
    xor rax, rax
    call printf
    
    ; Float (requer registradores XMM)
    mov rdi, fmt_float
    movsd xmm0, [flt]
    mov rax, 1          ; 1 argumento float
    call printf
    
    ; Múltiplos argumentos
    mov rdi, fmt_multiple
    mov esi, 100
    mov rdx, texto
    mov ecx, 0xFF
    xor rax, rax
    call printf
    
    mov rax, 60
    xor rdi, rdi
    syscall
```

### Especificadores de Formato printf

| Especificador | Tipo               | Exemplo                 | Saída          |
| ------------- | ------------------ | ----------------------- | -------------- |
| `%d` / `%i`   | Inteiro decimal    | `printf("%d", 42)`      | `42`           |
| `%u`          | Inteiro sem sinal  | `printf("%u", 42)`      | `42`           |
| `%x` / `%X`   | Hexadecimal        | `printf("%x", 255)`     | `ff`           |
| `%o`          | Octal              | `printf("%o", 8)`       | `10`           |
| `%c`          | Caractere          | `printf("%c", 'A')`     | `A`            |
| `%s`          | String             | `printf("%s", "texto")` | `texto`        |
| `%f`          | Float/Double       | `printf("%f", 3.14)`    | `3.140000`     |
| `%e`          | Notação científica | `printf("%e", 3.14)`    | `3.140000e+00` |
| `%p`          | Ponteiro           | `printf("%p", &var)`    | `0x7fff...`    |
| `%%`          | Porcentagem        | `printf("%%")`          | `%`            |

### Modificadores de Formato

```nasm
; Largura mínima
fmt_width db "|%10d|", 0xa, 0     ; |        42|
fmt_left db "|%-10d|", 0xa, 0     ; |42        |

; Precisão (decimais)
fmt_precision db "%.2f", 0xa, 0   ; 3.14

; Zero padding
fmt_padding db "%05d", 0xa, 0     ; 00042

; Tamanho (long, long long)
fmt_long db "%ld", 0xa, 0         ; long
fmt_llong db "%lld", 0xa, 0       ; long long
```

***

## 5. MIPS com printf (libc)

```nasm
.data
    fmt_int: .asciiz "Inteiro: %d\n"
    fmt_float: .asciiz "Float: %.2f\n"
    fmt_string: .asciiz "String: %s\n"
    texto: .asciiz "Assembly MIPS"
    numero: .word 42
    flt: .double 3.14159

.text
    .globl main

main:
    # Inteiro
    la $a0, fmt_int
    lw $a1, numero
    jal printf
    
    # Float (double)
    la $a0, fmt_float
    ldc1 $f12, flt
    jal printf
    
    # String
    la $a0, fmt_string
    la $a1, texto
    jal printf
    
    li $v0, 10
    syscall
```

***

## 6. Códigos ANSI para Cores (CLI)

Em terminais compatíveis, é possível usar cores com códigos ANSI.

### Definição de Cores

```nasm
section .data
    ; Cores de texto
    RESET   db 0x1b, '[0m', 0
    VERMELHO db 0x1b, '[31m', 0
    VERDE   db 0x1b, '[32m', 0
    AMARELO db 0x1b, '[33m', 0
    AZUL    db 0x1b, '[34m', 0
    MAGENTA db 0x1b, '[35m', 0
    CIANO   db 0x1b, '[36m', 0
    BRANCO  db 0x1b, '[37m', 0
    
    ; Estilos
    NEGRITO db 0x1b, '[1m', 0
    SUBLINHADO db 0x1b, '[4m', 0
    
    ; Cores de fundo
    BG_VERMELHO db 0x1b, '[41m', 0
    BG_VERDE    db 0x1b, '[42m', 0
    BG_AMARELO  db 0x1b, '[43m', 0
```

### Função para Imprimir Colorido

```nasm
; Função: print_color
; Parâmetros: RDI = cor, RSI = texto
print_color:
    push rbx
    
    ; Imprime cor
    mov rax, 1
    mov rbx, rdi
    call strlen
    mov rdx, rax
    mov rax, 1
    mov rdi, 1
    mov rsi, rbx
    syscall
    
    ; Imprime texto
    mov rax, 1
    mov rbx, rsi
    call strlen
    mov rdx, rax
    mov rax, 1
    mov rdi, 1
    mov rsi, rbx
    syscall
    
    ; Imprime reset
    mov rax, 1
    mov rsi, RESET
    mov rdx, 4          ; "\033[0m" tem 4 bytes
    syscall
    
    pop rbx
    ret

; Função auxiliar strlen
strlen:
    xor rax, rax
.loop:
    cmp byte [rbx + rax], 0
    je .done
    inc rax
    jmp .loop
.done:
    ret
```

### Uso das Cores

```nasm
section .data
    msg_erro db "Erro: arquivo não encontrado", 0xa, 0
    msg_sucesso db "Sucesso: operação concluída", 0xa, 0
    msg_aviso db "Aviso: memória baixa", 0xa, 0

section .text
    global _start

_start:
    ; Erro em vermelho
    mov rdi, VERMELHO
    mov rsi, msg_erro
    call print_color
    
    ; Sucesso em verde
    mov rdi, VERDE
    mov rsi, msg_sucesso
    call print_color
    
    ; Aviso em amarelo
    mov rdi, AMARELO
    mov rsi, msg_aviso
    call print_color
    
    ; Texto em negrito e azul
    mov rdi, NEGRITO
    mov rsi, AZUL
    call print_color
    
    mov rax, 60
    xor rdi, rdi
    syscall
```

***

## 7. Formatação Avançada com sprintf

`sprintf` permite formatar strings em buffer para uso posterior.

```nasm
extern sprintf

section .data
    fmt db "Valor: %d, Texto: %s", 0
    texto db "Assembly", 0

section .bss
    buffer resb 256

section .text
    global _start

_start:
    ; Formata string no buffer
    mov rdi, buffer
    mov rsi, fmt
    mov edx, 42
    mov rcx, texto
    xor rax, rax
    call sprintf
    
    ; Imprime resultado
    mov rax, 1
    mov rdi, 1
    mov rsi, buffer
    mov rdx, 256
    syscall
    
    mov rax, 60
    xor rdi, rdi
    syscall
```

***

## 8. Detecção de Ambiente para Cores

```nasm
; Verifica se o terminal suporta cores
detect_color:
    push rbx
    
    ; Verifica variável de ambiente TERM
    mov rsi, term_var
    call getenv
    
    test rax, rax
    jz .no_color
    
    ; Verifica se contém "xterm" ou "linux"
    mov rsi, rax
    mov rdi, xterm_str
    call strstr
    test rax, rax
    jnz .has_color
    
    mov rsi, term_var
    mov rdi, linux_str
    call strstr
    test rax, rax
    jnz .has_color

.no_color:
    xor rax, rax
    jmp .done

.has_color:
    mov rax, 1

.done:
    pop rbx
    ret

section .data
    term_var db "TERM", 0
    xterm_str db "xterm", 0
    linux_str db "linux", 0
```

***

## Comparação com Outras Linguagens

| Aspecto        | Assembly (x86/MIPS)         | Python                      | Bash                | C                |
| -------------- | --------------------------- | --------------------------- | ------------------- | ---------------- |
| **Impressão**  | Syscall `write`, `printf`   | `print()`                   | `echo`, `printf`    | `printf()`       |
| **Formatação** | Manual ou `%d`, `%s` (libc) | f-strings, `%`, `.format()` | `%d`, `%s` (printf) | `%d`, `%s`, `%f` |
| **Cores**      | Códigos ANSI manuais        | Bibliotecas (colorama)      | Códigos ANSI        | Códigos ANSI     |
| **Abstração**  | Mínima, manual              | Alta, automática            | Moderada            | Moderada         |
| **Eficiência** | Máxima                      | Menor                       | Moderada            | Alta             |

### Exemplo em Python

```python
print("Texto simples")
print(f"Inteiro: {42}")
print("\033[31mErro!\033[0m")
```

### Exemplo em Bash

```bash
echo "Texto simples"
printf "Inteiro: %d\n" 42
echo -e "\033[31mErro!\033[0m"
```

### Exemplo em C

```c
printf("Texto simples\n");
printf("Inteiro: %d\n", 42);
printf("\033[31mErro!\033[0m\n");
```

***

## Boas Práticas

{% stepper %}
{% step %}

#### 1. Use snprintf para Segurança

```nasm
; Prefira snprintf em vez de sprintf para evitar buffer overflow
extern snprintf

mov rdi, buffer
mov rsi, 256         ; Tamanho máximo
mov rdx, fmt
mov ecx, 42
call snprintf
```

{% endstep %}

{% step %}

#### 2. Valide Retornos de Syscall

```nasm
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, len
syscall
cmp rax, 0
jl erro_escrita      ; Verifica erro
```

{% endstep %}

{% step %}

#### 3. Use `isatty` para Detectar Terminal

```nasm
extern isatty

mov rdi, 1           ; stdout
call isatty
test rax, rax
jnz .tem_cor        ; Se for terminal, usa cores
```

{% endstep %}

{% step %}

#### 4. Evite Format String Attack

```nasm
; Perigoso - nunca faça isso!
; mov rdi, user_input
; call printf

; Correto
mov rdi, fmt_safe
mov rsi, user_input
call printf

section .data
    fmt_safe db "%s", 0
```

{% endstep %}
{% endstepper %}

## Exemplo Completo: Logger com Cores e Timestamp

```nasm
; logger.asm - Sistema de log com cores e timestamp
extern printf, time, localtime, strftime

section .data
    ; Cores ANSI
    RESET db 0x1b, '[0m', 0
    COLOR_DEBUG db 0x1b, '[36m', 0   ; Ciano
    COLOR_INFO db 0x1b, '[32m', 0    ; Verde
    COLOR_WARN db 0x1b, '[33m', 0    ; Amarelo
    COLOR_ERROR db 0x1b, '[31m', 0   ; Vermelho
    
    ; Formatos
    fmt_time db "%H:%M:%S", 0
    fmt_log db "[%s] %s: %s", 0xa, 0

section .bss
    time_buffer resb 64
    log_buffer resb 256

section .text
    global _start

; Função: log_message(nivel, mensagem)
; Parâmetros: RDI = nível (0=DEBUG,1=INFO,2=WARN,3=ERROR), RSI = mensagem
log_message:
    push rbx
    push r12
    
    mov r12, rsi        ; Salva mensagem
    mov rbx, rdi        ; Salva nível
    
    ; Obtém timestamp
    mov rdi, 0
    call time
    mov rdi, rax
    call localtime
    mov rdi, time_buffer
    mov rsi, fmt_time
    mov rdx, rax
    call strftime
    
    ; Seleciona cor baseada no nível
    cmp rbx, 0
    je .debug
    cmp rbx, 1
    je .info
    cmp rbx, 2
    je .warn
    ; .error
    mov rbx, COLOR_ERROR
    mov rcx, error_str
    jmp .print

.debug:
    mov rbx, COLOR_DEBUG
    mov rcx, debug_str
    jmp .print

.info:
    mov rbx, COLOR_INFO
    mov rcx, info_str
    jmp .print

.warn:
    mov rbx, COLOR_WARN
    mov rcx, warn_str

.print:
    ; Imprime cor
    mov rdi, rbx
    call print_str
    
    ; Imprime log formatado
    mov rdi, fmt_log
    mov rsi, time_buffer
    mov rdx, rcx
    mov rcx, r12
    xor rax, rax
    call printf
    
    ; Reseta cor
    mov rdi, RESET
    call print_str
    
    pop r12
    pop rbx
    ret

print_str:
    push rbx
    mov rbx, rdi
    call strlen
    mov rdx, rax
    mov rax, 1
    mov rdi, 1
    mov rsi, rbx
    syscall
    pop rbx
    ret

strlen:
    xor rax, rax
.loop:
    cmp byte [rbx + rax], 0
    je .done
    inc rax
    jmp .loop
.done:
    ret

section .data
    debug_str db "DEBUG", 0
    info_str db "INFO", 0
    warn_str db "WARN", 0
    error_str db "ERROR", 0

section .text
_start:
    mov rdi, 0          ; DEBUG
    mov rsi, debug_msg
    call log_message
    
    mov rdi, 1          ; INFO
    mov rsi, info_msg
    call log_message
    
    mov rdi, 2          ; WARN
    mov rsi, warn_msg
    call log_message
    
    mov rdi, 3          ; ERROR
    mov rsi, error_msg
    call log_message
    
    mov rax, 60
    xor rdi, rdi
    syscall

section .data
    debug_msg db "Inicializando sistema", 0
    info_msg db "Conexão estabelecida", 0
    warn_msg db "Uso de memória alto", 0
    error_msg db "Falha na conexão com banco", 0
```

***

## Recursos Adicionais

* **Livro Gratuito**: [Aprendendo Assembly](https://mentebinaria.gitbook.io/assembly) (x86/x86-64)
* **Manuais Intel**: [Volume 2A](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html)
* **ANSI Escape Codes**: [Wikipedia](https://en.wikipedia.org/wiki/ANSI_escape_code)
* **Ferramentas**: NASM ([nasm.us](https://nasm.us/)), PEDA ([github.com/longld/peda](https://github.com/longld/peda))


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/conceitos/programacao-e-linguagens/assembly/6.-print-e-formatacoes-de-impressao.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
