Estoy confundido sobre el código máquina y el código nativo en el contexto de los lenguajes .NET.
¿Cuál es la diferencia entre ellos? ¿Son lo mismo?
.net
assembly
bytecode
machine-code
samaladeepak
fuente
fuente
Respuestas:
De hecho, los términos son un poco confusos, porque a veces se usan de manera inconsistente.
Código de máquina: este es el mejor definido. Es un código que usa las instrucciones de código de bytes que su procesador (la pieza física de metal que hace el trabajo real) comprende y ejecuta directamente. El resto del código debe traducirse o transformarse en código de máquina antes de que su máquina pueda ejecutarlo.
Código nativo: este término se usa a veces en lugares donde se hace referencia al código de máquina (ver arriba). Sin embargo, a veces también se usa para referirse a código no administrado (ver más abajo).
Código no administrado y código administrado: el código no administrado se refiere al código escrito en un lenguaje de programación como C o C ++, que se compila directamente en código de máquina . Contrasta con el código administrado , que está escrito en C #, VB.NET, Java o similar, y se ejecuta en un entorno virtual (como .NET o JavaVM), que “simula” un procesador en software. La principal diferencia es que el código administrado "administra" los recursos (principalmente la asignación de memoria) por usted empleando la recolección de basura y manteniendo opacas las referencias a los objetos. Código no administradoes el tipo de código que requiere que asigne y desasigne memoria manualmente, lo que a veces provoca pérdidas de memoria (cuando se olvida de desasignar) y, a veces, fallas de segmentación (cuando desasigna demasiado pronto). No administrado también suele implicar que no hay comprobaciones en tiempo de ejecución de errores comunes, como desreferenciación de puntero nulo o desbordamiento de límites de matriz.
Estrictamente hablando, la mayoría de los lenguajes de tipado dinámico, como Perl, Python, PHP y Ruby, también son código administrado . Sin embargo, no se describen comúnmente como tales, lo que muestra que el código administrado es en realidad un término de marketing para los entornos de programación comercial realmente grandes y serios (.NET y Java).
Código ensamblador: este término generalmente se refiere al tipo de código fuente que la gente escribe cuando realmente quiere escribir código de bytes. Un ensamblador es un programa que convierte este código fuente en código de bytes real. No es un compilador porque la transformación es 1 a 1. Sin embargo, el término es ambiguo en cuanto a qué tipo de código de bytes se usa: podría ser administrado o no administrado. Si no está administrado, el código de bytes resultante es código de máquina . Si se administra, el código de bytes se usa detrás de escena por un entorno virtual como .NET. El código administrado (por ejemplo, C #, Java) se compila en este lenguaje de código de bytes especial, que en el caso de .NET se denomina Lenguaje Intermedio Común (CIL) y en Java se denomina código de bytes de Java.. Por lo general, el programador común tiene poca necesidad de acceder a este código o escribir en este lenguaje directamente, pero cuando la gente lo hace, a menudo se refiere a él como código ensamblador porque usa un ensamblador para convertirlo en código de bytes.
fuente
Lo que ve cuando usa Depurar + Windows + Desmontaje al depurar un programa C # es una buena guía para estos términos. Aquí hay una versión anotada de la misma cuando compilo un programa 'hola mundo' escrito en C # en la configuración de lanzamiento con la optimización JIT habilitada:
Haga clic con el botón derecho en la ventana y marque "Mostrar bytes de código" para obtener una pantalla similar.
La columna de la izquierda es la dirección del código de la máquina. Su valor es falsificado por el depurador, el código está ubicado en otro lugar. Pero eso podría ser en cualquier lugar, dependiendo de la ubicación seleccionada por el compilador JIT, por lo que el depurador simplemente comienza a numerar direcciones desde 0 al comienzo del método.
La segunda columna es el código de la máquina . Los 1 y 0 reales que ejecuta la CPU. El código de máquina, como aquí, se muestra comúnmente en hexadecimal. Quizás ilustrativo es que 0x8B selecciona la instrucción MOV, los bytes adicionales están ahí para decirle a la CPU exactamente lo que necesita moverse. También tenga en cuenta los dos tipos de la instrucción CALL, 0xE8 es la llamada directa, 0xFF es la instrucción de llamada indirecta.
La tercera columna es el código ensamblador . El ensamblaje es un lenguaje simple, diseñado para facilitar la escritura de código de máquina. Se compara con la compilación de C # en IL. El compilador utilizado para traducir el código ensamblador se llama "ensamblador". Probablemente tenga el ensamblador de Microsoft en su máquina, su nombre ejecutable es ml.exe, ml64.exe para la versión de 64 bits. Hay dos versiones comunes de lenguajes ensambladores en uso. El que ves es el que usan Intel y AMD. En el mundo del código abierto, el ensamblaje en la notación de AT&T es común. La sintaxis del lenguaje depende en gran medida del tipo de CPU para el que se escribió, el lenguaje ensamblador de un PowerPC es muy diferente.
Bien, eso aborda dos de los términos de su pregunta. El "código nativo" es un término confuso, no es infrecuente que se utilice para describir código en un lenguaje no administrado. Quizás sea instructivo ver qué tipo de código de máquina genera un compilador de C. Esta es la versión 'hola mundo' en C:
No lo anoté, principalmente porque es muy similar al código de máquina generado por el programa C #. La llamada a la función printf () es bastante diferente de la llamada Console.WriteLine () pero todo lo demás es casi igual. También tenga en cuenta que el depurador ahora está generando la dirección del código de máquina real y que es un poco más inteligente con los símbolos. Un efecto secundario de generar información de depuración después de generar código de máquina, como suelen hacer los compiladores no administrados. También debo mencionar que desactivé algunas opciones de optimización de código de máquina para que el código de máquina se vea similar. Los compiladores de C / C ++ tienen mucho más tiempo disponible para optimizar el código, el resultado es a menudo difícil de interpretar. Y muy difícil de depurar.
El punto clave aquí es que existen muy pocas diferencias entre el código máquina generado a partir de un lenguaje administrado por el compilador JIT y el código máquina generado por un compilador de código nativo. Esta es la razón principal por la que el lenguaje C # puede competir con un compilador de código nativo. La única diferencia real entre ellos son las llamadas a la función de soporte. Muchos de los cuales se implementan en CLR. Y eso gira principalmente en torno al recolector de basura.
fuente
El código nativo y el código de máquina son lo mismo: los bytes reales que ejecuta la CPU.
El código ensamblador tiene dos significados: uno es el código de máquina traducido a una forma más legible por humanos (con los bytes de las instrucciones traducidos a mnemónicos cortos parecidos a palabras como "JMP" (que "salta" a otro lugar en el código). El otro es el código de bytes IL (bytes de instrucción que generan compiladores como C # o VB, que eventualmente terminarán traducidos al código de máquina, pero que aún no lo están) que vive en una DLL o EXE.
fuente
En .NET, los ensamblados contienen código de lenguaje intermedio de MS (MSIL, a veces CIL).
Es como un código de máquina de "alto nivel".
Cuando se carga, MSIL es compilado por el compilador JIT en código nativo (código de máquina Intel x86 o x64).
fuente