Representação de Dados
Vídeo da aula estará disponível em breve
Sistemas Numéricos
Computadores operam em binário (base 2): cada fio, cada transistor, cada célula de memória está em um de dois estados — 0 ou 1. Mas para humanos, binário é difícil de ler. Por isso usamos hexadecimal (base 16) como notação compacta: cada dígito hex representa exatamente 4 bits.
Decimal Binário Octal Hexadecimal
─────── ────────── ───── ───────────
0 0000 0 0
1 0001 1 1
5 0101 5 5
8 1000 10 8
10 1010 12 A
15 1111 17 F
16 10000 20 10
42 101010 52 2A
255 11111111 377 FF
256 100000000 400 100
Conversão rápida binário ↔ hex:
Agrupe de 4 em 4 bits (da direita para esquerda):
1010 1100 0011 1111 = AC3F₁₆
Cada grupo de 4 bits = 1 dígito hex:
0000=0 0001=1 0010=2 0011=3 0100=4 0101=5
0110=6 0111=7 1000=8 1001=9 1010=A 1011=B
1100=C 1101=D 1110=E 1111=F
Notações no código:
Binário: 0b10101100 (prefixo 0b)
Octal: 0254 (prefixo 0)
Decimal: 172 (sem prefixo)
Hexadecimal: 0xAC (prefixo 0x)
Cada base tem sua utilidade: decimal para humanos, binário para o hardware, hex para programadores que precisam visualizar padrões de bits (endereços de memória, cores, instruções codificadas).
Complemento a 2: Inteiros com Sinal
Como representar números negativos em binário? A solução universalmente adotada é o complemento a 2. A ideia é elegante: o bit mais significativo (MSB) tem peso negativo.
Binário Unsigned Complemento a 2
──────── ───────── ────────────────
0000 0 0
0001 1 +1
0010 2 +2
0011 3 +3
0100 4 +4
0101 5 +5
0110 6 +6
0111 7 +7 ← maior positivo
1000 8 -8 ← menor negativo (assimétrico!)
1001 9 -7
1010 10 -6
1011 11 -5
1100 12 -4
1101 13 -3
1110 14 -2
1111 15 -1
Fórmula (N bits):
Valor = -b_{N-1} × 2^{N-1} + b_{N-2} × 2^{N-2} + ... + b_0 × 2^0
Exemplo (8 bits): 1101 0110
= -1×128 + 1×64 + 0×32 + 1×16 + 0×8 + 1×4 + 1×2 + 0×1
= -128 + 64 + 16 + 4 + 2
= -42
Intervalo com N bits:
Mínimo: -2^{N-1} (ex: -128 para 8 bits, -2147483648 para 32 bits)
Máximo: 2^{N-1} - 1 (ex: +127 para 8 bits, +2147483647 para 32 bits)
Para negar um número em complemento a 2: inverta todos os bits e some 1.
Exemplo: negar +5 (8 bits)
+5 = 0000 0101
Inverte: 1111 1010
Soma 1: 1111 1011 = -5 ✓
Verificação: 5 + (-5) deve dar 0:
0000 0101 (+5)
+ 1111 1011 (-5)
──────────
1 0000 0000 = 0 (o carry-out é ignorado em 8 bits)
Por que complemento a 2 é genial:
1. Subtração = soma com o negado (hardware reusa o somador!)
2. Apenas uma representação para zero (diferente de sinal-magnitude)
3. Comparação de magnitude funciona para positivos sem hardware extra
Extensão de Sinal
Quando precisamos expandir um valor de menos bits para mais bits (ex: imediato de 16 bits para registrador de 32 bits), usamos extensão de sinal: replicamos o bit de sinal para preencher os bits superiores.
# Positivo: estender +5 de 8 bits para 16 bits
8 bits: 0000 0101 (+5)
16 bits: 0000 0000 0000 0101 (+5) ✓
Regra: MSB = 0, preenche com 0s
# Negativo: estender -5 de 8 bits para 16 bits
8 bits: 1111 1011 (-5)
16 bits: 1111 1111 1111 1011 (-5) ✓
Regra: MSB = 1, preenche com 1s
# Onde isso acontece no MIPS:
# - addi, slti: imediato de 16 bits → extensão de sinal para 32 bits
# - lb (load byte): byte de 8 bits → extensão de sinal para 32 bits
# - lbu (load byte unsigned): extensão com ZEROS (zero-extension)
# - beq/bne: offset de 16 bits → extensão de sinal para 32 bits
# CUIDADO: andi, ori NÃO fazem extensão de sinal!
# Eles fazem zero-extension (preenchem com 0s).
# andi $t0, $s1, 0xFFFF → AND com 0x0000FFFF (não 0xFFFFFFFF)
Overflow: Quando os Bits Não São Suficientes
Overflow ocorre quando o resultado de uma operação excede o intervalo representável. Em complemento a 2 com 32 bits, somar dois positivos grandes pode dar um "resultado negativo" — isso é overflow.
# Overflow em adição (4 bits, intervalo -8 a +7):
0101 (+5)
+ 0100 (+4)
──────
1001 (-7 em complemento a 2!) ← OVERFLOW! Resultado correto seria +9
# Regras de detecção:
# Overflow ocorre quando:
# (+) + (+) = (-) ← soma de positivos dá negativo
# (-) + (-) = (+) ← soma de negativos dá positivo
#
# Overflow NÃO ocorre quando:
# (+) + (-) = qualquer ← sinais diferentes nunca causam overflow
# (-) + (+) = qualquer ← sinais diferentes nunca causam overflow
# No MIPS:
# - add, addi, sub: GERAM exceção (trap) em overflow
# - addu, addiu, subu: IGNORAM overflow (unsigned, sem trap)
#
# Na prática, compiladores C usam addu/addiu porque C define
# overflow de inteiros como undefined behavior, e a exceção
# causaria um crash inesperado.
# Detecção por hardware:
# Overflow = Carry_in do MSB XOR Carry_out do MSB
# Se esses dois carries diferem, houve overflow.
Representação de Caracteres
Computadores representam texto como números. Dois padrões dominam:
# ASCII (7 bits, 128 caracteres):
# Suficiente para inglês, insuficiente para o resto do mundo.
Char Decimal Hex Binário
──── ─────── ──── ────────
'0' 48 0x30 011 0000 ← Dígitos: 0x30–0x39
'9' 57 0x39 011 1001
'A' 65 0x41 100 0001 ← Maiúsculas: 0x41–0x5A
'Z' 90 0x5A 101 1010
'a' 97 0x61 110 0001 ← Minúsculas: 0x61–0x7A
'z' 122 0x7A 111 1010
' ' 32 0x20 010 0000 ← Espaço
'\n' 10 0x0A 000 1010 ← Nova linha
'\0' 0 0x00 000 0000 ← Terminador de string em C
# Truque útil: 'a' - 'A' = 32 = 0x20 (bit 5)
# Para converter maiúscula → minúscula: OR com 0x20
# Para converter minúscula → maiúscula: AND com 0xDF (NOT 0x20)
# Unicode (UTF-8, UTF-16, UTF-32):
# UTF-8: compatível com ASCII (1 byte para ASCII, 2-4 para o resto)
# UTF-16: 2 bytes para maioria, 4 para emojis e caracteres raros
# UTF-32: 4 bytes fixos por caractere (simples mas desperdiça espaço)
#
# 'ã' em UTF-8: 0xC3 0xA3 (2 bytes)
# 'ç' em UTF-8: 0xC3 0xA7 (2 bytes)
# Em MIPS, strings são sequências de bytes terminadas por '\0' (null).
lb quanto lbu funcionam porque o bit 7 é 0. Mas para caracteres estendidos (128-255), use lbu para evitar que a extensão de sinal transforme o valor em negativo.
No harness.os
Representação é sobre codificação de informação — o harness.os codifica conhecimento em tipos estruturados (build, product, operations, domain) da mesma forma que o computador codifica dados em complemento a 2.
Conceito de Representação Equivalente no harness.os
────────────────────────────── ────────────────────────────────────
Binário (2 estados) Decisões binárias: sim/não, pass/fail,
blocked/unblocked
Complemento a 2 (codificação Tipagem de conhecimento: o "tipo"
com convenção de interpretação) (build/product/ops/domain) determina
como o dado é interpretado, assim
como o formato (signed/unsigned)
determina se 1111 é -1 ou 15
Extensão de sinal (preservar Herança de contexto: quando um agente
significado ao expandir) filho herda contexto do pai, o
"sinal" (intenção/propósito) deve
ser preservado, não truncado
Overflow (limites da Compaction: quando a context window
representação) "transborda", o harness precisa
detectar e reagir — assim como o
hardware detecta overflow
ASCII → Unicode (evolução da Evolução do schema: de campos simples
codificação) para estruturas ricas, mantendo
compatibilidade retroativa
Homework
- Converta para as outras bases: (a) 0xDEAD em binário e decimal, (b) 0b11001010 em hex e decimal, (c) 173 em binário e hex.
- Represente -100 em complemento a 2 com 8 bits. Verifique somando com +100 e mostrando que o resultado é 0 (ignorando o carry-out).
- Explique por que a extensão de sinal de
0xFF(8 bits) produz0xFFFFFFFF(32 bits) comlb, mas0x000000FFcomlbu. Qual é o valor decimal em cada caso? - Determine se ocorre overflow nas seguintes operações em 8 bits (complemento a 2): (a) 100 + 50, (b) -100 + (-50), (c) 100 + (-50), (d) -100 + 50.
Resumo
- Binário (base 2) é a representação nativa; hex (base 16) é a notação compacta usada por programadores
- Complemento a 2: o MSB tem peso negativo; intervalo de -2^(N-1) a 2^(N-1)-1
- Negação: inverter bits + somar 1; subtração reusa o somador do hardware
- Extensão de sinal: replica o MSB ao expandir; lb faz extensão de sinal, lbu faz zero-extension
- Overflow: soma de mesmo sinal com resultado de sinal oposto; add gera exceção, addu ignora
- ASCII (7 bits, 128 chars) e Unicode/UTF-8 (variável, compatível com ASCII)
Verifique seu entendimento
Em complemento a 2 com 8 bits, qual é o valor decimal de 1001 0110?