¿Cómo determina una computadora el tipo de datos de un byte?

31

Por ejemplo, si la computadora ha 10111100almacenado en un byte particular de RAM, ¿cómo sabe la computadora interpretar este byte como un entero, un carácter ASCII u otra cosa? ¿Los datos de tipo se almacenan en un byte adyacente? (No creo que este sea el caso, ya que resultaría en usar el doble de espacio para un byte).

Sospecho que tal vez una computadora ni siquiera sabe el tipo de datos, que solo el programa que lo usa sabe. Supongo que debido a que la RAM es R AM y, por lo tanto, no se lee secuencialmente, un programa en particular solo le dice a la CPU que busque la información de una dirección específica y el programa define cómo tratarla. Esto parece encajar con cosas de programación, como la necesidad de conversión de texto.

¿Estoy en el camino correcto?

Bajista
fuente
44
Como nota al margen: si está hablando de tipos, debe hacerlo en un contexto de idioma. Le corresponde al compilador manejar ese tipo de cosas (símbolos, tipos de verificación, operaciones, conversión, ram de direcciones, etc.). CPU y RAM solo conocen bytes
jean
44
El tipo de datos de un byte es un byte. Más allá de eso, la computadora no sabe nada. Un programa puede interpretar un byte o un grupo de bytes como un tipo de datos en particular e intentar realizar operaciones en esos, pero no hay restricciones allí. El mismo grupo de bytes podría interpretarse como más de un tipo de datos (es decir, convertir punteros a tipos de valores, uniones tipo C, etc.). Que la RAM no se lea secuencialmente no es realmente relevante. - Es más porque la RAM es de uso general. - Los registros, por ejemplo, tampoco se leen secuencialmente, pero se escriben a máquina.
BrainSlugs83
55
Un enchufe descarado para mí, pero esta pregunta se hizo básicamente en los SE de los programadores hace aproximadamente un mes. Aquí está mi respuesta . Es un poco largo en este punto, pero lo ataca desde varios ángulos diferentes.
Shaz
2
Una consecuencia útil del hecho de que el hardware es independiente del tipo de datos es que un solo byte (o palabra, etc.) puede ser interpretado de múltiples maneras por un programa. En particular, la interpretación temporal de un número de coma flotante como un entero se utiliza para calcular la raíz cuadrada inversa rápida .
Aoeuid
@ BrainSlugs83, ¿podría considerar convertir eso en una respuesta?
DW

Respuestas:

38

Tu sospecha es correcta. La CPU no se preocupa por la semántica de sus datos. A veces, sin embargo, hace la diferencia. Por ejemplo, algunas operaciones aritméticas producen resultados diferentes cuando los argumentos están semánticamente firmados o sin firmar. En ese caso, debe decirle a la CPU qué interpretación pretendía.

Depende del programador dar sentido a sus datos. La CPU solo obedece las órdenes, felizmente inconsciente de su significado u objetivos.

Yuval Filmus
fuente
1
En cuanto a "cuando los argumentos están semánticamente firmados o sin firmar", ¿cómo lo sabría la CPU? Las operaciones de la CPU solo ven los bytes de parámetros y carecen de ese tipo de conocimiento del contexto del tipo de datos. Usted implica el tipo de datos eligiendo la operación de CPU adecuada (o su compilador lo hace).
Shiv
44
@Shiv En tales casos, la CPU recibe una instrucción diferente para procesar números con signo y números sin signo. Como en las sospechas del OP, el programa está obligado a proporcionar esos detalles, porque la CPU no lo sabe.
Cort Ammon - Restablece a Mónica el
2
He estado trabajando con computadoras todo el tiempo que me recuerdo, y aunque sé que a la CPU no le importan las construcciones de alto nivel que usamos en la programación de alto nivel, pero esta separación de conceptos todavía me asusta de vez en cuando.
Loupax
1
@Loupax Bueno, trabajar con un ensamblaje de muy bajo nivel ayuda bastante, incluso mov al, 42es un poco de alto nivel, es obvio que solo hay una posible instrucción que esto podría llamar, pero todavía está algo abstraído. Sin embargo, el uso mov.8 al, 42explícito hace que esto sea dolorosamente obvio :)
Luaan
1
@ Shiv: Me gustaría señalar que hay máquinas donde se escriben los datos en la memoria. Estas se denominan arquitecturas de memoria etiquetadas (o simplemente arquitecturas etiquetadas), pero no han tenido tanto éxito comercial como las arquitecturas normales, en parte porque ahora programamos principalmente en lenguajes compilados en lugar de ensamblar y el compilador se encarga de escribir. Ver: en.wikipedia.org/wiki/Tagged_architecture
slebetman
14

Como otros ya han respondido, las CPU comunes de hoy no saben qué contiene una posición de memoria determinada; El software decide.

Sin embargo, hay otras posibilidades. Lisp Machines, por ejemplo, utilizó una arquitectura etiquetada que almacenaba el tipo de cada posición de memoria; de esa manera, el hardware en sí podría hacer parte del trabajo de los lenguajes de alto nivel.

E incluso ahora, supongo que podría considerar el bit NX en Intel, AMD, ARM y otras arquitecturas para seguir el mismo principio: distinguir a nivel de hardware si una zona de memoria dada contiene datos o instrucciones.

Además, solo para completar, en las arquitecturas de Harvard (como algunos microcontroladores) los datos y las instrucciones están físicamente separados, por lo que la CPU tiene una idea de lo que está leyendo.

En esta pregunta de Quora hay algunos comentarios sobre cómo funciona la memoria etiquetada, sus implicaciones de rendimiento y desaparición, y más.

hmijail
fuente
La arquitectura etiquetada es una nota interesante. ¿Sería significativamente más rápido?
Bassinator
4

Sí. El programa solo obtiene un byte de la memoria y puede interpretarlo como quiera.

David Richerby
fuente
3

No hay anotaciones de tipo.
RAM almacena datos puros, y luego el programa define qué hacer.

Con los registros de la CPU es un poco más difícil, si tiene registros de un tipo dado (como FPU), usted dice lo que hay dentro.
Las operaciones en registros de coma flotante utilizan explícitamente datos escritos. Usted o su compilador dicen qué y cuándo deben colocarse allí, para que no tengan tanta libertad.
La computadora no hace suposiciones sobre los datos subyacentes en la RAM, y en los registros con una excepción: los registros escritos en la CPU son de tipo conocido, optimizados para manejarlos. Esto es solo para mostrar que hay lugares donde los datos deben ser del tipo esperado, pero nada le impide lanzar cadenas a flotantes y multiplicarlos.

En los lenguajes de programación, se especifica el tipo, o en los idiomas de nivel superior, los datos son generales y el compilador / intérprete / VM codifica lo que hay dentro con sobrecarga.
Por ejemplo, en C, su tipo de puntero le dice qué hacer con los datos, cómo acceder a ellos.

Por supuesto, puede leer cadenas (caracteres) y tratarlas como valores de punto flotante, enteros y mezclarlos.

Mal
fuente
Incluso los bits en un registro FPU no siempre representan valores de coma flotante. En los viejos tiempos (¿quizás ya no tanto?), Una optimización común era usar registros de coma flotante (64 bits o más) para copiar datos más rápido que los registros de propósito general / enteros (32 bits), siendo el doble de grande, generalmente podían copiar datos el doble de rápido.
Seth
1
Estoy totalmente de acuerdo contigo, es por eso que escribí que alguien podría empujar las cadenas allí. Y al mismo tiempo, la gente hacía operaciones de coma flotante en enteros, porque era más rápido. ¡Ese es el punto!
Mal
@HCBPshenanigans hay instrucciones que manipulan valores de punto flotante. Si se usa FADD, solo tiene sentido que los grupos de memoria (4,8 o 10) bytes contengan números de punto flotante. Eso es cierto para varios tipos de instrucción: multiplicar dos enteros solo tiene sentido si son enteros, saltar solo tiene sentido si es una dirección.
JDługosz
@seth y evilJS no se supone que sea el caso de las instrucciones 8087 apiladas de coma flotante heredadas, pero es el caso de los registros CIMD más nuevos que se pueden usar solo para cargar / guardar sin interpretación (aunque deben estar alineados), y una advertencia que si los registros CIMD nunca se usaron, entonces no necesitan guardarse en un cambio de contexto. Si (solo) mueve 8 bytes a través del registro XMM, es una pérdida neta ya que todo el conjunto debe guardarse.
JDługosz
3

A la CPU no le importa, ejecuta el código de ensamblaje, que simplemente mueve los datos, los cambia, los agrega o los multiplica ...

Los tipos de datos son un concepto de lenguaje de nivel superior: en C o C ++ debe especificar los tipos para cada pieza de datos que manipula; el compilador C / C ++ se encarga de transformar estos datos en los comandos correctos para que los procese la CPU (los compiladores escriben el código de ensamblaje)

En algunos lenguajes de nivel aún más alto, se pueden inferir Tipos: en Python o Javascript, por ejemplo, uno no tiene que especificar tipos de datos, sin embargo, los datos tienen un tipo y no puede agregar una cadena con un entero, pero puede agregar un flotante con un número entero: el 'compilador' (que en el caso de Javascript es un compilador JIT (Just in Time). A menudo se llama a JavaScript un lenguaje 'interpretado' porque históricamente los navegadores interpretaban el código Javascript, pero hoy en día los motores Javascript son compiladores.

El código siempre se compila en código de máquina, pero obviamente el formato del código de máquina depende de la máquina a la que se dirige (el código x86 de 64 bits no funcionará en una máquina x86 de 32 bits o un procesador ARM, por ejemplo)

Entonces, en realidad, hay muchas capas involucradas en la ejecución de código interpretado.

Java y C # son otros interesantes, ya que el código Java o C # está técnicamente 'compilado' en un binario Java (código de bytes), pero ese código en sí es interpretado por Java Runtime, que es específico del hardware subyacente (uno necesita instalar JRE dirigido a la máquina correcta para ejecutar binarios Java (Jars)

MrE
fuente
Un compilador compila, ya sea JIT o no; y un intérprete interpreta sin compilar (¡porque si no sería un compilador!). Son cosas muy diferentes. Y con respecto a que "Java es divertido" debido a la interpretación de bytecode, considere que incluso el código de máquina x86 será interpretado (¿o incluso compilado?) Por el microprocesador en microcódigo .
hmijail
Gracias por la aclaración ... De acuerdo: un compilador compila y un intérprete interpreta. En el caso de Javascript, aunque la historia es un poco complicada, ya que algunos navegadores más antiguos interpretan el código, mientras que los navegadores más modernos realmente compilan justo a tiempo, lo que probablemente es la razón por la que todavía se conoce como un lenguaje 'interpretado' a pesar de técnicamente ya no lo es.
MrE
Pero AFAIK, JS comienza a interpretarse y luego puede compilarse según sea necesario. Y los JIT pueden cambiar de interpretado a compilado a interpretado nuevamente, dependiendo de muchas cosas. Por ejemplo, un fragmento de código puede compilarse para una variable que tiene un tipo dado; pero luego el código se ejecuta nuevamente con esa variable que tiene un tipo diferente, por lo que el código compilado existente no se puede usar para que el intérprete intervenga, hasta que el código se compile nuevamente para el nuevo tipo ...
hmijail
Me estás citando algo que no dije, quítalo porque está totalmente mal. Microcode no tiene nada que ver con el sistema operativo; Es algo interno al microprocesador. 32 bits o 64 bits tampoco tiene nada que ver con eso.
hmijail
3

Los tipos de datos no son una característica de hardware. La CPU conoce un par (bueno, mucho) de comandos diferentes. Esos se llaman el conjunto de instrucciones de una CPU.

Uno de los más conocidos es el conjunto de instrucciones x86 . Si busca "multiplicar" en esta página, obtendrá 50 resultados. MULPDy MULSDpara la multiplicación de dobles, FIMULpara la multiplicación de enteros, ...

Esos comandos funcionan en registros. Los registros son ranuras de memoria que pueden contener un número fijo de bits (a menudo 32 o 64, dependiendo de la arquitectura que utilice su CPU), sin importar lo que representen estos bits. Por lo tanto, la instrucción de la CPU interpreta los valores de los registros de una manera diferente, pero los valores en sí mismos no tienen tipos.

Stuart Williams dio un ejemplo en PyCon 2017 :

ingrese la descripción de la imagen aquí

Martin Thoma
fuente
1
Tenga en cuenta que esto no es estrictamente cierto: hay registros de propósito especial que no pueden contener valores arbitrarios (por ejemplo, registros de puntero que no son solo cualquier dirección y no permiten adiciones arbitrarias o registros de punto flotante donde puede t almacenar valores no normalizados). Pero su respuesta es correcta para registros de propósito general en la mayoría de las arquitecturas.
Gilles 'SO- deja de ser malvado'
2

... que un programa en particular solo le dice a la CPU que busque la información de una dirección específica y el programa define cómo tratarla.

Exactamente. Pero la RAM no se lee "secuencialmente" y significa Memoria de acceso aleatorio, que es exactamente lo contrario.

Además de saber lo que un byte es , que ni siquiera sabe si es un byte , o un fragmento de un artículo más grande como un número de coma flotante.

Me gustaría agregar a otras respuestas dando algunos ejemplos específicos.

Considere 01000001. El programa podría copiarlo de un lugar a otro como parte de un gran paquete de datos sin tener en cuenta su significado. Pero copiar eso a la dirección utilizada por el búfer de video en modo texto hará que la letra se Amuestre en alguna posición en la pantalla. La misma acción exacta cuando la tarjeta está en un modo de gráficos CGA mostrará un píxel rojo y un píxel azul.

En un registro, podría ser el número 65 como un entero. Hacer aritmética para establecer el bit de 32 podría significar cualquier cosa sin contexto, pero podría específicamente cambiar una letra a minúscula.

La CPU 8086 (todavía) tiene instrucciones especiales llamadas DAA que se usan cuando el registro contiene 2 dígitos decimales, por lo que si acaba de usar esa instrucción la está interpretando como dos dígitos 41.

Los programas se bloquean porque se lee una palabra de memoria pensando que es un puntero cuando se almacena algo allí.

Usando un depurador, inspeccionando la memoria, se usa un mapa para guiar la interpretación para su visualización. Sin esta información de símbolo, un depurador de bajo nivel le permite especificar: mostrar esta dirección como palabras de 16 bits, mostrar esta dirección como punto flotante largo, como cadenas ... lo que sea. Observar un volcado de paquetes de red o un formato de archivo desconocido, resolverlo es un desafío.

Esa es una fuente importante de poder y flexibilidad en la arquitectura moderna de la computadora: una celda de memoria puede significar cualquier cosa , datos o instrucción, implícita solo en lo que "significa" para el programa por lo que hace con el valor y cómo afecta las operaciones posteriores. el significado es más profundo que el ancho entero: ¿son estos caracteres ... caracteres en ascii o ebcdic? ¿Formando palabras en inglés o códigos de producto SQU? ¿La dirección para enviar o la dirección de devolución? La interpretación más bajo nivel (bits lógicos; número entero similar, con o sin signo; flotador; BCD; puntero) es contextual a nivel de instrucción-set, pero se ve que es todo el contexto en algún nivel: el dela dirección es lo que es debido a la ubicación que está impresa en el sobre. Es contextual a las reglas del cartero, no de la CPU. El contexto es un gran continuo, con bits en un extremo.


※ Nota al pie: La instrucción DAA está codificada como un byte 00100111. De modo que ese byte es la instrucción mencionada anteriormente si se lee en el flujo de instrucciones, y los dígitos 27si se interpretan como dígitos bcd, y 0x27 = 39 como un entero, que es el número 9 en ASCII, y parte de la tabla de interrupción (mitad de INT 13 Dirección de 2 bytes, utilizada para las rutinas de servicio del BIOS).

JDługosz
fuente
1

La única forma en que la computadora sabe que una ubicación de memoria es una instrucción es que un registro de propósito especial llamado puntero de instrucción los señala en un punto u otro. Si el puntero de instrucción apunta a una palabra de memoria, se carga como una instrucción. Aparte de eso, la computadora no tiene forma de saber la diferencia entre los programas y otros tipos de datos.

Dummy Dum
fuente