assembly - ¿Cómo funcionan los lenguajes de ensamblaje?
hardware grammar (5)
Tengo mucha curiosidad sobre cómo funcionan los lenguajes de ensamblaje. Sigo siendo general porque no estoy hablando solo del ensamblaje de Intel x86 (aunque es el único con el que estoy familiarizado remotamente). Para ser un poco más claro ...
mov %eax,%ebx
¿Cómo sabe la computadora qué hace una instrucción como "mov"? ¿Cómo sabe que eax y ebx son registros? ¿Las personas escriben gramáticas para lenguajes ensambladores? ¿Cómo escriben esto? Me imagino que nada impide que alguien escriba un lenguaje ensamblador que sustituye la instrucción mov
por algo como dog
o horse
, etc. (obviamente esto no es semántico)
Lo siento si esto no está muy claro, pero es algo que encuentro un poco desconcertante, sé que no puede ser mágico, pero no puedo ver cómo funciona. He buscado algunas cosas en wikipedia, pero todo parece indicar que se traduce en código de máquina, bueno, lo que estoy preguntando es cómo se produce esa traducción, supongo.
¿Pensamientos?
EDITAR: me doy cuenta de que esto está definido en los manuales de referencia y en las cosas, supongo que lo que deseo saber es cómo le dices a tu procesador: "De acuerdo, cuando veas el mov
, harás esto". También sé que es una secuencia de probablemente una tonelada de puertas lógicas ... pero tiene que haber alguna forma de que el procesador reconozca que mov
es el símbolo que significa "usar estas puertas lógicas"
Las computadoras están básicamente construidas a partir de puertas lógicas . Aunque esta es una idealización abstracta de la maquinaria física real, está lo suficientemente cerca de la verdad que podemos creerlo por el momento. En un nivel muy básico, estas cosas funcionan igual que los predicados verdadero / falso. O si alguna vez has jugado minecraft, funciona mucho como redstone. El campo que estudia cómo armar puertas lógicas para hacer circuitos complejos e interesantes, como las computadoras, se llama arquitectura de computadora . Tradicionalmente se considera una mezcla de informática e ingeniería eléctrica.
Las puertas lógicas más básicas son cosas como AND y OR que simplemente juntan bits y destruyen alguna operación booleana entre ellos. Al crear bucles de retroalimentación en compuertas lógicas, puede almacenar memoria. Un tipo de circuito de memoria estándar se llama flip-flop , y es básicamente un pequeño bucle de cable junto con algunas puertas Y y poder para mantenerlo estable. Al juntar múltiples cierres, puede crear vectores de bits, y estos elementos se denominan registros (que son lo que representan elementos como eax y ebx). También hay muchos otros tipos de partes, como sumadores, multiplexores, etc. que implementan varias piezas de lógica booleana. Aquí hay un directorio de algunos circuitos:
http://www.labri.fr/perso/strandh/Teaching/AMP/Common/Strandh-Tutorial/Dir.html
Su CPU es básicamente un conjunto de estas cosas unidas, todas construidas a partir de las mismas puertas lógicas básicas. La forma en que su computadora sabe cómo seguir ejecutando instrucciones es que hay una pieza especial de maquinaria llamada reloj que emite pulsos a intervalos regulares. Cuando el reloj de su CPU emite un pulso, se activa una secuencia de reacciones en estas puertas lógicas que hace que la CPU ejecute una instrucción. Por ejemplo, cuando lee una instrucción que dice "mov eax, ebx", lo que termina sucediendo es que el estado de uno de estos registros (ebx) se copia al estado de otro (eax) justo a tiempo antes del siguiente pulso de sale del reloj.
Por supuesto, esto es una simplificación excesiva, pero como una imagen de alto nivel, es esencialmente correcta. El resto de los detalles tardan en explicarse, y aquí hay algunas cosas que descuidé debido a la sutileza innecesaria (por ejemplo, en una CPU real a veces se ejecutan múltiples instrucciones en un solo reloj, y debido a la paginación del registro a veces eax isn no siempre es lo mismo, y a veces, debido a un reordenamiento ocasional, se mueve la forma en que se ejecutan las instrucciones, y así sucesivamente). Sin embargo, definitivamente vale la pena aprender toda la historia, ya que en realidad es bastante sorprendente (¡o al menos me gusta pensar que sí!). Te harías un gran favor para salir y leer sobre esto, y tal vez intentar construir un pocos circuitos propios (¡ya sea usando hardware real, un simulador o incluso minecraft!)
De todos modos, espero que responda un poco a tu pregunta sobre lo que mov eax, ebx hace.
Las instrucciones del código de ensamblado se asignan al conjunto de instrucciones real y a los nombres de registro para la arquitectura de CPU a la que se dirige. mov
es una instrucción X86, y eax
y otros son los nombres de registros (en este caso de uso general) que definen el manual de referencia de Intel x86.
Lo mismo para otras arquitecturas: el código de ensamblado se asigna bastante directamente a los nombres reales de las operaciones tal como se define en las especificaciones / documentación del chip.
Ese mapeo es mucho más simple que, por ejemplo, compilar el código C
Lo primero que todas las instrucciones como mov, add, etc. tienen significado propio en forma binaria como 10101010, 00110000, 10100, algunas de ellas también, que entienden siempre la CPU.
pero los humanos no pueden recordarlos a todos. entonces ... para fines de programación que se usan en inglés. que finalmente llegará a su propio lugar (binario).
La segunda conversión de inglés (mov, add, etc.) a binario ocurre en, al ensamblar o compilar el código. después de eso- instrucciones binarias (conjuntos de instrucciones) almacenados en RAM y listos para su ejecución.
pero puede que no sea tu respuesta, lo sé.
si quieres saber e imaginar perfectamente, cómo la CPU extruye las instrucciones y trabaja en ellas. Puedes aprenderlo con gráficos aquí. mira este video en youtube: (enlace aquí)
Míralo una vez y te lo prometo. lo tendrás más claro al respecto. mira bien.
Lo que se ve son mnemotécnicos, que facilitan que el programador escriba el ensamblaje, pero no es ejecutable en forma mnemónica. cuando pasa estas instrucciones de ensamblaje a través de un ensamblador, se traducen en el código de máquina que representan, que es lo que la CPU y sus diversos coprocesadores interpretan y ejecutan (generalmente es reducido a unidades más pequeñas por la CPU, llamadas microoperaciones) .
si tiene curiosidad sobre cómo exactamente lo hace, bueno, eso es un proceso largo, pero esto tiene toda esa información.
Todas las semánticas, etc., son manejadas por el ensamblador, que verifica la validez y la integridad cuando es posible (¡aún así se puede ensamblar el código no válido!). esto básicamente hace que el ensamblado sea un lenguaje de bajo nivel, aunque tiene una correlación de 1 a 1 con el código de la máquina de salida (excepto cuando se usan ensambladores basados en macros, pero las macros todavía se expanden a 1 a 1).
Su CPU no ejecuta el ensamblaje. El ensamblador lo convierte en código de máquina. Este proceso depende tanto del lenguaje ensamblador particular como de la arquitectura de la computadora de destino. En general, estos van de la mano, pero puede encontrar diferentes sabores del lenguaje ensamblador (nasm vs. AT & T, por ejemplo), que se traducen en códigos de máquina similares.
Una instrucción de ensamblaje típica ( MIPS ) como "Y inmediato"
andi $t, $s, imm
se convertiría en la palabra de código de máquina de 32 bits
0011 00ss ssst tttt iiii iiii iiii iiii
donde s
y t
son números del 0-31 cuyo nombre se registra, i
es un valor de 16 bits. Es este patrón de bits que la CPU realmente ejecuta. El 001100
al principio es el código de operación correspondiente a la instrucción andi
, y el patrón de bits que sigue (registro de origen de 5 bits, registro de destino de 5 bits, literal de 16 bits) varía según las instrucciones. Cuando esta instrucción se coloca en la CPU, responde de manera apropiada decodificando el código de operación, seleccionando los registros que se leerán y escribirán, y configurando la ALU para realizar la aritmética necesaria.