Código de ensamblaje vs código de máquina vs código de objeto?

227

¿Cuál es la diferencia entre el código objeto, el código máquina y el código ensamblador?

¿Puedes dar un ejemplo visual de su diferencia?

mmcdole
fuente
También tengo curiosidad acerca de dónde vino el nombre del "código objeto". ¿Qué se supone que significa la palabra "objeto" en ella? ¿Está relacionado de alguna manera con la programación orientada a objetos o simplemente una coincidencia de nombres?
SasQ
@SasQ: Código de objeto .
Jesse Good
No estoy preguntando qué es un código objeto, Capitán Obvio. Estoy preguntando de dónde vino el nombre y por qué se llama código "objeto".
BarbaraKwarc

Respuestas:

296

El código de máquina es un código binario (1 y 0) que la CPU puede ejecutar directamente. Si abriera un archivo de código de máquina en un editor de texto, vería basura, incluidos caracteres no imprimibles (no, no esos caracteres no imprimibles;)).

El código de objeto es una parte del código de máquina que aún no se ha vinculado a un programa completo. Es el código de máquina para una biblioteca o módulo en particular que conformará el producto completo. También puede contener marcadores de posición o compensaciones que no se encuentran en el código de máquina de un programa completado. El enlazador utilizará estos marcadores de posición y compensaciones para conectar todo.

El código de ensamblaje es un código fuente de texto sin formato y (algo) humano que puede leerse y que en su mayoría tiene un análogo directo 1: 1 con instrucciones de la máquina. Esto se logra usando mnemónicos para las instrucciones, registros u otros recursos reales. Los ejemplos incluyen JMPy MULTpara las instrucciones de salto y multiplicación de la CPU. A diferencia del código de máquina, la CPU no comprende el código de ensamblaje. Convierte el código de ensamblaje a máquina con el uso de un ensamblador o un compilador , aunque generalmente pensamos en compiladores en asociación con un lenguaje de programación de alto nivel que se extrae aún más de las instrucciones de la CPU.

Construir un programa completo implica escribir el código fuente del programa en ensamblador o en un lenguaje de nivel superior como C ++. El código fuente se ensambla (para el código de ensamblaje) o se compila (para lenguajes de nivel superior) al código objeto, y los módulos individuales se vinculan entre sí para convertirse en el código de máquina para el programa final. En el caso de programas muy simples, el paso de vinculación puede no ser necesario. En otros casos, como con un IDE (entorno de desarrollo integrado), el vinculador y el compilador se pueden invocar juntos. En otros casos, un complicado maquillaje script o solución de archivo puede ser utilizado para contar el entorno de la forma de construir la aplicación final.

También hay idiomas interpretados que se comportan de manera diferente. Los idiomas interpretados se basan en el código de máquina de un programa especial de interpretación. En el nivel básico, un intérprete analiza el código fuente e inmediatamente convierte los comandos a un nuevo código de máquina y los ejecuta. Los intérpretes modernos, a veces también llamados entornos de tiempo de ejecución o máquinas virtuales , son mucho más complicados: evaluar secciones enteras de código fuente a la vez, almacenar en caché y optimizar donde sea posible, y manejar tareas complejas de administración de memoria. Un lenguaje interpretado también se puede precompilar a un lenguaje intermedio de nivel inferior o código de bytes, similar al código ensamblador.

Joel Coehoorn
fuente
24
+1: respuesta agradable, pero algo simplificadora: no todas las instrucciones de ensamblaje se traducen 1: 1 a instrucciones de máquina, y los archivos de objetos también pueden contener otros datos (información de reubicación, tablas de símbolos, ...)
Christoph
55
Se agregó una palabra comadreja para su primer problema, editado para aclarar el segundo.
Joel Coehoorn el
2
@ Christoph: usted dice "no todas las instrucciones de montaje se traducen 1: 1 a las instrucciones de la máquina", por favor, dé un ejemplo.
Olof Forshell
55
@Olof: las arquitecturas RISC a veces proporcionan un conjunto de instrucciones virtuales de nivel de ensamblaje, por ejemplo, pseudoinstrucciones MIPS ( en.wikipedia.org/wiki/MIPS_architecture#Pseudo_instructions )
Christoph
3
@Panzercrisis El ensamblador no agrega nada. Es una traducción directa de lo que escribió a las instrucciones reales de la máquina. Y no llamaría "innecesario" el código extra que ponen los compiladores
Joel Coehoorn
125

Las otras respuestas dieron una buena descripción de la diferencia, pero también solicitó un visual. Aquí hay un diagrama que muestra que viajan del código C a un ejecutable.

Noob de gráficos
fuente
3
Encuentro esto realmente útil, pero le falta la etiqueta "Código de máquina"
Alexx Roche
Entonces, cuando está en el nivel de código ejecutable, ¿es eso equivalente al código de máquina?
CMCDragonkai
3
En el contexto de este diagrama, el "código objeto" es el código máquina.
Graphics Noob
55
En realidad, tanto el código objeto como el código ejecutable son códigos de máquina. La diferencia es que el código objeto no es el programa completo. Debe combinarse con otros códigos auxiliares de biblioteca / módulo como se indica en el diagrama para formar un código / programa ejecutable completo.
okey_on
@okeyxyz, ¿a qué nivel sería correcto decir que el procesador lo ejecuta directamente? ¿Después del ensamblador, después del enlazador, después del cargador, después de que se convierte en microcontrolador?
Celeritas
49

El código de ensamblaje es una representación legible por humanos del código de máquina:

mov eax, 77
jmp anywhere

El código de la máquina es código hexadecimal puro:

5F 3A E3 F1

Supongo que te refieres al código objeto como en un archivo objeto. Esta es una variante del código de máquina, con la diferencia de que los saltos están parametrizados de tal manera que un enlazador puede completarlos.

Un ensamblador se utiliza para convertir el código de ensamblaje en código de máquina (código de objeto). Un vinculador vincula varios archivos de objeto (y biblioteca) para generar un ejecutable.

Una vez he escrito un programa de ensamblador en hexadecimal puro (no hay ensamblador disponible), afortunadamente, esto se remonta al antiguo y antiguo 6502. Pero me alegro de que haya ensambladores para los códigos de operación pentium.

Toon Krijthe
fuente
76
No no no no. El código de la máquina no es código hexadecimal. Es puro binario. El código hexadecimal es solo una representación conveniente de binario.
Breton
56
Si realmente estamos llegando a extremos, no es binario, es una cantidad de electricidad almacenada en un circuito. ;-)
Toon Krijthe el
17
Sí, por supuesto. Existe una relación entre el hexadecimal y lo que llamaría "Código de máquina", pero no es del todo exacto decir que hexadecimal es código de máquina. Eso es todo lo que intento decir.
Breton
99
@Breton En ese sentido, no existe el "código hexadecimal", ¿verdad? El "código hexadecimal" es solo una forma de ver el código de la máquina. Puede ver el código de la máquina en hexadecimal, binario, octal, decimal o como desee. También de nuevo en ese sentido, tampoco hay un "código binario". Nuevamente, el "código binario" es solo una forma de ver el código de la máquina.
Utku
99
@Breton Lo que dices no tiene mucho sentido. Binario es una forma de representación, al igual que hexadecimal. Si no es hexadecimal, tampoco es binario.
Koray Tugay
18

8B 5D 32 es código de máquina

mov ebx, [ebp+32h] es asamblea

lmylib.soque contiene 8B 5D 32es el código objeto

Quassnoi
fuente
8

Un punto que aún no se menciona es que hay algunos tipos diferentes de código de ensamblaje. En la forma más básica, todos los números utilizados en las instrucciones deben especificarse como constantes. Por ejemplo:

$ 1902: BD 37 14: LDA $ 1437, X
$ 1905: 85 03: STA $ 03
$ 1907: 85 09: STA $ 09
$ 1909: CA: DEX
$ 190A: 10: BPL $ 1902

El bit de código anterior, si se almacena en la dirección $ 1900 en un cartucho Atari 2600, mostrará una serie de líneas en diferentes colores obtenidas de una tabla que comienza en la dirección $ 1437. En algunas herramientas, escribir una dirección, junto con la parte más a la derecha de la línea de arriba, almacenaría en la memoria los valores que se muestran en la columna central, y comenzaría la siguiente línea con la siguiente dirección. Escribir código en esa forma era mucho más conveniente que escribir en hexadecimal, pero uno tenía que saber las direcciones precisas de todo.

La mayoría de los ensambladores permiten usar direcciones simbólicas. El código anterior se escribiría más como:

rainbow_lp:
  lda ColorTbl, x
  sta WSYNC
  sta COLUBK
  dex
  bpl rainbow_lp

El ensamblador ajustará automáticamente la instrucción LDA para que haga referencia a cualquier dirección asignada a la etiqueta ColorTbl. El uso de este estilo de ensamblador hace que sea mucho más fácil escribir y editar código de lo que sería posible si uno tuviera que teclear y mantener manualmente todas las direcciones.

Super gato
fuente
1
+1. Un punto adicional más: también hay diferentes sintaxis en lenguaje ensamblador , siendo las más famosas Intel y AT&T .
informatik01
1
@ informatik01: ¿Qué tal la mnemotecnia Intel 8080 vs Zilog Z80? Supongo que es anterior a la guerra de sintaxis Intel vs AT&T.
supercat
Sin discutir, solo mencioné ese aspecto (sintaxis diferente) y di un ejemplo de las dos sintaxis más populares / conocidas / famosas.
informatik01
4

Código fuente, código de ensamblaje, código de máquina, código de objeto, código de byte, archivo ejecutable y archivo de biblioteca.

Todos estos términos son a menudo muy confusos para la mayoría de las personas por el hecho de que piensan que son mutuamente excluyentes . Vea el diagrama para entender sus relaciones. La descripción de cada término se da a continuación.


Tipos de código


Código fuente

Instrucciones en lenguaje legible por humanos (programación)


Código de alto nivel

Instrucciones escritas en un lenguaje de alto nivel (programación),
por ejemplo, programas C, C ++ y Java


Código de montaje

Instrucciones escritas en lenguaje ensamblador (tipo de lenguaje de programación de bajo nivel). Como primer paso del proceso de compilación, el código de alto nivel se convierte a este formulario. Es el código de ensamblaje que luego se convierte en código de máquina real. En la mayoría de los sistemas, estos dos pasos se realizan automáticamente como parte del proceso de compilación.
por ejemplo, program.asm


Código de objeto

El producto de un proceso de compilación. Puede estar en forma de código de máquina o código de byte.
por ejemplo, file.o


Codigo de maquina

Instrucciones en lenguaje máquina.
por ejemplo, a.out


Código de bytes

Instrucción en una forma intermedia que puede ser ejecutada por un intérprete como JVM.
por ejemplo, archivo de clase Java


Archivo ejecutable

El producto del proceso de vinculación. Son códigos de máquina que pueden ser ejecutados directamente por la CPU.
por ejemplo, un archivo .exe.

Tenga en cuenta que, en algunos contextos, un archivo que contiene código de bytes o instrucciones de lenguaje de script también puede considerarse ejecutable.


Archivo de la biblioteca

Parte del código se compila en este formulario por diferentes razones, como la reutilización y luego es utilizado por archivos ejecutables.

Bertram Gilfoyle
fuente
1
Yo diría que no todo el ensamblaje es realmente fuente en el sentido más estricto del código escrito y / o mantenido por humanos. A menudo, se genera a máquina desde la fuente, y nunca está destinado al consumo humano (por ejemplo, gcc realmente crea texto asm que alimenta a un ensamblador separado, en lugar de tener un ensamblador incorporado dentro del cc1ejecutable). Creo que el círculo asm debería sobresalir del lado izquierdo del círculo "fuente", porque algunos asm son solo asm, no fuente. Nunca es un código objeto , por supuesto, pero algunos asm son un paso en el camino desde los archivos fuente a los objetos.
Peter Cordes
@PeterCordes Muchas gracias por el comentario. No sabía lo que dijiste sobre el funcionamiento de gcc. Sin embargo, me temo que puedo estar completamente de acuerdo contigo. Lo que quiero decir es que el código fuente es algo escrito usando un lenguaje de programación legible por humanos. Puede o no ser escrito o mantenido por humanos. Estoy seguro de que conocerá los transcompiladores. Desde su punto de vista, ¿a qué categoría colocará el producto de dicho compilador? Código fuente o algo más? Por favor corrígeme si estoy equivocado. Otros comentarios son siempre bienvenidos.
Bertram Gilfoyle
1

El código de ensamblaje se discute aquí .

"Un lenguaje ensamblador es un lenguaje de bajo nivel para la programación de computadoras. Implementa una representación simbólica de los códigos numéricos de la máquina y otras constantes necesarias para programar una arquitectura de CPU en particular".

El código de la máquina se discute aquí .

"El código de máquina o lenguaje de máquina es un sistema de instrucciones y datos ejecutados directamente por la unidad central de procesamiento de una computadora".

Básicamente, el código del ensamblador es el lenguaje y un ensamblador lo traduce al código objeto (el código nativo que ejecuta la CPU) (análogo a un compilador).

rbrayb
fuente
1

Creo que estas son las principales diferencias.

  • legibilidad del código
  • control sobre lo que está haciendo tu código

La legibilidad puede mejorar o sustituir el código 6 meses después de que se creó con poco esfuerzo, por otro lado, si el rendimiento es crítico, es posible que desee utilizar un lenguaje de bajo nivel para apuntar al hardware específico que tendrá en producción, para obtener ejecución más rápida

Las computadoras IMO de hoy son lo suficientemente rápidas como para permitir que un programador obtenga una ejecución rápida con OOP.

Alberto Zaccagni
fuente
1

Ensamblaje es un breve término descriptivo que los humanos pueden entender que se puede traducir directamente al código de máquina que una CPU realmente usa.

Aunque es algo comprensible para los humanos, Assembler sigue siendo de bajo nivel. Se necesita mucho código para hacer algo útil.

Entonces, en su lugar, usamos lenguajes de nivel superior como C, BÁSICO, FORTAN (OK, sé que he salido conmigo mismo). Cuando se compilan estos producen código objeto. Los primeros idiomas tenían el lenguaje de máquina como su código objeto.

Hoy en día, muchos lenguajes como JAVA y C # se compilan en un código de bytes que no es código de máquina, sino uno que se puede interpretar fácilmente en tiempo de ejecución para producir código de máquina.

Jim C
fuente
Su comentario sobre Java y C #: ambos utilizan la compilación Just In Time para que los bytecodes no se interpreten. C # (.NET en general) se compila en lenguaje intermedio (IL) que luego se JIT en lenguaje de máquina nativo para la CPU de destino.
Craig Shearer
-1

Los archivos de origen de sus programas se compilan en archivos de objetos, y luego el vinculador vincula esos archivos de objetos, produciendo un archivo ejecutable que incluye los códigos de máquina de su arquitectura.

Tanto el archivo objeto como el archivo ejecutable incluyen el código de máquina de la arquitectura en forma de caracteres imprimibles y no imprimibles cuando es abierto por un editor de texto.

No obstante, la dicotomía entre los archivos es que los archivos de objeto pueden contener referencias externas no resueltas (como printf, por ejemplo). Por lo tanto, es posible que deba vincularse con otros archivos de objetos. Es decir, las referencias externas no resueltas deben resolverse para obtener el archivo ejecutable ejecutable decente mediante la vinculación con otros archivos de objetos como la biblioteca de tiempo de ejecución C / C ++ .

snr
fuente