Como a comparação de números inteiros funciona internamente?

18

Por exemplo, ao comparar dois números inteiros da seguinte forma em um idioma semelhante ao C:

if (3 > 2) {
    // do something
}

Como é o julgamento se 3 é maior que 2 (verdadeiro) ou não (falso) feito internamente?

Niek
fonte
19
A resposta atual é válida para o caso em que a comparação se refere à expressão variável, mas não existe a isenção de responsabilidade de que muitos compiladores modernos analisarão seu trecho de código, detectam que a expressão sempre será verdadeira (por causa de literais) e simplesmente ignoram o ifconjunto. , indo direto para a codificação do something.
SJuan76
3
Possível duplicata de How Do Computers Work?
3
@ Snowman eu discordo. Qualquer pergunta de programação "como isso funciona" pode ser resumida a essa pergunta, mas isso não as torna duplicadas.
user1643723
1
@ user1643723 Faz quando a função em questão é um código de operação específico.
usar o seguinte comando
1
@ user1643723 A pergunta é sobre como um computador executa uma operação básica, e a resposta principal discute portas lógicas e tabelas lógicas. Dois tópicos abordados extensivamente na principal resposta do alvo idiota, que também responde à sua pergunta.

Respostas:

61

Todo o caminho até a toca do coelho, não é? OK, vou tentar.

Etapa 1. De C à linguagem de máquina

O compilador C transforma sua comparação com códigos de operação armazenados em linguagem de máquina . A linguagem de máquina é uma série de números que a CPU interpreta como instruções. Nesse caso, haveria dois opcodes: "subtrair com carry" e "pular se carregar". Em outras palavras, 2 é subtraído de 3 em uma instrução e a próxima instrução verifica se ela estourou. Estes seriam precedidos por duas instruções para carregar os números 2 e 3 nos locais onde eles podem ser comparados.

MOV AX, 3    ; Store 3 in register AX
MOV BX, 2    ; Store 2 in register BX
SUB AX, BX   ; Subtract BX from AX
JC  Label    ; If the previous operation overflowed, continue processing at memory location "Label"

Cada um dos acima tem uma representação binária; por exemplo, o código para SUBé 2Dhexadecimal ou 00101101em binário.

Etapa 2. Opcodes para ALU

Opcodes aritméticas como ADD, SUB, MUL, e DIVrealizar operações matemáticas inteiro básico usando uma ALU ou Arithmetic Logic Unit construído na CPU. Os números são armazenados nos registros por alguns códigos de operação; outros opcodes instruem o chip a ligar para a ALU para fazer contas com o que estiver armazenado nos registros da época.

Nota: Neste ponto, estamos muito além de qualquer coisa com a qual qualquer engenheiro de software se preocupe se estiver trabalhando com um 3GL como C.

Etapa 3. A ALU, meio-somador e somador completo

Você sabia que todas as operações matemáticas que você conhece podem ser reduzidas a uma série de operações NOR ? E é exatamente assim que a ALU funciona.

A ALU sabe apenas trabalhar com números binários e só pode executar operações lógicas como OR, NOT, AND e XOR. A implementação da adição e subtração binárias é realizada com uma série de operações lógicas organizadas de uma certa maneira, em um subsistema conhecido como somador . Esses subsistemas são compostos de uma rede de "meio-somadores" que operam em dois bits e determinam sua soma de um bit e um sinalizador de transporte de um bit. Ao agrupá-las, a ALU pode executar operações em números com 8, 16, 32 etc. bits.

Semi-adicionador

E a subtração? Subtração é apenas outra forma de adição:

A - B = A + (-B)

A ALU calcula -Btomando o complemento de dois de B. Depois de convertido em negativo, o envio do valor ao somador resultará em uma operação de subtração.

Etapa 4: a etapa final: transistores no chip

As operações dos somadores são implementadas usando uma combinação de componentes elétricos que interagem para criar "portas lógicas", como as encontradas na lógica transitor-transistor ou TTL, ou no CMOS . Clique aqui para alguns exemplos para ver como eles são conectados.

Em um chip, é claro, esses "circuitos" são implementados em milhões de pequenos pedaços de material condutor e não condutor, mas o princípio é o mesmo que se fossem componentes de tamanho normal em uma tábua de pão. Assista a este vídeo que mostra todos os transistores em um microchip através da lente de um microscópio eletrônico.

Algumas notas adicionais:

  1. O código que você escreveu seria pré-computado pelo compilador e não executado em tempo de execução, porque é composto apenas por constantes.

  2. Alguns compiladores não compilam com o código da máquina, mas introduzem outra camada, como o bytecode Java ou a linguagem intermediária .NET. Mas, no final, tudo é executado via linguagem de máquina.

  3. Algumas operações matemáticas não são computadas; eles são pesquisados ​​em tabelas massivas em uma unidade aritmética de coprocessamento ou contêm uma combinação de pesquisa e computação ou interpolação. Um exemplo seria a função de calcular uma raiz quadrada . Cada uma das CPUs modernas de PC possui uma unidade de coprocessamento de ponto flutuante embutida em cada núcleo da CPU.

John Wu
fonte
3
FWIW, a referência ao TTL pode ser confusa, pois praticamente nenhum processador moderno usa sinalização TTL, a maioria usando FETs CMOS e tensões mais baixas em vez de BJTs de 5v.
Whatsisname
2
Definitivamente, o CMOS seria uma referência melhor que o TTL, como sugere o @whatsisname, porque não só é mais preciso o que acontece nos processadores modernos, como também é conceitualmente muito mais simples.
Jules
3
@JackAidley é o que esta parte significa: "Em outras palavras, 2 é subtraído de 3 em uma instrução, e a próxima instrução verifica se ela estourou".
precisa saber é o seguinte
1
Picuinhas: Suponho que CMPseria usado, não SUB- mas, novamente, que é mais ou menos um " SUBmeio após o resultado é ignorado e apenas os sinalizadores estão definidos"
Hagen von Eitzen
5
Suas definições de meio e de somador completo estão incorretas. Um meio adicionador pega duas entradas de 1 bit e retorna a soma e o valor. Um somador completo recebe uma entrada adicional de transporte, mas ainda é apenas um bit. Existem várias maneiras de criar um somador de N bits, sendo o mais simples um somador de transporte de ondulação, que é apenas uma cadeia de N somadores completos. Na prática, para Ns maiores, esse atraso é bastante ruim, portanto, projetos mais complexos são usados ​​em projetos modernos de CPU.
Voo