¿Cómo funciona internamente la comparación de enteros?

18

Por ejemplo, al comparar dos enteros de la siguiente manera en un lenguaje tipo C:

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

¿Cómo se determina internamente si 3 es mayor que 2 (verdadero) o no (falso)?

Niek
fuente
19
La respuesta actual está bien para el caso en que la comparación es sobre expresión variable, pero carece de la exención de responsabilidad de que muchos compiladores modernos verán su fragmento de código, detectarán que la expresión siempre será verdadera (debido a los literales) e ignorarán por ifcompleto , yendo directamente a la codificación do something.
SJuan76
3
Posible duplicado de ¿Cómo funcionan las computadoras?
3
@Snowman, no estoy de acuerdo. Cualquier consulta de programación de "cómo funciona esto" puede resumirse en esa pregunta, pero eso no los convierte en duplicados.
user1643723
1
@ user1643723 Lo hace cuando la función en cuestión es un código de operación específico.
chrylis -on strike-
1
@ user1643723 La pregunta es acerca de cómo una computadora realiza una operación básica, y la respuesta principal discute las puertas lógicas y las tablas lógicas. Dos temas que se tratan ampliamente en la respuesta principal del objetivo engañado, que también responde a su pregunta.

Respuestas:

61

Todo el camino por la madriguera del conejo, ¿eh? OK, lo intentaré.

Paso 1. De C al lenguaje máquina

El compilador de C transforma su comparación con los códigos de operación almacenados en lenguaje máquina . El lenguaje de máquina es una serie de números que la CPU interpreta como instrucciones. En este caso, habría dos códigos de operación: "restar con acarreo" y "saltar si se lleva". En otras palabras, 2 se resta de 3 en una instrucción, y la siguiente instrucción verifica si se desbordó. Estarían precedidos por dos instrucciones para cargar los números 2 y 3 en ubicaciones donde se puedan comparar.

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 uno de los anteriores tiene una representación binaria; por ejemplo, el código para SUBes 2Dhexadecimal o 00101101en binario.

Paso 2. Códigos de operación para ALU

Códigos de operación aritmética como ADD, SUB, MUL, y DIVrealizar operaciones matemáticas básicas número entero usando una ALU o unidad aritmética lógica integrada en la CPU. Los números se almacenan en registros por algunos códigos de operación; otros códigos de operación le indican al chip que llame a la ALU para hacer cálculos matemáticos sobre lo que esté almacenado en los registros en ese momento.

Nota: En este punto, estamos mucho más allá de lo que cualquier ingeniero de software se preocuparía si trabajara con un 3GL como C.

Paso 3. La ALU, medio sumador y sumador completo

¿Sabía que todas las operaciones matemáticas que conoce pueden reducirse a una serie de operaciones NOR ? Y así es exactamente como funciona la ALU.

La ALU solo sabe cómo trabajar con números binarios y solo puede realizar operaciones lógicas como OR, NOT, AND y XOR. La implementación de la suma y resta binarias se logra con una serie de operaciones lógicas dispuestas de cierta manera, en un subsistema conocido como sumador . Estos subsistemas están compuestos por una red de "medios sumadores" que operan en dos bits y determinan su suma de un solo bit y un indicador de acarreo de un solo bit. Al encadenarlos, la ALU puede realizar operaciones en números con 8, 16, 32, etc. bits.

Half-Adder

¿Qué pasa con la resta? La resta es solo otra forma de suma:

A - B = A + (-B)

La ALU calcula -Btomando el complemento de dos de B. Una vez que se convierte en negativo, enviar el valor al sumador dará como resultado una operación de resta.

Paso 4: El paso final: transistores en chip

Las operaciones de los sumadores se implementan utilizando una combinación de componentes eléctricos que interactúan para crear "puertas lógicas", como las que se encuentran en la lógica transitor-transistor o TTL, o en CMOS . Haga clic aquí para ver algunos ejemplos para ver cómo están conectados.

En un chip, por supuesto, estos "circuitos" se implementan en millones de pequeños trozos de material conductor y no conductor, pero el principio es el mismo que si fueran componentes de tamaño completo en una placa de pruebas. Mire este video que le muestra todos los transistores en un microchip a través de la lente de un microscopio electrónico.

Algunas notas adicionales:

  1. En realidad, el compilador precalculó el código que escribió y no se ejecutó en tiempo de ejecución, ya que está compuesto únicamente por constantes.

  2. Algunos compiladores no compilan el código de la máquina, pero introducen otra capa, como el bytecode de Java o el lenguaje intermedio .NET. Pero al final todo se ejecuta a través del lenguaje de máquina.

  3. Algunas operaciones matemáticas no se calculan realmente; se buscan en tablas masivas en una unidad de coprocesamiento aritmético, o contienen una combinación de búsqueda y cálculo o interpolación. Un ejemplo sería la función para calcular una raíz cuadrada . Las CPU de PC modernas tienen una unidad de coprocesamiento de punto flotante integrada en cada núcleo de CPU.

John Wu
fuente
3
FWIW, hacer referencia a TTL puede ser confuso ya que prácticamente ningún procesador moderno usa señalización TTL, la mayoría usa FET CMOS y voltajes más bajos en lugar de BJT de 5v.
whatsisname
2
CMOS definitivamente sería una mejor referencia que TTL, como sugiere @whatsisname, porque no solo es más preciso a lo que sucede en los procesadores modernos, sino que también es conceptualmente mucho más simple.
Jules
3
@JackAidley, eso es lo que significa esta parte: "En otras palabras, 2 se resta de 3 en una instrucción, y la siguiente instrucción verifica si se desbordó".
KutuluMike
1
Nitpicking: Supongo CMPque se usaría, no SUB, pero de nuevo eso es más o menos "donde SUBse ignora el resultado y solo se establecen las banderas"
Hagen von Eitzen
55
Sus definiciones de sumador medio y completo son incorrectas. Un medio sumador toma dos entradas de 1 bit y devuelve la suma y el acarreo. Un sumador completo toma una entrada de entrada adicional pero sigue siendo solo un bit. Hay muchas formas de crear un sumador de N bits, el más simple es un sumador de transferencia de ondas que es solo una cadena de N sumadores completos. En la práctica, para N más grandes, esto tiene un retraso bastante grave, por lo que se utilizan diseños más complejos en los diseños modernos de CPU.
Voo