¿Cómo diferenciaría la ALU en un microprocesador entre un número con signo, -7 que se denota con 1111 y un número sin signo 15, también con 1111?
¿Cómo diferenciaría la ALU en un microprocesador entre un número con signo, -7 que se denota con 1111 y un número sin signo 15, también con 1111?
Respuestas:
La respuesta corta y simple es: no lo hace. Ninguna CPU mainstream moderna ISA funciona de la manera que piensas.
Para la CPU, es solo un patrón de bits. Depende de usted, el programador, hacer un seguimiento de lo que significa ese patrón de bits.
En general, los ISA no distinguen entre diferentes tipos de datos, cuando se trata de almacenamiento. (Ignorando los registros de propósito especial, como los registros flotantes en una FPU). Es solo un patrón de bits sin sentido para la CPU. Sin embargo, las NIA hacer tienen diferentes tipos de instrucciones que pueden interpretar el patrón de bits de diferentes maneras. Por ejemplo, instrucciones aritméticas tales como MUL
, DIV
, ADD
, SUB
interpretan el patrón de bits como una especie de número, mientras que las instrucciones lógicas, tales como AND
, OR
, XOR
interpretarlo como una matriz de booleanos. Por lo tanto, depende del programador (o el autor del intérprete o compilador si usa un lenguaje de nivel superior) elegir las instrucciones correctas.
Es muy posible que haya instrucciones separadas para números con y sin signo, por ejemplo. Algunos ISA también tienen instrucciones para la aritmética con decimales codificados en binario.
Sin embargo, tenga en cuenta que escribí "ISA mainstream moderna" arriba. De hecho, existen ISA no convencionales o históricas que funcionan de manera diferente. Por ejemplo, tanto el CISC ISA original de 48 bits del IBM AS / 400 como el RISC ISA actual de 64 bits basado en POWER del sistema ahora llamado IBM i, distinguen entre punteros y otros valores. Los punteros siempre están etiquetados e incluyen información de tipo y gestión de derechos. La CPU sabe si un valor es un puntero o no, y solo el núcleo privilegiado de i / OS puede manipular los punteros libremente. Las aplicaciones de usuario solo pueden manipular los punteros que poseen para apuntar a la memoria que poseen utilizando una pequeña cantidad de instrucciones seguras.
También hubo algunos diseños históricos de ISA que incluían al menos alguna forma limitada de reconocimiento de tipos.
char
, que es un tipo sin signo de 16 bits. Por supuesto, todavía no hay instrucciones aritméticas sin signo en el código de bytes de Java, ya que cualquier char
valor se promueve automáticamente int
(con signo de 32 bits) para aritmética.
Versión corta: no lo sabe. No hay forma de saberlo.
Si 1111
representa -7, entonces tiene una representación de magnitud de signo , donde el primer bit es el signo y el resto de los bits son la magnitud. En este caso, la aritmética es algo complicada, ya que un complemento sin signo y un complemento con signo utilizan una lógica diferente. Por lo tanto, probablemente tenga un SADD
y un UADD
código de operación, y si elige el incorrecto, obtendrá resultados sin sentido.
Sin embargo, más a menudo 1111
representa -1, en lo que se llama una representación de complemento a dos . En este caso, a la ALU simplemente no le importa si los números están firmados o no. Por ejemplo, tomemos la operación de 1110 + 0001
. En aritmética con signo, esto significa "-2 + 1", y el resultado debería ser -1 ( 1111
). En aritmética sin signo, esto significa "14 + 1", y el resultado debe ser 15 ( 1111
). Por lo tanto, la ALU no sabe si desea un resultado firmado o sin firmar, y no le importa. Simplemente hace la adición como si no estuviera firmada, y si desea tratar eso como un entero firmado después, eso depende de usted.
EDITAR: Como Ruslan y Daniel Schepler señalan con razón en los comentarios, algunos operandos todavía necesitan versiones separadas firmadas y sin firmar, incluso en una máquina con dos complementos. La suma, la resta, la multiplicación, la igualdad y todo eso funciona bien sin saber si los números están firmados o no. Pero la división y cualquier comparación mayor que / menor que deben tener versiones separadas.
EDITAR EDITAR: También hay algunas otras representaciones, como el complemento de uno , pero básicamente ya no se usan más, por lo que no debería preocuparse por ellas.
<
<=
>=
>
son diferentes para operandos con ==
y sin signo, y !=
son independientes de la firma.
Una de las grandes ventajas de las matemáticas de complemento a dos, que utilizan todas las arquitecturas modernas, es que las instrucciones de suma y resta son exactamente las mismas para los operandos con signo y sin signo.
Muchas CPU ni siquiera tienen instrucciones de multiplicación, división o módulo. Si lo hacen, deben tener formas separadas y firmadas de la instrucción, y el compilador (o el programador en lenguaje ensamblador) elige la apropiada.
Las CPU también generalmente tienen diferentes instrucciones para las comparaciones con o sin firma. Por ejemplo, x86 podría seguir a CMP
con JL
(Saltar si es menor que) si la comparación debe estar firmada, o JB
(Saltar si está debajo) si la comparación debe estar sin firmar. Nuevamente, el compilador o el programador elegirían la instrucción correcta para el tipo de datos.
Algunas otras instrucciones a menudo vienen en variantes con signo y sin signo, como desplazamiento a la derecha o cargar un valor en un registro más amplio, con o sin extensión de signo.
smulh
y umulh
que devuelve solo los bits superiores de la multiplicación y las instrucciones con y sin signo que devuelve el resultado en un registro dos veces más ancho que los operandos de origen.
No lo hace. El procesador se basa en el conjunto de instrucciones para decirle qué tipo de datos está mirando y dónde enviarlos. No hay nada acerca de 1s y 0s en el operando en sí mismo que pueda indicar de forma inherente a la ALU si los datos son char, float, int, firmado int, etc. Si ese 1111 va a un circuito eléctrico que espera un complemento de 2s, va para ser interpretado como un complemento 2s.
char
a nivel de hardware. Quizás alguna vez, en los días de las teleimpresoras mecánicas. Pero hoy, a char
es solo un número en lo que respecta al hardware. La razón por la que diferentes números corresponden a diferentes formas de letras en su pantalla es que esos números se utilizan para seleccionar diferentes mapas de bits o diferentes rutinas de dibujo de una tabla grande (es decir, de una "fuente").
Me gustaría agregar una adición a las respuestas ya hechas:
En la mayoría de las otras respuestas, se observa que en la aritmética de dos complementos, el resultado es el mismo para números con signo y sin signo:
-2 + 1 = -1 1110 + 0001 = 1111
14 + 1 = 15 1110 + 0001 = 1111
Sin embargo , hay excepciones:
Division:
-2 / 2 = -1 1110 / 0010 = 1111
14 / 2 = 7 1110 / 0010 = 0111
Comparison:
-2 < 2 = TRUE 1110 < 0010 = TRUE
14 < 2 = FALSE 1110 < 0010 = FALSE
"Typical" (*) multiplication:
-2 * 2 = -4 1110 * 0010 = 11111100
14 * 2 = 28 1110 * 0010 = 00011100
(*) En muchas CPU, el resultado de una multiplicación de dos números de n bits es (2 * n) bits de ancho.
Para tales operaciones, las CPU tienen diferentes instrucciones para aritmética con y sin signo.
Esto significa que el programador (o el compilador) debe usar otras instrucciones para aritmética con y sin signo.
La CPU x86, por ejemplo, tiene una instrucción llamada div
para hacer una división sin signo y una instrucción llamada idiv
para hacer una división con signo.
También hay diferentes instrucciones "condicionales" (saltos condicionales, set-bit-on-condition), así como instrucciones de multiplicación para aritmética con y sin signo.