Ir para o conteúdo principal

Representação de Dados: Bits que Significam Algo

Autor
Francisco Bustamante
Um químico trabalhando com Ciência de Dados e Programação em Python.
Tabela de conteúdos
Por Dentro do Computador - Este artigo faz parte de uma série de artigos.
Parte 7: Esse Artigo

No artigo anterior — Pipeline e Barramentos — vimos como a CPU executa múltiplas instruções em paralelo e como os barramentos transportam informação entre os componentes. Mas o que é essa informação? Para o hardware, tudo são bits — tensões altas e baixas, zeros e uns. A diferença entre um caractere, um inteiro negativo e um número de ponto flutuante está exclusivamente na convenção de interpretação — na forma como acordamos que um padrão de bits deve ser lido.

Essa escolha não afeta apenas o software; ela molda o design físico do chip. A quantidade de bits que escolhemos para representar um dado dita diretamente a largura do barramento de dados, a capacidade dos registradores e a complexidade da UAL. A primeira dessas convenções que precisamos entender não lida com matemática pesada, mas com a forma como o computador aprendeu a ler e escrever conosco: o texto.

Este artigo percorre essas convenções fundamentais: os padrões para representar texto (ASCII, Unicode, UTF-8), os três métodos para inteiros com sinal (e por que o complemento a dois dominou), os deslocamentos de bits e o padrão IEEE 754 para números reais. Entender essas representações é essencial para compreender por que 0.1 + 0.2 ≠ 0.3 em programação e como números negativos funcionam em hardware.

Observação: alguns assuntos deste artigo já foram abordados em artigos anteriores aqui do site. Temos uma série de artigos sobre representação numérica que cobre os detalhes de complemento a 2, deslocamentos e ponto flutuante. Este artigo aqui serve como um resumo integrado desses conceitos, focando na perspectiva de arquitetura de computadores .

Representação de caracteres
#

O primeiro problema resolvido pelos computadores não foi o cálculo — foi a comunicação: como representar letras, dígitos e símbolos como bits? Para isso, o computador usa uma codificação de caracteres (character encoding): uma convenção que associa símbolos a números.

É importante separar três ideias que às vezes aparecem misturadas:

  • código de caracteres: a tabela de símbolos;
  • ponto de código: o número abstrato associado a um caractere;
  • codificação: a forma concreta de armazenar esse ponto de código em bytes.
Sistema Natureza Observação
ASCII Código de caracteres de 7 bits 128 símbolos; base histórica do texto em sistemas modernos
EBCDIC Código de caracteres de 8 bits Usado historicamente em ambientes IBM
Latin-1 (ISO 8859-1) Código de caracteres de 8 bits Extensão para línguas ocidentais
Unicode Repertório universal de pontos de código Define os caracteres; não define sozinho como armazená-los
UTF-8 / UTF-16 / UTF-32 Codificações Unicode Formas de armazenar pontos de código em bytes

ASCII, Latin-1 e o 8º bit
#

O ASCII (American Standard Code for Information Interchange) usa 7 bits e representa 128 símbolos. Ele inclui:

  • caracteres de controle (0 a 31);
  • caracteres imprimíveis (32 a 127), como letras, dígitos e pontuação.

Historicamente, em muitos sistemas o 8º bit do byte podia ser usado como bit de paridade para detectar erros de transmissão. Em outros contextos, esse bit passou a ser aproveitado para extensões de 8 bits, como o Latin-1, permitindo representar caracteres acentuados e símbolos adicionais.

Unicode e codificações UTF
#

O Unicode não deve ser entendido como uma codificação fixa de 16 bits, mas como um repertório universal de pontos de código. Seu espaço de códigos vai de U+0000 até U+10FFFF.

Para armazenar esses pontos de código em memória ou em arquivos, usamos codificações como:

Codificação Comprimento Característica principal
UTF-8 1 a 4 bytes Compatível com ASCII nos primeiros 128 códigos
UTF-16 2 ou 4 bytes Usa 1 unidade de 16 bits no BMP e pares substitutos fora dele
UTF-32 4 bytes Um ponto de código por unidade de 32 bits

Assim, o correto é pensar:

  • Unicode = repertório de caracteres;
  • UTF-8 / UTF-16 / UTF-32 = maneiras de codificar esse repertório.
UTF-8 domina a prática moderna

O UTF-8 se tornou a codificação dominante porque preserva total compatibilidade com ASCII nos primeiros 128 códigos e usa comprimento variável apenas quando necessário. Para arquivos de texto, protocolos e páginas web, ele é hoje a escolha padrão.

Inteiros sem sinal
#

Para inteiros sem sinal (unsigned), a representação é direta: cada bit corresponde a uma potência de 2, do LSB (bit menos significativo, \(b_0\)) ao MSB (bit mais significativo):

$$N_{10} = \sum_{i=0}^{n-1} b_i \cdot 2^i$$

Exemplo: \(10110101_2\):

$$= 1\cdot2^7 + 0\cdot2^6 + 1\cdot2^5 + 1\cdot2^4 + 0\cdot2^3 + 1\cdot2^2 + 0\cdot2^1 + 1\cdot2^0 = 128 + 32 + 16 + 4 + 1 = 181_{10}$$

Conversão binário ↔ hexadecimal
#

O hexadecimal funciona como uma notação compacta para binário: agrupe os bits de 4 em 4, da direita para a esquerda, e converta cada grupo para seu dígito hexadecimal equivalente (0–9, A–F).

Binário Grupos de 4 Hexadecimal Decimal
01011010 0101 + 1010 5A 90
11110011 1111 + 0011 F3 243

Verificação: \(\text{5A}_{16} = 5 \times 16 + 10 = 80 + 10 = 90_{10}\) ✓

Inteiros com sinal
#

Representar números negativos exige uma convenção adicional. Ao longo da história, três métodos foram usados:

Sinal e magnitude
#

O MSB indica o sinal (0 = positivo, 1 = negativo); os demais \(n-1\) bits representam o módulo. Intervalo: \(-(2^{n-1}-1)\) a \(+(2^{n-1}-1)\). O problema fatal: dois zeros — \(+0 = 0000\,0000\) e \(-0 = 1000\,0000\) — complicam circuitos de comparação e aritmética.

Complemento de 1 (C1)
#

O negativo de um número é obtido invertendo todos os bits. O resultado de \(-5\) em 8 bits: \(+5 = 0000\,0101 \Rightarrow -5 = 1111\,1010\). A aritmética fica mais simples do que no sinal e magnitude, mas o problema de dois zeros permanece (\(0000\,0000\) e \(1111\,1111\)). O C1 raramente é usado em sistemas modernos.

Complemento de 2 (C2) — o padrão moderno
#

O negativo é obtido invertendo todos os bits e somando 1 ao resultado. O C2 tem apenas um zero, e a subtração se reduz a uma adição — o hardware da UAL precisa de apenas um somador para realizar as duas operações.

$$\text{Intervalo:} \quad -2^{n-1} \leq x \leq +(2^{n-1}-1)$$
\(n\) bits Mínimo Máximo
8 \(-128\) \(+127\)
16 \(-32.768\) \(+32.767\)
32 \(-2.147.483.648\) \(+2.147.483.647\)
Por que o complemento a 2 é o padrão?

Três razões concretas fazem do C2 o padrão universal:

  1. Subtração = adição: \(A - B = A + C2(B)\) — a UAL precisa apenas de um somador.
  2. Zero único: sem ambiguidade entre \(+0\) e \(-0\).
  3. Intervalo assimétrico: em 8 bits, vai de \(-128\) a \(+127\) — o lado negativo tem um valor a mais do que o sinal e magnitude, o que simplifica a faixa de representação.

Operações em complemento a 2
#

Como calcular o C2 de um número (negação)
#

O algoritmo tem três passos:

  1. Escrever o número em binário
  2. Inverter todos os bits (obter o complemento de 1)
  3. Somar 1 ao resultado
Passo Bits
\(+5\) em binário 0000 0101
Inverter todos os bits (C1) 1111 1010
Somar 1 → resultado 1111 1011 = \(-5\) ✓

Verificação (\(+5 + (-5)\) deve ser zero):

$$0000\,0101 + 1111\,1011 = \underbrace{1}_{\text{carry}}\;0000\,0000 \xrightarrow{\text{descarta carry}} 0000\,0000 = 0 \;\checkmark$$

Subtração como adição: \(A - B = A + C2(B)\)
#

Para entender como isso funciona na prática, vamos simular a operação 5 - 3. Seguindo a fórmula acima, definimos \(A = 5\) e \(B = 3\). Em vez de usar um circuito dedicado para subtrair, a CPU calcula o complemento de dois de 3 (obtendo a representação em bits de -3) e soma esse valor diretamente ao número 5. A tabela a seguir detalha esse processo passo a passo usando 8 bits:

Passo Operação Resultado
Representar \(+3\) binário 0000 0011
Inverter bits (C1) 1111 1100
Somar 1 → \(C2(3) = -3\) 1111 1101
Somar \(5 + (-3)\) 0000 0101 + 1111 1101 \(\underbrace{1}_{\text{carry}}\,0000\,0010\)
Descartar carry 0000 0010 = \(2\) ✓
Exemplo — Adição, subtração e overflow em 8 bits

Considere \(A = 00110010_2 = +50_{10}\) e \(B = 11010000_2\). Para determinar o valor de B: como o MSB é 1, é negativo. \(C2(B) = 00110000_2 = 48\), portanto \(B = -48_{10}\).

a) \(A + B\): \(00110010 + 11010000 = 1\;00000010_2\) → descarta carry → \(00000010_2 = +2_{10}\) ✓ (\(50 + (-48) = +2\) — sinais opostos nunca geram overflow)

b) \(B - A = B + C2(A)\): \(C2(A)\): inverter \(00110010 = 11001101\) + 1 = \(11001110_2\) \(11010000 + 11001110 = 1\;10011110_2\) → descarta carry → \(10011110_2\) MSB=1 → negativo: \(C2(10011110) = 01100010 = 98\) → resultado = \(-98_{10}\) (\(-48 - 50 = -98\) ✓ — dentro do intervalo \([-128, +127]\))

c) Dois positivos podem somar para um resultado negativo? Sim — isso é exatamente o overflow. Exemplo: \(C = 01000001_2 = +65\) e \(D = 01100000_2 = +96\): \(C + D = 11100001_2\) → MSB=1 → interpretado como negativo, mas \(65 + 96 = 161 > 127\) → overflow

Detectando overflow
#

Overflow em complemento a 2

O overflow ocorre quando o resultado correto não cabe no número de bits disponíveis:

  • Dois positivos somados → resultado negativo = overflow ❌
  • Dois negativos somados → resultado positivo = overflow ❌
  • Positivo + Negativonunca gera overflow ✓

Regra de hardware: overflow ocorre quando o carry de entrada no bit de sinal é diferente do carry de saída do bit de sinal.

Caso essa parte do overflow tenha sido difícil para você, temos todo um artigo dedicado a isso na série Do Zero ao Float, onde explicamos o conceito de overflow em detalhes, com exemplos e exercícios.

Deslocamentos de bits (shifts)
#

Essa eficiência estrutural do Complemento a 2 não se limita apenas à facilidade de somar números negativos; ela permite que o hardware utilize “atalhos” matemáticos. A operação mais eficiente possível para multiplicar ou dividir por potências de 2 não aciona somadores complexos, mas sim os deslocamentos de bits (shifts) — uma operação resolvida “empurrando” bits para os lados em um único ciclo de UAL.

Operação Efeito matemático Bit inserido
Deslocamento à esquerda (1 bit) Multiplica por 2 0 à direita
Deslocamento lógico à direita (1 bit) Divide por 2 (inteiro sem sinal) 0 à esquerda
Deslocamento aritmético à direita (1 bit) Divide por 2 (inteiro com sinal) Réplica do MSB (bit de sinal)

A réplica do MSB funciona da seguinte forma: se o número é positivo (MSB = 0), o deslocamento à direita preenche com 0, mantendo o resultado positivo. Se o número é negativo (MSB = 1), o deslocamento preenche com 1, preservando o sinal negativo. Isso faz com que o deslocamento aritmético à direita se comporte como uma divisão inteira por 2, arredondando para baixo, mesmo para números negativos. Por exemplo: \(-3\) em 8 bits é 1111 1101. Deslocar à direita aritmeticamente resulta em 1111 1110, pois o MSB é 1, indicando um número negativo, e 1 é inserido à esquerda para manter o sinal. O resultado é \(-2\), que é o resultado esperado de \(-3\) dividido por 2, arredondando para baixo.

Exemplos em 8 bits:

Operação Antes Depois Valor
Shift esquerdo 0000 0011 (3) 0000 0110 6 = 3 × 2 ✓
Shift lógico direito 0000 0110 (6) 0000 0011 3 = 6 ÷ 2 ✓
Shift aritmético direito 1111 0000 (−16) 1111 1000 −8 = −16 ÷ 2 ✓

Deslocamento aritmético à direita: cuidado com a interpretação
#

O deslocamento aritmético à direita é frequentemente apresentado como uma forma rápida de “dividir por 2” inteiros com sinal. Isso é útil como intuição, mas merece uma observação:

  • para inteiros sem sinal, o deslocamento lógico à direita equivale à divisão inteira por 2;
  • para inteiros com sinal em complemento a 2, o deslocamento aritmético à direita preserva o bit de sinal, o que faz o resultado se comportar como um arredondamento para baixo em muitos casos negativos.

Por isso, a frase mais segura é:

o deslocamento aritmético à direita é uma operação de hardware que, em complemento a 2, costuma corresponder à divisão inteira por potência de 2 com preservação do sinal.

Dica: aritmético × lógico

Use shift aritmético à direita para dividir inteiros com sinal (replica o bit de sinal, preservando-o). Use shift lógico para inteiros sem sinal (preenche com 0). Deslocar à esquerda multiplica por 2 em ambos os casos — basta garantir que não há overflow.

Exemplo — Divisão por 2 repetida com deslocamento aritmético

Considere \(A = 01011110_2 = +94_{10}\) e \(B = 10011101_2 = -99_{10}\).

Dividindo A (positivo) por 2 com shift aritmético à direita: \(01011110 \to 00101111 = 47 \to 00010111 = 23 \to 00001011 = 11 \to 00000101 = 5 \to 00000010 = 2 \to 00000001 = 1 \to 00000000 = 0\) Cada step divide por 2 (truncando), até atingir zero.

Dividindo B (negativo) por 2: o shift aritmético replica o bit de sinal (MSB=1), preservando o sinal negativo: \(10011101 \to 11001110 = -50 \to 11100111 = -25 \to 11110011 = -13 \to 11111001 = -7 \to 11111100 = -4 \to 11111110 = -2 \to 11111111 = -1 \to 11111111 = -1\) Para números negativos, o processo converge para −1 (não para zero), pois o bit de sinal nunca é eliminado.

Ponto flutuante: o padrão IEEE 754
#

Embora os inteiros em Complemento a 2 sejam perfeitos para contagens exatas e manipulação de memória, o mundo físico — com suas distâncias microscópicas e grandezas astronômicas — exige uma flexibilidade que os bits fixos não conseguem oferecer. Para grandezas contínuas, precisamos de números reais aproximados. O ponto flutuante resolve isso utilizando uma notação científica normalizada em base 2:

$$(-1)^S \times 1{,}\text{mantissa} \times 2^E$$

onde \(S\) é o bit de sinal (0 = positivo, 1 = negativo), \(E\) é o expoente inteiro e a mantissa são os bits fracionários após o 1. implícito.

Mas de onde vêm as regras para guardar isso em bits? Historicamente, cada fabricante de computador criava seu próprio jeito de representar números de ponto flutuante, o que causava um caos: um mesmo cálculo científico dava resultados diferentes dependendo de qual marca de computador o executasse. Para unificar a indústria, o IEEE (Institute of Electrical and Electronics Engineers — a principal organização mundial de padronização para engenharia elétrica e computação) publicou em 1985 a norma IEEE 754.

O padrão IEEE 754 original definiu com exatidão os formatos básicos de precisão simples e dupla, estabelecendo apenas requisitos mínimos para formatos “estendidos”. A tabela a seguir mostra os formatos de 32 e 64 bits definidos na norma, além do famoso formato extended de 80 bits (uma implementação específica da Intel/x86 que atende aos requisitos de formato estendido da norma):

Precisão Sinal Expoente Mantissa Total Bias
Single (32 bits) 1 bit 8 bits 23 bits 32 bits 127
Double (64 bits) 1 bit 11 bits 52 bits 64 bits 1.023
Extended (80 bits) 1 bit 15 bits 64 bits 80 bits 16.383

O expoente é armazenado com bias (viés): o valor real é o armazenado menos o bias, permitindo representar expoentes negativos sem bit de sinal próprio. O bit 1 à esquerda do ponto é implícito no single e double — não precisa ser armazenado, adicionando um bit extra de precisão efetiva (24 bits no single, 53 bits no double). Já no formato extended (80 bits), esse bit inteiro inicial é explícito e precisa ser armazenado, ocupando um espaço real e resultando em exatos 64 bits de precisão na mantissa. Hoje em dia, o formato extended de 80 bits é amplamente considerado legado: ele era o padrão interno dos antigos coprocessadores matemáticos (x87 FPU) da arquitetura x86. Processadores modernos geralmente realizam cálculos de ponto flutuante usando registradores vetoriais (SSE/AVX) otimizados para os formatos single e double. Contudo, o extended ainda é suportado nos processadores atuais por questões de retrocompatibilidade (sendo frequentemente mapeado para o tipo long double em compiladores C/C++ na arquitetura x86).

Abaixo, a estrutura de bits para o formato de precisão simples (32 bits) do IEEE 754, onde o bit de sinal é o mais significativo (MSB), seguido pelo expoente com bias e pela mantissa fracionária:

 31  30        23 22                       0
 ┌───┬──────────┬──────────────────────────┐
 │ S │ Expoente │        Mantissa          │
 │ 1 │  8 bits  │         23 bits          │
 └───┴──────────┴──────────────────────────┘

Casos especiais
#

O IEEE 754 reserva padrões específicos para situações limite:

Expoente Mantissa Significado
00000000 000...0 Zero (\(\pm 0\))
00000000 \(\neq 0\) Número denormalizado (subnormal)
11111111 000...0 \(\pm\infty\)
11111111 \(\neq 0\) NaN (Not a Number)
O vácuo perto do zero e o Underflow

Se você observar a matemática do IEEE 754, perceberá que existe um “salto” de precisão considerável entre o menor número normalizado possível e o zero absoluto. Para evitar que cálculos percam a precisão abruptamente e desabem para zero ao lidar com valores atômicos (um problema conhecido como underflow), o padrão introduziu os números denormalizados. Eles abrem mão do 1. implícito na mantissa para conseguir representar valores absurdamente pequenos (como \(1,4 \times 10^{-45}\) na precisão simples), preenchendo esse “vácuo” com uma degradação suave de precisão.

Convertendo para IEEE 754 single precision
#

flowchart TD
    A["Número decimal com sinal"] --> B["1. Converter para binário"]
    B --> C["2. Normalizar: 1.xxx × 2^E"]
    C --> D["3. Bit de sinal S
0 = positivo, 1 = negativo"] C --> Exp["4. Expoente com bias
E_real + 127"] C --> Mant["5. Mantissa
bits após o 1 implícito
(completar com zeros à direita)"] D --> R["Resultado: S | Expoente | Mantissa"] Exp --> R Mant --> R

Aplicando ao exemplo \(-5{,}75\):

Passo Operação Resultado
1. Converter para binário \(5 = 101_2\); \(0{,}75 \times 2 = 1{,}50\) → 1; \(0{,}5 \times 2 = 1{,}0\) → 1 \(-101{,}11_2\)
2. Normalizar Mover ponto 2 posições à esquerda \(-1{,}0111 \times 2^2\)
3. Bit de sinal Negativo 1
4. Expoente com bias \(E_{\text{real}} = 2\); \(2 + 127 = 129\) \(10000001_2\)
5. Mantissa Bits após 1.: 0111, completar com zeros 01110000000000000000000
Resultado final 1 10000001 01110000000000000000000

Verificação:

$$(-1)^1 \times 1{,}0111_2 \times 2^{129-127} = -1{,}0111_2 \times 2^2 = -101{,}11_2 = -5{,}75_{10} \;\checkmark$$
Exemplo — Decodificando um formato personalizado de 16 bits

Um formato hipotético usa: 1 bit de sinal, 5 bits de expoente com bias 15, e 10 bits de mantissa (normalizado — parte inteira implícita = 1).

Dado o padrão BA32₁₆ = 1011 1010 0011 0010₂:

  • Sinal: 1 → negativo
  • Expoente: 01110₂ = 14 → \(E_{\text{real}} = 14 - 15 = -1\)
  • Mantissa: 1000110010₂

Valor: \(-(1{,}1000110010_2) \times 2^{-1}\)

Convertendo a mantissa: \(1 + 2^{-1} + 2^{-5} + 2^{-6} + 2^{-9} = 1 + 0{,}5 + 0{,}03125 + 0{,}015625 + 0{,}001953\ldots \approx 1{,}5488\)

Resultado: \(-1{,}5488 \times 0{,}5 \approx -0{,}7744\)

Maior valor positivo normalizado: expoente = 11110₂ = 30 → \(E = 15\); mantissa = 1111111111₂ → \(1{,}1111111111_2 \times 2^{15} = 65504\)

Menor valor positivo normalizado: expoente = 00001₂ = 1 → \(E = -14\); mantissa = 0000000000₂ → \(1{,}0 \times 2^{-14} \approx 0{,}000061\)

Exemplo — Decodificando um número IEEE 754

Número com: sinal = 0 (positivo), mantissa = 1100100₂, expoente real = −3.

Número normalizado: \(+(1{,}1100100)_2 \times 2^{-3}\)

Convertendo a mantissa: \(1 + 2^{-1} + 2^{-2} + 2^{-5} = 1 + 0{,}5 + 0{,}25 + 0{,}03125 = 1{,}78125\)

Resultado: \(1{,}78125 \times 2^{-3} = 1{,}78125 / 8 = \mathbf{0{,}222656}\)

Aprofundamento: a série “Do Zero ao Float”

O padrão IEEE 754 tem muitas nuances além do que cobrimos aqui: arredondamento, números subnormais, operações especiais e as armadilhas de comparar floats. Se você quiser explorar esses tópicos em profundidade — incluindo por que 0.1 + 0.2 ≠ 0.3 em praticamente toda linguagem de programação — a série Do Zero ao Float cobre tudo isso com diversos exemplos.

Bônus Python: inspecionando representações de bits
#

Python oferece ferramentas diretas para inspecionar como números são armazenados em bits, usando o módulo struct (para ponto flutuante) e os operadores << e >> (para inteiros).

import struct

# Representação IEEE 754 single precision de -5.75
raw = struct.pack(">f", -5.75)          # ">f" = big-endian single float
print(f"-5.75 como bytes : {raw.hex()}")
# c0b80000

bits = int.from_bytes(raw, "big")
print(f"Em binário (32)  : {bits:032b}")
# 11000000101110000000000000000000
# S=1 | Exp=10000001 | Mant=01110000000000000000000 ✓

# Desempacotando de volta
valor = struct.unpack(">f", raw)[0]
print(f"De volta ao float: {valor}")
# -5.75 ✓

# Shifts e complemento a 2 com inteiros Python
a = 0b00110010  # +50 em decimal
b = 0b11010000  # em 8 bits sem sinal = 208, em C2 = -48

print(f"\na = {a}  ({a:08b})")
print(f"a << 1 = {a << 1}  ({a<<1:08b})  (× 2)")
print(f"a >> 1 = {a >> 1}  ({a>>1:08b})  (÷ 2)")

# Complemento a 2 em Python (Python usa inteiros de precisão arbitrária)
def c2_negacao(n: int, bits: int = 8) -> int:
    """Retorna -n em representação complemento a 2 com 'bits' bits."""
    mascara = (1 << bits) - 1          # 0xFF para 8 bits
    return (~n & mascara) + 1

print(f"\n-50 em C2 (8 bits) : {c2_negacao(50):08b} = {c2_negacao(50)}")
# 11001110 = 206 (em unsigned) ou -50 (em C2)

# Adição com truncamento para 8 bits
def soma_c2(a: int, b: int, bits: int = 8) -> int:
    mascara = (1 << bits) - 1
    return (a + b) & mascara

print(f"50 + (-48) em 8 bits: {soma_c2(a, b):08b} = {soma_c2(a, b)}")
# 00000010 = 2 ✓

# Verificando -5.75 como double (64 bits)
raw64 = struct.pack(">d", -5.75)
bits64 = int.from_bytes(raw64, "big")
print(f"\n-5.75 double (64 bits): {bits64:064b}")
# 1 10000000001 0111000000000000000000000000000000000000000000000000

Conclusão e próximos artigos
#

Bits sozinhos não têm significado — o significado emerge da convenção de interpretação. O ASCII transforma 7 bits em um caractere; o complemento a dois transforma um padrão de bits em um inteiro negativo; o IEEE 754 transforma 32 bits em um número fracionário de precisão. Entender essas convenções é entender como o computador funciona.

No próximo artigo, vamos explorar a representação de instruções de máquina — como os padrões de bits que compõem as instruções que a CPU executa, os diferentes formatos de instrução e os modos de endereçamento que determinam onde buscar os operandos. Compreender a representação de dados é o passo fundamental para entender a representação de instruções, pois as instruções também são apenas padrões de bits, mas com uma estrutura específica que o hardware interpreta para realizar operações.

Até lá!

Por Dentro do Computador - Este artigo faz parte de uma série de artigos.
Parte 7: Esse Artigo

Relacionados