# 7. VGA e Criação de Interfaces Gráficas

## Introdução ao VGA

O padrão **VGA (Video Graphics Array)** é um sistema de exibição introduzido pela IBM em 1987 que se tornou o padrão para gráficos em PCs. Em Assembly, podemos programar o VGA diretamente para criar interfaces gráficas simples, aproveitando seu acesso direto à memória e portas de I/O. Esta documentação cobre os fundamentos da programação VGA, modos de vídeo, manipulação de memória gráfica e criação de interfaces.

## Modos de Vídeo do VGA

O VGA oferece vários modos de vídeo, sendo os mais relevantes para programação em Assembly:

| Modo                | Número | Resolução        | Cores | Memória | Uso típico                |
| ------------------- | ------ | ---------------- | ----- | ------- | ------------------------- |
| **Texto 80x25**     | 03h    | 80x25 caracteres | 16    | 0xB8000 | Modo padrão, console      |
| **Gráfico 320x200** | 13h    | 320x200 pixels   | 256   | 0xA0000 | Jogos, gráficos simples   |
| **Gráfico 640x480** | 12h    | 640x480 pixels   | 16    | 0xA0000 | Alta resolução, baixa cor |
| **Gráfico 640x350** | 10h    | 640x350 pixels   | 16    | 0xA0000 | Modo EGA compatível       |

***

## 1. Modo Texto VGA (80x25)

### Estrutura da Memória de Texto

* **Endereço base**: `0xB8000` (segmento 0xB800)
* **Cada caractere**: 2 bytes
  * **Byte 0**: Código ASCII do caractere
  * **Byte 1**: Atributo (cor de fundo e primeiro plano)

### Estrutura do Atributo

```
Bit:    7    6    5    4    3    2    1    0
      +----+----+----+----+----+----+----+----+
      | BL | B3 | B2 | B1 | F3 | F2 | F1 | F0 |
      +----+----+----+----+----+----+----+----+
        |    |         |         |
        |    |         +---------+---> Cor do texto (4 bits)
        |    +--------------------> Cor de fundo (3 bits)
        +-------------------------> Blink (piscar) / Background intenso
```

### Cores Disponíveis

| Código | Cor         | Código | Cor            |
| ------ | ----------- | ------ | -------------- |
| 0      | Preto       | 8      | Cinza escuro   |
| 1      | Azul        | 9      | Azul claro     |
| 2      | Verde       | A      | Verde claro    |
| 3      | Ciano       | B      | Ciano claro    |
| 4      | Vermelho    | C      | Vermelho claro |
| 5      | Magenta     | D      | Magenta claro  |
| 6      | Marrom      | E      | Amarelo        |
| 7      | Cinza claro | F      | Branco         |

### Exemplo Prático (x86)

```nasm
; modo_texto.asm - Programa em modo texto 80x25
section .text
    global _start

_start:
    ; Configura modo de vídeo 80x25 (03h)
    mov ax, 0x0003
    int 0x10

    ; Aponta ES para segmento de vídeo
    mov ax, 0xB800
    mov es, ax

    ; Escreve caractere 'A' com atributo (verde sobre preto)
    mov byte [es:0], 'A'      ; Caractere
    mov byte [es:1], 0x02     ; Atributo (verde)

    ; Escreve string colorida na segunda linha
    mov si, mensagem
    mov di, 160               ; Segunda linha (80 chars * 2 bytes)
    mov cx, len
    mov ah, 0x1E              ; Atributo (amarelo sobre azul)

escrever:
    lodsb                     ; Carrega caractere de DS:SI
    stosw                     ; Armazena caractere+atributo em ES:DI
    loop escrever

    ; Espera tecla
    mov ah, 0x00
    int 0x16

    ; Retorna ao DOS
    mov ax, 0x4C00
    int 0x21

section .data
    mensagem db "Interface grafica em Assembly!", 0
    len equ $ - mensagem
```

### Função para Escrever Texto Colorido

```nasm
; Função: escrever_texto
; Parâmetros: BX = linha, DX = coluna, SI = string, AL = atributo
escrever_texto:
    pusha
    mov ax, 0xB800
    mov es, ax
    
    ; Calcula offset: (linha * 80 + coluna) * 2
    mov ax, bx
    mov cx, 80
    mul cx
    add ax, dx
    shl ax, 1
    mov di, ax
    
    mov ah, al              ; Atributo
.escrever_loop:
    lodsb                   ; Carrega caractere
    cmp al, 0
    je .fim
    stosw                   ; Armazena caractere + atributo
    jmp .escrever_loop
.fim:
    popa
    ret
```

***

## 2. Modo Gráfico 13h (320x200, 256 cores)

### Características

* **Frame buffer linear** em `0xA0000`
* **Cada pixel**: 1 byte (índice na paleta)
* **Resolução**: 320x200 = 64,000 bytes
* **Cores**: 256 cores simultâneas (paleta configurável)

### Exemplo Prático

```nasm
; modo_grafico.asm - Programa em modo gráfico 13h
section .text
    global _start

_start:
    ; Configura modo gráfico 13h
    mov ax, 0x0013
    int 0x10

    ; Aponta ES para segmento de vídeo
    mov ax, 0xA000
    mov es, ax

    ; Desenha pixel vermelho em (100,50)
    mov di, (50 * 320) + 100  ; Y * 320 + X
    mov byte [es:di], 40      ; Índice de cor vermelha

    ; Desenha retângulo azul
    mov cx, 50                ; Altura
    mov dx, 30                ; Largura
    mov bx, 20                ; X inicial
    mov bp, 20                ; Y inicial

desenhar_retangulo:
    push cx
    mov cx, dx                ; Largura
    mov di, bp
    imul di, 320
    add di, bx                ; DI = Y*320 + X
    
    mov al, 9                 ; Cor azul
    rep stosb                 ; Preenche linha

    pop cx
    inc bp                    ; Próxima linha
    loop desenhar_retangulo

    ; Espera tecla
    mov ah, 0x00
    int 0x16

    ; Retorna ao modo texto
    mov ax, 0x0003
    int 0x10

    ; Retorna ao DOS
    mov ax, 0x4C00
    int 0x21
```

### Funções para Desenho em Modo Gráfico

```nasm
; Desenha pixel
; Parâmetros: BX = X, BP = Y, AL = cor
desenhar_pixel:
    pusha
    mov di, bp
    imul di, 320
    add di, bx
    mov [es:di], al
    popa
    ret

; Desenha linha horizontal
; Parâmetros: BX = X inicial, BP = Y, CX = comprimento, AL = cor
desenhar_linha_horizontal:
    pusha
    mov di, bp
    imul di, 320
    add di, bx
    rep stosb
    popa
    ret

; Desenha linha vertical
; Parâmetros: BX = X, BP = Y inicial, CX = altura, AL = cor
desenhar_linha_vertical:
    pusha
    mov di, bp
    imul di, 320
    add di, bx
.vertical_loop:
    mov [es:di], al
    add di, 320
    loop .vertical_loop
    popa
    ret

; Desenha retângulo preenchido
; Parâmetros: BX = X, BP = Y, DX = largura, CX = altura, AL = cor
desenhar_retangulo_preenchido:
    pusha
    mov si, bp              ; Y atual
.retangulo_loop:
    push cx
    mov di, si
    imul di, 320
    add di, bx
    mov cx, dx
    rep stosb
    pop cx
    inc si
    loop .retangulo_loop
    popa
    ret
```

***

## 3. Manipulação da Paleta VGA

A paleta VGA controla a correspondência entre índices de cor e cores RGB reais.

### Estrutura da Paleta

* **256 entradas** (0-255)
* **Cada cor**: 6 bits para R, G, B (0-63)
* **Portas**:
  * `0x3C8` - Índice da paleta (write)
  * `0x3C9` - Dados RGB

### Exemplo: Configurar Paleta

```nasm
; Configura paleta - deve ser feito após mudar para modo 13h
configurar_paleta:
    pusha
    mov dx, 0x3C8            ; Porta de índice da paleta
    xor al, al               ; Começa na cor 0
    out dx, al

    mov dx, 0x3C9            ; Porta de dados da paleta
    mov cx, 256              ; 256 cores

gradiente:
    ; R = índice / 4
    mov al, cl
    shr al, 2
    out dx, al

    ; G = índice / 2
    mov al, cl
    shr al, 1
    out dx, al

    ; B = índice
    mov al, cl
    out dx, al

    loop gradiente
    popa
    ret
```

### Função para Definir Cor Específica

```nasm
; Define cor na paleta
; Parâmetros: BL = índice, BH = R, DH = G, DL = B
definir_cor:
    pusha
    mov dx, 0x3C8
    mov al, bl
    out dx, al

    mov dx, 0x3C9
    mov al, bh
    out dx, al
    mov al, dh
    out dx, al
    mov al, dl
    out dx, al
    popa
    ret
```

***

## 4. Modo Gráfico 12h (640x480, 16 cores)

### Características

* **Resolução**: 640x480 pixels
* **Cores**: 16 cores (4 bits por pixel)
* **Memória**: 640 \* 480 / 2 = 153,600 bytes (4 bits/pixel)
* **Acesso**: 4 planos de bits (bit planes)

### Acesso a Bit Planes

No modo 12h, a memória é organizada em 4 planos de bits. Cada pixel é representado por 4 bits, um em cada plano.

```nasm
; Configura modo 12h
mov ax, 0x0012
int 0x10

; Seleciona plano de bits (sequenciador)
mov dx, 0x3C4
mov al, 2           ; Registrador Map Mask
out dx, al
inc dx
mov al, 0x0F        ; Habilita todos os 4 planos
out dx, al

; Desenha pixel branco em (100,50) - todos os planos
mov ax, 0xA000
mov es, ax
mov di, (50 * 640) + 100
shr di, 1           ; Divide por 2 (2 pixels por byte)
mov byte [es:di], 0xFF  ; Escreve em todos os planos
```

***

## 5. Desenhando Componentes de Interface

### Botão Simples

```nasm
; Parâmetros:
; BX = X, BP = Y, DX = Largura, CX = Altura
desenhar_botao:
    pusha
    mov si, dx               ; Salva largura

    ; Moldura superior
    mov di, bp
    imul di, 320
    add di, bx
    mov al, 15               ; Branco
    mov cx, dx
    rep stosb

    ; Laterais e interior
    dec cx
    mov dx, cx               ; Largura-1
    dec cx                   ; Altura-1

desenhar_lados:
    mov di, bp
    imul di, 320
    add di, bx

    ; Lado esquerdo
    mov byte [es:di], 15     ; Branco

    ; Interior (cinza)
    inc di
    mov al, 7                ; Cinza
    mov cx, dx
    rep stosb

    ; Lado direito
    mov byte [es:di], 8      ; Cinza escuro

    inc bp
    loop desenhar_lados

    ; Moldura inferior
    mov di, bp
    imul di, 320
    add di, bx
    mov al, 8                ; Cinza escuro
    mov cx, si               ; Largura original
    rep stosb

    popa
    ret
```

### Sistema de Janelas Simples

```nasm
; Parâmetros:
; BX = X, BP = Y, DX = Largura, CX = Altura, AL = Cor do título
desenhar_janela:
    pusha
    mov si, dx               ; Salva largura

    ; Barra de título
    mov di, bp
    imul di, 320
    add di, bx
    mov ah, al               ; Cor do título
    mov cx, dx
    
preencher_titulo:
    mov byte [es:di], ah
    inc di
    loop preencher_titulo

    ; Borda superior
    mov di, bp
    imul di, 320
    add di, bx
    mov byte [es:di], 15     ; Branco (canto esquerdo)
    add di, dx
    dec di
    mov byte [es:di], 8      ; Cinza escuro (canto direito)

    ; Conteúdo da janela
    inc bp                   ; Próxima linha
    dec cx                   ; Altura-1
    mov dx, si               ; Restaura largura

desenhar_conteudo:
    mov di, bp
    imul di, 320
    add di, bx

    ; Borda esquerda
    mov byte [es:di], 15     ; Branco

    ; Fundo
    inc di
    mov al, 7                ; Cinza
    mov cx, dx
    sub cx, 2                ; Largura-2
    rep stosb

    ; Borda direita
    mov byte [es:di], 8      ; Cinza escuro

    inc bp
    loop desenhar_conteudo

    ; Borda inferior
    mov di, bp
    imul di, 320
    add di, bx
    mov cx, si               ; Largura original
    
preencher_base:
    cmp cx, si               ; Primeiro pixel?
    je .borda_esquerda
    cmp cx, 1                ; Último pixel?
    je .borda_direita
    
    mov byte [es:di], 8      ; Cinza escuro
    jmp .proximo_pixel

.borda_esquerda:
    mov byte [es:di], 15     ; Branco
    jmp .proximo_pixel

.borda_direita:
    mov byte [es:di], 8      ; Cinza escuro

.proximo_pixel:
    inc di
    loop preencher_base

    popa
    ret
```

***

## 6. Double Buffering

Double buffering elimina flicker ao desenhar animações.

```nasm
section .bss
    buffer_back resb 64000   ; Buffer de 320x200 (64KB)

section .text
; Inicializa double buffer
init_double_buffer:
    pusha
    mov di, buffer_back
    mov cx, 64000
    xor al, al
    rep stosb                ; Limpa buffer
    popa
    ret

; Desenha no back buffer
desenhar_no_back:
    pusha
    mov es, buffer_back      ; Aponta para back buffer
    ; ... rotinas de desenho ...
    popa
    ret

; Copia back buffer para tela
swap_buffers:
    pusha
    mov si, buffer_back
    mov di, 0xA000
    mov es, di
    mov di, 0
    mov cx, 64000
    rep movsb                ; Copia 64KB
    popa
    ret
```

***

## 7. Entrada do Usuário

### Teclado (INT 16h)

```nasm
; Espera tecla
esperar_tecla:
    mov ah, 0x00
    int 0x16
    ret

; Verifica se tecla foi pressionada (não bloqueante)
tecla_pressionada:
    mov ah, 0x01
    int 0x16
    jz .nenhuma_tecla
    mov ah, 0x00
    int 0x16
    ret
.nenhuma_tecla:
    xor ax, ax
    ret
```

### Mouse (INT 33h)

```nasm
; Inicializa mouse
inicializar_mouse:
    mov ax, 0x0000
    int 0x33
    cmp ax, 0
    je .mouse_nao_encontrado
    ret
.mouse_nao_encontrado:
    mov ax, 0
    ret

; Obtém posição e botões
; Retorna: CX = X, DX = Y, BX = botões
obter_mouse:
    mov ax, 0x0003
    int 0x33
    ret
```

***

## 8. Exemplo Completo: Interface Gráfica Simples

```nasm
; interface.asm - Interface gráfica completa
section .text
    global _start

_start:
    ; Inicializa modo gráfico
    mov ax, 0x0013
    int 0x10
    mov ax, 0xA000
    mov es, ax

    ; Configura paleta
    call configurar_paleta

    ; Desenha interface
    mov bx, 50               ; X
    mov bp, 30               ; Y
    mov dx, 150              ; Largura
    mov cx, 100              ; Altura
    mov al, 9                ; Azul para barra de título
    call desenhar_janela

    ; Botão 1
    mov bx, 70
    mov bp, 70
    mov dx, 60
    mov cx, 20
    call desenhar_botao

    ; Texto no botão
    mov bx, 85
    mov bp, 75
    mov si, texto_botao
    mov al, 0x0F
    call escrever_texto_modo_grafico

    ; Loop principal
loop_principal:
    ; Verifica tecla
    mov ah, 0x01
    int 0x16
    jz loop_principal
    mov ah, 0x00
    int 0x16

    ; Retorna ao modo texto
    mov ax, 0x0003
    int 0x10

    ; Retorna ao DOS
    mov ax, 0x4C00
    int 0x21

; Inclui as rotinas gráficas
%include "paleta.asm"
%include "janela.asm"
%include "botao.asm"
%include "texto_grafico.asm"

section .data
    texto_botao db "Clique", 0
```

***

## Tabela de Referência Rápida

| Operação                       | Portas/Endereços              | Exemplo em Assembly                     |
| ------------------------------ | ----------------------------- | --------------------------------------- |
| Mudar modo de vídeo            | INT 10h, AH=00h, AL=mode      | `mov ax, 0x0013; int 0x10`              |
| Acesso memória vídeo (gráfico) | 0xA0000                       | `mov ax, 0xA000; mov es, ax`            |
| Acesso memória vídeo (texto)   | 0xB8000                       | `mov ax, 0xB800; mov es, ax`            |
| Modificar paleta               | 0x3C8 (índice), 0x3C9 (dados) | `mov dx, 0x3C8; mov al, 0; out dx, al`  |
| Desenhar pixel                 | ES:DI = 0xA000:Y\*320+X       | `mov di, (y*320)+x; mov [es:di], al`    |
| Escrever texto (modo texto)    | ES:DI = 0xB800:(Y\*80+X)\*2   | `mov [es:di], 'A'; mov [es:di+1], 0x0F` |

***

## Dicas para Interfaces Gráficas em Assembly

### 1. Organização do Código

* Separe rotinas gráficas em includes
* Crie macros para operações comuns
* Mantenha tabelas de cores e estilos

### 2. Otimização

* Use `REP STOSB` para preenchimentos
* Calcule endereços com `IMUL` para Y\*320
* Minimize acesso a portas de I/O
* Use double buffering para animações

### 3. Interação

* Use INT 16h para entrada de teclado
* Implemente rotinas de detecção de clique
* Considere double buffering para animações

### 4. Extensões

* Para sistemas modernos, considere VBE (VESA BIOS Extensions)
* Em ambientes protegidos, use drivers de vídeo

***

## Conclusão

A programação VGA em Assembly oferece controle total sobre o hardware gráfico, permitindo a criação de interfaces eficientes e personalizadas. Embora requeira mais esforço que linguagens de alto nível, o conhecimento dessas técnicas é valioso para:

* Desenvolvimento de sistemas embarcados
* Programação de jogos retrô
* Criação de sistemas operacionais
* Entendimento profundo de hardware gráfico

Para projetos modernos, considere combinar essas técnicas com:

* Aceleração por hardware
* Double buffering
* Suporte a resoluções maiores via VBE

***

## Recursos Adicionais

* **Livro**: "Programmer's Guide to the EGA/VGA" (Ferraro)
* **Documentação**: [VGA Hardware](https://wiki.osdev.org/VGA_Hardware)
* **OSDev Wiki**: [VGA Tutorial](https://wiki.osdev.org/VGA)
* **Ferramentas**: NASM, DOSBox, QEMU


---

# 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/7.-vga-e-criacao-de-interfaces-graficas.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.
