¿Es posible un lenguaje ensamblador universal para todas las computadoras?


23

Me gustaría hacer algunas preguntas sobre el lenguaje ensamblador. Tengo entendido que está muy cerca del lenguaje de máquina, lo que lo hace más rápido y más eficiente.

Dado que tenemos diferentes arquitecturas de computadora, ¿eso significa que tengo que escribir un código diferente en Assembly para diferentes arquitecturas? Si es así, ¿por qué no es ensamblado, escribir una vez? ¿No sería más fácil simplemente hacerlo universal, para que lo escriba solo una vez y pueda ejecutarlo en prácticamente cualquier máquina con diferentes configuraciones? (Creo que sería imposible, pero me gustaría tener algunas respuestas concretas y profundas)

Algunas personas podrían decir que C es el lenguaje que estoy buscando. No he usado C antes, pero creo que sigue siendo un lenguaje de alto nivel, aunque probablemente más rápido que Java, por ejemplo. Podría estar equivocado aquí.


10
¿Qué investigación has hecho? Esperamos que haga una investigación antes de preguntar, para ayudarlo a hacer una mejor pregunta. Hay muchos escritos en lenguaje ensamblador.
DW

44
Esperamos que haga una gran cantidad de investigación / autoestudio antes de preguntar, y que nos diga en la pregunta qué investigación ha realizado. En este caso, la investigación podría incluir la lectura de artículos relevantes de Wikipedia (por ejemplo, sobre lenguaje ensamblador y arquitectura de computadora) y la lectura de un libro de texto de arquitectura de computadora. Para que esta sea una mejor pregunta: investigue, si aún no lo ha hecho, y luego edite la pregunta para explicar la investigación que ha realizado. A menudo, ese tipo de investigación lo ayuda a formular una mejor pregunta; y en cualquier caso, ayuda a los respondedores a evitar repetir lo que ya sabes.
DW

15
Comience por comprender que / por qué no hay un lenguaje llamado Asamblea.
Raphael

2
Un problema "clásico" con la portabilidad en C son los diferentes tamaños de primitivas (por ejemplo, enteros) en diferentes hardware y se mencionan algunos otros.
vzn

3
Esto es más un problema social que técnico: debe convencer a todos los fabricantes de CPU para que acepten el mismo lenguaje de máquina. (En realidad, x86 casi iba a ser esto, por casualidad, luego los teléfonos inteligentes despegaron)
user253751

Respuestas:


45

El lenguaje ensamblador es una forma de escribir instrucciones para el conjunto de instrucciones de la computadora , de una manera que es un poco más comprensible para los programadores humanos.

Las diferentes arquitecturas tienen diferentes conjuntos de instrucciones: el conjunto de instrucciones permitidas es diferente en cada arquitectura. Por lo tanto, no puede esperar tener un programa de ensamblaje de escribir una vez y ejecutar en todas partes. Por ejemplo, el conjunto de instrucciones admitidas por los procesadores x86 se ve muy diferente del conjunto de instrucciones admitidas por los procesadores ARM. Si escribió un programa de ensamblaje para un procesador x86, tendría muchas instrucciones que no son compatibles con el procesador ARM, y viceversa.

La razón principal para usar el lenguaje ensamblador es que permite un control de muy bajo nivel sobre su programa y para aprovechar todas las instrucciones del procesador: al personalizar el programa para aprovechar las características que son exclusivas del procesador en particular. se ejecutará, a veces puedes acelerar el programa. La filosofía de escribir una vez y correr en todas partes está fundamentalmente en desacuerdo con eso.


1
Creo que esa pregunta ya está respondida en el tercer párrafo de mi respuesta. Como dijiste, dicho esquema no sería eficiente, por lo que estaría fundamentalmente en desacuerdo con la razón principal para usar el lenguaje ensamblador.
DW

26
@nTuply Tan pronto como modifique su lenguaje ensamblador para atender a diferentes máquinas, se convertirá en un lenguaje de alto nivel con una sintaxis horriblemente de estilo ensamblador. Una vez que haya decidido usar un lenguaje de alto nivel, también puede usar uno con una sintaxis más amigable y dejar que el compilador haga el trabajo duro.
David Richerby

15
No es una idea completamente estúpida tener un "lenguaje ensamblador" que se traduzca para diferentes máquinas, porque eso es básicamente lo que es el "IR" de LLVM. Sin embargo, por las razones que da David, normalmente no escribe el ensamblaje LLVM. Además, porque 99 de cada 100 veces haría un trabajo peor al escribirlo que al hacer ruido al traducir su C a LLVM. Los lenguajes de ensamblaje son potencialmente más eficientes que los lenguajes de alto nivel, pero en manos de la mayoría de los programadores reales con una cantidad típica de tiempo disponible para optimizar, de todos modos no alcanzan su potencial.
Steve Jessop

99
@nTuply, eso existe. El proceso de pasar de ese lenguaje extra-ensamblador a las instrucciones de la máquina se llama compilación.
Paul Draper

3
@PJTraill No hay ninguna razón para escribir un compilador en ensamblador en un sistema moderno, excepto el primer paso de arranque (y la mayoría de las veces, ni siquiera entonces). Los compiladores escritos en un lenguaje de alto nivel son mucho más probable que sea realmente fácil de mantener. También compare ¿Cómo puede un lenguaje cuyo compilador está escrito en C ser más rápido que C? . El propósito de un compilador es traducir de un idioma (el idioma de origen) a otro (generalmente lenguaje de máquina para una arquitectura y sistema operativo específicos); Esto se puede escribir en cualquier idioma.
un CVn

13

La DEFINICIÓN del lenguaje ensamblador es que es un lenguaje que se puede traducir directamente al código de máquina. Cada código de operación en lenguaje ensamblador se traduce exactamente en una operación en la computadora de destino. (Bueno, es un poco más complicado que eso: algunos ensambladores determinan automáticamente un "modo de direccionamiento" basado en los argumentos de un código operativo. Pero aún así, el principio es que una línea de ensamblaje se traduce en una instrucción en lenguaje de máquina).

Sin duda, podría inventar un lenguaje que se parezca al lenguaje ensamblador, pero que se traduciría a diferentes códigos de máquina en diferentes computadoras. Pero por definición, eso no sería lenguaje ensamblador. Sería un lenguaje de nivel superior que se asemeja al lenguaje ensamblador.

Su pregunta es un poco como preguntar: "¿Es posible hacer un bote que no flote o tenga otra forma de viajar a través del agua, pero que tenga ruedas y un motor y pueda viajar por tierra?" La respuesta sería que, por definición, dicho vehículo no sería un barco. Suena más como un auto.


1
C a menudo se ha descrito como "lenguaje ensamblador portátil".
Larry Gritz

2
@LarryGritz Claro. Y cuando se inventó C, fue innovador: ofreció gran parte del poder del lenguaje ensamblador con la facilidad de uso de un compilado. Pero por definición, sigue siendo un lenguaje compilado
Jay

8

No hay ninguna conceptual (me atrevería a decir, ningún ordenador ciencia ) razón en contra de tener un lenguaje ensamblador para todos los equipos del mundo. De hecho, eso facilitaría muchas cosas. En lo que respecta a la teoría, todos son iguales, de todos modos, hasta una biyección funky.

En la práctica, sin embargo, hay diferentes chips para diferentes propósitos, con diferentes operaciones y principios de diseño (por ejemplo, RISC vs CISC) que sirven para diferentes objetivos, y los conjuntos de instrucciones que los operan y, por lo tanto, los lenguajes de ensamblaje difieren. Al final, la respuesta es la misma que cuando se pregunta por qué hay tantos lenguajes de programación diferentes: objetivos diferentes, decisiones de diseño diferentes.

Dicho esto, por supuesto, puede introducir niveles de abstracción para llegar a alguna interfaz compartida. x86, por ejemplo, se ha eliminado en el nivel de chip durante bastante tiempo; hay una pequeña pieza de hardware que traduce las instrucciones x86 a lo que su procesador realmente funcione. Lenguajes como C estarían un paso más allá del hardware (aunque sea uno muy pequeño), hasta lenguajes como Haskell, Java o Ruby. Sí, los compiladores son uno de los principales logros de la informática porque permiten separar las preocupaciones de esta manera.


66
"si se puede decir que es muy pequeño": ahí están sus dos tipos de programadores. Quienes consideran que C es un lenguaje de bajo nivel porque sus operaciones básicas se parecen mucho al tipo de cosas que aparecen en los conjuntos de instrucciones de la CPU, y quienes consideran que C es un lenguaje de alto nivel porque no es el mismo conjunto de instrucciones que la máquina.
Steve Jessop

Si por lenguaje ensamblador se refiere a uno que proporciona control completo sobre el código de máquina generado para un tipo específico (o familia) de hardware, sería posible definir un idioma "para todas las computadoras" en nuestro mundo en un momento dado, pero sería Hay que seguir cambiando. Es cierto (si está bien diseñado) acortar la curva de aprendizaje para la codificación de una nueva arquitectura, pero espero que cualquier trabajo que desee hacer con ella en lugar de un compilador solo se aplique a una pequeña fracción de arquitecturas. Que las computadoras son iguales en un nivel abstracto es una pista falsa, se trata de código de máquina.
PJTraill

7

Usted menciona la frase "escribir una vez que se ejecuta en cualquier lugar" sin que parezca darse cuenta de su importancia. Ese es el lema de marketing de Sun Microsystems que inventó comercialmente el concepto de una "máquina virtual" y "bytecodes" para Java, aunque posiblemente la idea puede tener su origen en el mundo académico 1 st. La idea fue copiada más tarde por Microsoft para .Net después de que Sun los demandó con éxito por incumplimiento de la licencia de Java. Los bytecodes de Java son una implementación de la idea de ensamblaje entre máquinas o lenguaje de máquina. Se usan para varios otros idiomas además de Java y, en teoría, se pueden usar para compilar cualquier lenguaje. Después de muchos años de optimización muy avanzada, Java se acerca en rendimiento a los lenguajes compilados que muestran que el objetivo de la tecnología de máquina virtual independiente de la plataforma de alto rendimiento es alcanzable en general.

Otra nueva idea en las primeras etapas / circulación relacionada con sus requisitos se llama proyecto de recálculo y es para investigación científica, aunque podría usarse para otros fines. La idea es hacer que los experimentos computacionales sean replicables a través de la tecnología de máquina virtual. Esta es principalmente la idea de simular diferentes arquitecturas de máquinas en hardware arbitrario.


8
Sun no inventó ni las máquinas virtuales ni el código de bytes, ni siquiera fueron el primer grupo en ganar dinero con ellas. Busque el código p.
jmoreno

@ jmoreno: también podría querer buscar Smalltalk.
Bob Jarvis - Restablece a Monica el

El artículo no reclama máquinas virtuales inventadas por Sun / código de bytes. Hay otra historia no citada pero mencionada. por cierto, otra tecnología clave muy relevante aquí: cliente nativo de Google (función de Chrome)
vzn

5

Razones de alto nivel

Cuando lo piensa, un microprocesador hace una cosa asombrosa: le permite tomar una máquina (como una lavadora o un elevador) y reemplazar una gran cantidad de mecanismos o circuitos diseñados a medida con un silicio barato y producido en masa. chip. Se ahorra mucho dinero en piezas y mucho tiempo en diseño.

¿Pero espera un chip estándar que reemplaza innumerables diseños personalizados ? No puede haber un solo microprocesador perfecto que sea perfecto para cada aplicación. Algunas aplicaciones necesitan minimizar el uso de energía pero no necesitan ser rápidas; otros deben ser rápidos pero no deben ser fáciles de programar, otros deben ser de bajo costo, etc.

Por lo tanto, tenemos muchos "sabores" diferentes de microprocesador, cada uno con sus propias fortalezas y debilidades. Es deseable que todos usen un conjunto de instrucciones compatible, ya que esto permite la reutilización del código y facilita la búsqueda de personas con las habilidades adecuadas. Sin embargo, el conjunto de instrucciones hace afectar el costo, la complejidad, la velocidad, facilidad de uso y las limitaciones físicas del procesador, y por eso tenemos un compromiso: hay unos "principales" conjuntos de instrucciones (y muchos otros menores), y Dentro de cada conjunto de instrucciones hay muchos procesadores con diferentes características.

Ah, y a medida que la tecnología cambia, todas estas compensaciones cambian, por lo que los conjuntos de instrucciones evolucionan, surgen otros nuevos y los viejos mueren. Incluso si hubiera un "mejor" conjunto de instrucciones de hoy, podría no serlo en 20 años.

Detalles de hardware

Probablemente, la decisión de diseño más importante en un conjunto de instrucciones es el tamaño de la palabra , es decir, qué tan grande puede manipular el procesador "naturalmente". Los procesadores de 8 bits manejan números del 0 al 255, mientras que los procesadores de 32 bits manejan números del 0 al 4,294,967,295. El código diseñado para uno necesita ser completamente repensado para otro.

No se trata solo de traducir las instrucciones de un conjunto de instrucciones a otro. Un enfoque completamente diferente puede ser preferible en un conjunto de instrucciones diferente. Por ejemplo, en un procesador de 8 bits, una tabla de búsqueda puede ser ideal, mientras que en un procesador de 32 bits una operación aritmética sería mejor para el mismo propósito.

Existen otras diferencias importantes entre los conjuntos de instrucciones. La mayoría de las instrucciones se dividen en cuatro categorías:

  • Computación (aritmética y lógica)
  • Flujo de control
  • Transferencia de datos
  • Configuración del procesador

Los procesadores difieren en el tipo de cálculos que pueden realizar, así como en la forma en que abordan el flujo de control, la transferencia de datos y la configuración del procesador.

Por ejemplo, algunos procesadores AVR no pueden multiplicarse ni dividirse; mientras que todos los procesadores x86 pueden. Como puede imaginar, eliminar los circuitos necesarios para tareas como la multiplicación y la división puede hacer que un procesador sea más simple y económico; estas operaciones aún pueden realizarse utilizando rutinas de software si son necesarias.

x86 permite instrucciones aritméticas para cargar sus operandos de la memoria y / o guardar sus resultados en la memoria; ARM es una arquitectura de almacén de carga y, por lo tanto, solo tiene unas pocas instrucciones dedicadas para acceder a la memoria. Mientras tanto, x86 tiene instrucciones dedicadas de ramificación condicional, mientras que ARM permite que prácticamente todas las instrucciones se ejecuten condicionalmente. Además, ARM permite realizar cambios de bits como parte de la mayoría de las instrucciones aritméticas. Estas diferencias conducen a diferentes características de rendimiento, diferencias en el diseño interno y el costo de los chips, y diferencias en las técnicas de programación a nivel de lenguaje ensamblador.

Conclusión

La razón por la que es imposible tener un lenguaje ensamblador universal es que, para convertir correctamente el código ensamblador de un conjunto de instrucciones a otro, uno debe diseñar el código nuevamente, algo que las computadoras aún no pueden hacer.


Excelente respuesta! Las personas no entienden lo suficiente que las cosas informáticas que necesitan ser programadas están en todas partes entre nosotros. No solo se ven las aplicaciones que se ejecutan en nuestras pantallas. ¿Cuántos miles de millones de chips se fabrican cada año?
phs

4

Agregando a la maravillosa respuesta de DW: si desea tener un ensamblador, necesitaría mantener todas las arquitecturas, un traductor perfecto entre ellas y comprender completamente lo que está haciendo.
Algunos códigos muy optimizados por arquitectura necesitarían ser desoptimizados, entendidos en un nivel más abstracto y optimizados por otro.
Pero si esto fuera posible, tendríamos un compilador C perfecto, y escribir en ensamblado puro no sería beneficioso en absoluto.
El punto principal de usar el ensamblador es el rendimiento, que no se puede extraer de los compiladores recientes.
Escribir dicho programa sería aún más difícil que los compiladores existentes y mantener todas las arquitecturas nuevas que se están creando lo haría aún más difícil.
Y para el programa "one only", también significaría compatibilidad total con versiones anteriores.


Para la gran mayoría de los casos, gcc realiza una mejor optimización que un programador. El punto principal de usar el ensamblador es hacer cosas que no puedes hacer en C, como acceder a los registros. Si nos fijamos en el árbol fuente de Linux, eso es más o menos para lo que usan el ensamblaje.
slebetman

@slebetman - gcc le permite poner una variable en un registro sin recurrir al ensamblaje.
Jirka Hanika

@JirkaHanika: ¿estás hablando de registros de CPU o registros de hardware de propósito especial tratados con instrucciones especiales? Sospecho que slebetman significa lo último.
PJTraill

"Todos los códigos" - "GCC funciona mejor" = "usa ensamblador". Sí, puede acceder a los registros sin inserciones de ensamblador.
Mal

@PJTraill: el comentario de Slebetman es generalmente excelente y quizás debería incorporarse a la respuesta. Pero, es probable que sus dos ejemplos (acceso de registro y árbol de fuentes de Linux) alimenten conceptos erróneos comunes en lugar de que sean excelentes ejemplos de lo que no se puede hacer en C con extensiones gcc; esos deben ser reemplazados u omitidos. (Si hay una instrucción HW para hacer algo hoy, tendrá la extensión gcc correspondiente dentro de un año a partir de ahora. No siempre, pero muy a menudo. Ejemplos de edad.)
Jirka Hanika

3

Microsoft inventó MSIL para ser un lenguaje ensamblador intermedio. Los programas se compilarían de C # o VB.Net a MSIL. En tiempo de ejecución, el MSIL se compiló en código de máquina para la máquina que lo estaba ejecutando utilizando un compilador JIT . El archivo que contenía el MSIL era un archivo .EXE con algunas instrucciones al principio en X86 para iniciar el programa. En un procesador ARM, escribiría la palabra mono delante del nombre del programa para ejecutarlo.


¿Cuál es la diferencia entre "lenguaje ensamblador intermedio" y "máquina virtual"?
Bob Jarvis - Restablece a Monica el

@BobJarvis: Uno es código mientras que el otro es intérprete. Debería haber preguntado cuál es la diferencia entre el ensamblaje intermedio y el
código de bytes

Esto no parece responder a la pregunta. Siempre que cada máquina compile / ensamble MSIL de manera diferente, no tiene nada de universal, y el propósito de dicha compilación es portar la funcionalidad genérica y no la explotación de un conjunto de instrucciones en particular, que, como señala DW, es el (o a) razón para usar el ensamblador.
PJTraill

3

Como se señaló, LLVM es lo más cercano a esto hasta ahora. Una gran barrera para un lenguaje realmente universal serán las diferencias fundamentales relacionadas con las compensaciones implícitas: concurrencia, uso de memoria, rendimiento, latencia y consumo de energía. Si escribe en un estilo SIMD explícito, podría estar usando demasiada memoria. Si escribe en un estilo explícitamente SISD, obtendría una paralelización subóptima. Si optimiza el rendimiento, daña la latencia. Si maximiza el rendimiento de un solo subproceso (es decir, la velocidad del reloj), daña la vida útil de la batería.

Por lo menos, el código necesitaría ser anotado con las compensaciones. Lo que puede ser más importante es que el lenguaje tenga buenas propiedades algebraicas / tipo que le den al compilador mucho margen de maniobra para optimizar y detectar inconsistencias lógicas.

Luego está la cuestión del comportamiento indefinido. Gran parte de la velocidad de C y los lenguajes de ensamblaje provienen de un comportamiento indefinido. Si admite un comportamiento indefinido que realmente sucede, entonces termina manejándolos como casos especiales (es decir: pirateos específicos de arquitectura y contexto).


0

Quizás lo que está buscando es una notación de Universal Turning Machine donde todos estén de acuerdo con los símbolos de los comandos. ( https://en.wikipedia.org/wiki/Universal_Turing_machine )

Un 'ensamblador' que traduce un lenguaje Aceptable de Turning al código de máquina específico del proveedor subyacente y se construye para cualquiera de esas cosas que llamamos computadoras.

En The Art of Computer Programming hay un ejemplo de cómo se vería esto.

Pero considere la pregunta "por qué no es un lenguaje universal disponible en el mercado que se puede usar con todas las computadoras". Sugeriría que las influencias más dominantes son (1) conveniencia, no todos los lenguajes ensambladores son los más convenientes para usar; (2) la economía, el suministro, la incompatibilidad entre máquinas de diferentes marcas y proveedores es una estrategia comercial, así como el resultado de recursos limitados (tiempo / dinero) para diseñar máquinas.


La pregunta es acerca de un lenguaje ensamblador que pueda usarse para programar cualquier computadora, no un lenguaje ensamblador que sea universal en el sentido de "máquina universal de Turing".
David Richerby

1
Church-Turing nos dice que el UTC puede hacer lo que cualquier computadora programable puede hacer. Aparte de los problemas finitos de almacenamiento físico. Un lenguaje ensamblador para un UTC es bastante factible. Pero, como dije, la practicidad cultural y económica puede limitar la implementación y adopción reales en el mercado.
Chris

Te estás perdiendo el mayor problema, ¡el rendimiento ! ¿Por qué usar un lenguaje 1000 veces más lento solo por un alto objetivo de ser independiente del hardware? La máquina de Turing es un modelo terrible para la informática práctica.
Artelius

1
¿Les gustaría a los comentaristas ofrecer alguna informática para respaldar sus afirmaciones? Esto es después de todo el foro de informática.
Chris

1
No soy un experto en CS. Pero lo que creo es que la arquitectura von Neumann es una brillante pieza de ingeniería que logra un equilibrio entre la capacidad de programación y el rendimiento, mientras que el propósito de la máquina Turing es mostrar que incluso la máquina más básica puede calcular cualquier cosa que una máquina más compleja pueda. Claro, puede seguir agregando más y más funciones a una máquina Turing (más cintas, aritmética), pero luego tiene el mismo problema que tuvo en primer lugar, es decir, las personas que no están de acuerdo con un conjunto de instrucciones. Además, la falta de acceso aleatorio crea grandes gastos generales en muchos algoritmos.
Artelius

0

supuesto: compilar y optimizar un lenguaje de alto nivel L1 a un lenguaje de nivel inferior L0 es más fácil que compilar y optimizar un lenguaje de alto nivel L2 (superior a L1) a L0; más fácil en el sentido de que supuestamente puede generar código más optimizado al compilar L1 a L0 que L2 a L0.

Creo que la suposición es probablemente correcta, por eso probablemente la mayoría de los compiladores usan un lenguaje intermedio de bajo nivel (IR / LLVM).

si esto es cierto, utilice cualquier lenguaje de bajo nivel L0 y escriba compiladores para traducir L0 a otros idiomas de bajo nivel. Por ejemplo, use el conjunto de instrucciones MIPS y compílelo a x86, arm, power, ...

-Taoufik


¿Entonces no sabes si tu respuesta es verdadera? ¿Y no puede soportarlo?
Mal
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.