¿Cómo se ejecuta un programa a nivel de CPU?

14

Sé que esta es una pregunta muy común. Pero tengo un ángulo diferente en mi mente. Trataré de articularlo aquí.

Por lo que sé, cada instrucción que ejecuta una CPU está en lenguaje de máquina y todo lo que la CPU puede hacer es realizar algunas operaciones aritméticas gracias a ALU y a sus transistores (si vamos a nivel de hardware).

Sin embargo, esto es más fácil de escribir que comprenderlo. Entonces, si todo lo que hace la CPU es sumar, restar, etc., ¿cómo se ejecuta un programa, digamos un programa JAVA que dice print Hello World, con estas operaciones aritméticas?

Quiero decir, ¿cómo se convierte este programa en algo que es solo una adición para la CPU?

PD: Si esta pregunta no es aplicable a este sitio web, me disculpo.

-----La segunda parte-----

Bueno. Gracias a todos por responder tan rápido y con tanto entusiasmo. Pensé que era mejor modificar un poco mi pregunta que ir y comentar todas las respuestas y volver a hacerlas.

Asi que aqui esta.

Primero, todos han respondido específicamente al ejemplo de Hello World. Esto es mi culpa. Debería haber mantenido esto genérico. El ejemplo de Hello World pone en cuestión los dispositivos de salida y cómo su procesamiento no se limita solo a la CPU, que legítimamente aparece en sus respuestas.

También muchos de ustedes me hicieron notar que la CPU hace más que solo agregar. Estoy de acuerdo con eso. Simplemente no escribí eso y asumí todo el camino. Por lo que entiendo, este es el proceso:

  1. lea las instrucciones de la memoria (usando buses de datos y direcciones y cosas de contador de programas)

    1. almacenar datos en el registro dentro de la CPU
    2. Ahora ALU realiza operaciones aritméticas, por supuesto, después de decodificar la instrucción, o dar un salto si es una instrucción similar.
    3. Y luego comunicarse con otros recursos si es necesario, como con el dispositivo de salida, etc. Los procesos más allá de esto son triviales por ahora.

Entonces, en el paso 3, donde la CPU decodifica una instrucción y decide hacer una operación aritmética (aquí estamos asumiendo que no hay otra operación que hacer, como saltar la instrucción actual ... dado que las operaciones aritméticas se realizan principalmente ... así que nos atendremos a eso ) Aquí es donde termina mi visualización. Cómo una instrucción de mi programa es solo una operación aritmética para la CPU. Realiza esa operación aritmética y esa instrucción cumple su propósito.

Espero haberme aclarado esta vez.

PD: Supongo aquí que ALU simplemente no está restringido a la operación aritmética real que hacemos en nuestros programas, sino que ejecuta todas las instrucciones, que ahora están en forma binaria, al sumarlas o restarlas, etc. para obtener el resultado que están destinados. ceder. Si me equivoco aquí, las respuestas a continuación responden correctamente mi pregunta.

usuario2827893
fuente
Entiendo que el compilador convierte el programa en lenguaje máquina. Simplemente no puedo visualizar un programa como una operación aritmética. Sin embargo, si el programa en sí mismo trata de sumar dos números, entonces es comprensible, pero de lo contrario no ... :)
user2827893
1
Tal vez debería comenzar a mirar el conjunto de instrucciones real de las CPU, por ejemplo, muy simples como MC6502, Z80 ... luego ver que hay instrucciones de acceso a la memoria, instrucciones de procesamiento de datos, ramas ... Entonces podría adivinar cómo pueden ser combinado para implementar cualquier algoritmo.
TEMLIB
3
Una CPU definitivamente puede hacer más que sumar. Es crucial mencionar que una CPU puede hacer comparaciones y saltos.
Theodoros Chatzigiannakis
1
Parece que todavía se niega firmemente a ver IF (tomar una decisión) y MOVE (leer y almacenar datos), la programación es 99% IF y MOVE. La aritmética es insignificante. Su primer ejemplo (Hola mundo) no tiene aritmética en absoluto.
edc65
1
1. Creo que es más probable que obtenga buenas respuestas si hace una nueva pregunta con su nueva confusión, en lugar de editar esta pregunta para cambiar lo que está preguntando. Obtuviste buenas respuestas a tu pregunta original, y parece que tu pregunta original puede sostenerse por sí sola, entonces, ¿por qué no eliminar la edición y hacer una nueva pregunta? 2. Dicho esto, no puedo entender la nueva parte. ¿Cuál es exactamente su pregunta sobre la nueva parte? Cuando se dice "aquí es donde termina mi visualización", ¿Quieres decir que no entiende el paso 3, o no entiende el paso 3? Si lo haces, ¿qué no entiendes?
DW

Respuestas:

7

Puede intentar tomar un programa simple y compilarlo en código máquina nativo. (Java normalmente se compila en código JVM, pero Andrew Tennenbaum tiene un libro donde describe cómo diseñar una CPU que se ejecute de forma nativa, por lo que funcionará). En GCC, por ejemplo, le da el -Sinterruptor al compilador .

Esto le dirá que cualquier cosa complicada, como E / S, se implementa llamando al sistema operativo. Si bien puede descargar la fuente al kernel de Linux y hacer lo mismo, lo que sucede debajo del capó es: todo está manipulando el estado de la memoria de la computadora, por ejemplo, la lista de procesos en ejecución, o hablando con el hardware usando direcciones de memoria especiales que lo controlan o que usan instrucciones especiales de CPU como iny outen el x86 Sin embargo, en general, solo los programas especiales llamados controladores de dispositivo hablarán con un hardware en particular, y el sistema operativo enviará solicitudes para usar el hardware al controlador correcto.

Específicamente, si imprime "¡Hola, mundo!" su compilador lo convertirá en un conjunto de instrucciones que carga la cadena en una ubicación particular (por ejemplo, carga la dirección de la cadena en la memoria en el %rdiregistro) y llama a una función de biblioteca con la callinstrucción. Esta función de biblioteca puede encontrar la longitud de la cadena con un bucle, luego llamar a la llamada del sistemawrite()para escribir ese número de bytes de la cadena al descriptor de archivo número 1, que es la salida estándar. En ese punto, el sistema operativo busca qué es el archivo número 1 de ese proceso y decide qué significa escribir en él. Si las escrituras en la salida estándar se imprimen en su pantalla, habrá algún proceso como copiar los bytes a un búfer, que luego es leído por su programa de terminal, que le dice al sistema de ventanas qué letras colocar y en qué fuente. El sistema de ventanas decide exactamente cómo debería ser, y le dice al controlador de un dispositivo que coloque los píxeles en la pantalla, lo que hace cambiando la memoria de video.

Davislor
fuente
Gracias @Lorehead. Esta explicación se ve bien wrt Hola mundo ejemplo.
user2827893
5

Su CPU en sí misma es tonta, como descubrió. Pero hay un microcosmos de chips de hardware a su alrededor. Tiene una instrucción que le permite configurar una línea de la CPU a alto nivel que está conectada a otro chip. Ese chip de hardware monitorea la línea y dice: "Oye, si esta línea es alta, entonces hago algo con otras líneas".

Para facilitar esto, estas líneas se agrupan. Algunos se usan para direccionar dispositivos, algunos se usan para transferir datos para esas direcciones y otros son simplemente "Amigo, hay algo importante en las líneas de mi chip".

Al final, su CPU simplemente le dice a otro chip que modifique la señal al monitor para que se vea como "Hola Mundo".

Google el dibujo de una pantalla de 7 segmentos. Tiene cables, lo que hará que un segmento se ilumine si le aplicas voltaje. Si conecta ahora una línea de salida de su CPU con una línea de la pantalla de 7 segmentos, la pantalla se ilumina. No es la CPU la que hace que el LED se ilumine, solo aplica voltaje a las líneas, pero algunas otras cosas de hardware pueden hacer cosas ingeniosas debido a eso.

Si su CPU ahora establece todas las líneas para que la H sea alta, el segmento 7 mostrará H, aunque H no es un número del que una CPU sumaría o restaría.

Ahora, si todas las capas están de acuerdo con lo que es necesario para hacer que la pantalla de 7 segmentos H (establezca 5 líneas específicas en alto), el compilador de Java puede crear código para que muestre H. Esto, por supuesto, es bastante inconveniente, por lo que las capas comienzan abstraer. La capa más baja comenzará por: "Oye, hay como 26 letras, asignemos números a cada letra, ¿qué tal si le damos a la letra 'H' el número '72'? Entonces puedes decirme" Mostrar letra 72 ", en lugar de "Establecer la línea 309 alta, establecer la línea 310 alta, establecer la línea 498 alta, establecer la línea 549 alta, establecer la línea 3 alta". Y así cada capa comienza a extraer información, cómo lograr ciertos resultados, por lo que no necesita preocuparse por ellos.

Entonces, sí, se resume en un mapeo enorme de números o bits, la CPU realmente puede procesar, con los significados que todos en la cadena acordaron.

John Hammond
fuente
3

En la universidad como parte de un programa de CS, estudié un ejemplo extendido de lenguaje de transferencia de registros que define una CPU. Me inspiré para tomar una opinión diferente y escribir un simulador que acepte dicha notación como definición, y publiqué eso en Embedded Systems Programming (edición de marzo de 1989) como una forma de responder el mismo tipo de pregunta que usted hizo, permitiendo a las personas construir su comprensión intuitiva de tales cosas.

¡En clase, pasamos a destilar esa notación de transferencia de resistencia en puertas lógicas reales en los registros! Se escribe a sí mismo: mira todo lo que tiene el registro 'A' como destino, y codifica A = (caso1) o (caso2) ... y eso se expresa como una forma normalizada de suma de productos o producto de sumas.

Solo al final del curso supe que se trataba de una CPU real: el PDP-8 si recuerdo correctamente.

Hoy podría alimentar el diagrama de puerta en un chip de matriz lógica programable.

Esa es la esencia de esto: se establece un registro con el resultado de las compuertas AND y OR que conducen a otros registros. Uno de los valores a incluir es el valor del código de operación.

Así que imagine: A: = (código de operación == 17 y X + Y) | (código de operación == 18 y X + Z) | ...

Los cpus modernos son más complicados, con tuberías y buses, pero las subunidades individuales como una ALU única funcionan de esa manera.

JDługosz
fuente
2

Está considerando la CPU aquí, pero hay otro componente involucrado al ejecutar 'Hello World': ¡la pantalla!

Para la CPU, un valor en la memoria es solo un número representado como un número dado de bits (0 y 1).

Cómo se convierte en letras en la pantalla es otra historia: la pantalla también tiene memoria. Esta memoria (memoria gráfica) se asigna a 'píxeles' en la pantalla. Cada píxel está codificado con un valor: si se trata de una pantalla monocromática muy básica, el valor es solo intensidad, para las pantallas en color, el valor es una combinación de rojo, verde y azul (RGB) que puede codificarse de muchas maneras diferentes.

Entonces, cuando la CPU 'escribe' un valor dado en la memoria de la pantalla, los píxeles se iluminan. Para escribir letras, uno necesita iluminar muchos píxeles. Por lo general, una computadora tendrá un conjunto de caracteres (en realidad varios) definidos en su sistema operativo. (haciendo una abstracción de las 'fuentes' en sí mismas, que se asigna a una definición de cómo debería ser cada letra en la pantalla)

Entonces, a medida que se compila el código, incluye todo tipo de cosas que provienen de las bibliotecas del sistema operativo, incluidos estos conjuntos de fuentes / caracteres, etc., que permiten a la CPU saber qué escribir en qué parte de la memoria de gráficos. (Es bastante complejo, pero esa es la idea general: el compilador incluye mucho más código que el que está en el código de 'hello world' solo, a través de bibliotecas importadas)

Al final, ha habido muchas cosas sucediendo como sospechas, pero no tuviste que escribir todo ese código.

MrE
fuente
1

Aquí hay un enfoque formal para su pregunta desde el campo de la informática teórica.

Básicamente, podemos definir un mapeo entre el modelo de cálculo de una CPU y una máquina de turing. Existen pruebas teóricas de que el conjunto de todos los programas imaginables de máquinas de Turing (y, por lo tanto, todos los programas imaginables ejecutables en una CPU) es contable infinito. Esto significa que podemos identificar cada programa con un número natural único, incluido el programa que ampliaría los números naturales a las máquinas de trabajo .

Como ya sabe que casi todo lo que hacen las CPU son cálculos sobre números naturales en representación binaria, puede razonar que las CPU pueden llevar a cabo todos los programas imaginables.

Nota: Esto está demasiado simplificado, pero, en mi opinión, da una buena intuición.

Kevin Dreßler
fuente
1

Lo que puede ayudar es alejar su pensamiento de "hacer aritmética". Si realmente está tratando de cavar en lo que las computadoras están haciendo bajo el capó para imprimir "Hello World", es mejor pensar un nivel más bajo. El "estado" de la computadora puede describirse como un conjunto de bits, almacenados por interruptores de transistor que están encendidos o apagados (o condensadores que están cargados o no cargados). La computadora manipula esos bits de acuerdo con las reglas. Las formas en que la computadora puede manipular esos bits se escriben en la CPU en forma de transistores que hacen el trabajo de cambiar los bits de 0 a 1, o de 1 a 0.

Cuando una ALU "hace aritmética", lo que realmente significa es que cambió el estado de la computadora de una manera que es consistente con nuestras reglas de aritmética. Todo lo que hizo fue cambiar algunas partes. Es el significado detrás del software lo que explica por qué deberíamos considerarlo como sumas o restas. La CPU no "sabe" lo que está haciendo. Simplemente cambia de estado a estado, y eso es todo (al menos hasta que Skynet se haga cargo).

Cuando piensas de esa manera, las instrucciones más complicadas como una instrucción de "salto" no son diferentes. Todo lo que hace es cambiar algunos bits. En este caso, sucede que cambia los bits que sabemos que significan la ubicación de la próxima instrucción a ejecutar. La CPU no "sabe" esto, pero nosotros sí. Entonces usamos la instrucción que cambia esos bits para "saltar" de un lugar a otro en nuestro código.

IO tampoco es realmente diferente, solo está cambiando bits. La única diferencia menor es que esos bits están conectados a transistores que eventualmente conducen a iluminar los caracteres en su pantalla. Si recuerdo algunas décadas atrás, cuando "Hello World" era realmente simple, había un espacio de memoria en el que, si escribía bits correspondientes a los caracteres ASCII para "Hello World", esos caracteres se representarían directamente en el pantalla. Hoy en día es un poco más complicado, porque tenemos tarjetas gráficas y sistemas operativos que lo molestan, pero la idea básica es la misma. Tiene un conjunto de transistores que están activados o desactivados, que están vinculados a los circuitos para mostrar un píxel en la pantalla. Establecemos los correctos, y parece que "Hello World" aparece en la pantalla.

La confusión es simplemente una cuestión de sintaxis vs semántica. El comportamiento de un "medio agregado" o un "completo agregado" en una ALU es la sintaxis. Define qué bits saldrán cuando los inserte. La semántica de los mismos es el concepto de la capacidad de hacer sumas. Usted y yo somos conscientes de que la ALU puede "sumar", pero para comprender realmente lo que sucede debajo, debe recordar que una ALU solo manipula los bits y bytes de la sintaxis.

Cort Ammon - Restablece a Monica
fuente
0

Las CPU funcionan así:

  • buscar la instrucción actual, incrementar el puntero de "instrucción actual".

  • descifrarlo (por ejemplo, averiguar qué es lo que esta instrucción le dice a la CPU que haga)

  • ejecútelo (haga lo que dice la instrucción): el puntero de instrucción actual puede modificarse si la instrucción es algo así como un "salto".

  • Repetir para siempre

Las CPU modernas son más complejas e intentan superponerse en gran medida e incluso predecir partes de ese proceso (por ejemplo, comenzar a ejecutar mientras otras 10 instrucciones están decodificando mientras la CPU está yendo muy por delante del puntero de "instrucción actual" para mantener las "tuberías" llenas), pero El proceso esencial es realmente el mismo.

Hay muchos tipos de instrucciones, un ejemplo de la mayoría de ellas es:

  • Instrucciones de "mover". Estos pueden copiar X a otra X, donde X es memoria (RAM), un registro o una dirección en el espacio de E / S si la CPU admite tal noción.

  • Instrucciones de manipulación de la pila, incluyendo pop en el registro, registro de inserción en la pila, etc. Estos son un caso especial de instrucciones de "movimiento" que usan y actualizan un registro de "puntero de pila".

  • Instrucciones que realizan operaciones matemáticas, ya sea entre dos registros o memoria y un registro. Estas instrucciones afectan automáticamente a un registro de banderas. Uno de estos indicadores es el indicador "cero" que se establece si el resultado es cero, otro es el indicador "negativo" que se establece si se establece el bit más significativo del resultado. Puede haber otros dependiendo de la CPU.

  • Un caso especial de operaciones matemáticas son las instrucciones de comparación, que es lo mismo que una resta, pero el resultado no se mantiene. Las banderas aún están afectadas.

  • Hay instrucciones de bifurcación que saltan a una dirección de memoria SI se establecen indicadores específicos. ¿Recuerdas la bandera de "cero" mencionada anteriormente? También funciona como el indicador "si es igual", por lo que verá instrucciones como BEQen muchas CPU que realmente se ramifican si se establece el indicador "cero".

  • Instrucciones que realizan operaciones lógicas (AND, OR, NOT), bits de desplazamiento y bits de prueba. Pueden afectar banderas como las instrucciones matemáticas dependiendo de la CPU.

  • Instrucciones que saltan incondicionalmente.

  • Instrucciones que saltan y guardan la dirección de retorno en la pila (una "llamada"), y otras instrucciones que extraen una dirección de la pila (una "devolución").

  • Instrucciones especiales como las que detienen la CPU, identifican la CPU o llaman a los manejadores de interrupciones.

  • "Sin operación": casi todas las CPU tienen una instrucción "sin operación" que solo consume ciclos y continúa.

Esto es realmente solo un ejemplo, hay CPU con menos tipos de instrucciones y CPU con más.

El punto es ilustrar que hay muchos tipos de instrucciones además de las instrucciones matemáticas en una CPU. Todo en un lenguaje de nivel superior se desglosa en los tipos de operaciones anteriores y solo algunas de ellas serán matemáticas o instrucciones de tipo ALU.

LawrenceC
fuente