assembly - maquina - lenguaje ensamblador pdf
¿Son el conjunto de instrucciones y el lenguaje ensamblador lo mismo? (7)
Me preguntaba si el conjunto de instrucciones y el lenguaje ensamblador son la misma cosa.
Si no, ¿en qué se diferencian y cuáles son sus relaciones?
¡Gracias y saludos!
Creo que todos te están dando la misma respuesta. El conjunto de instrucciones es el conjunto (como en matemáticas) de todas las instrucciones que el procesador puede ejecutar o entender. El lenguaje ensamblador es un lenguaje de programación.
Déjame probar algunos ejemplos basados en algunas de las preguntas que estás haciendo. Y voy a saltar de un procesador a otro con el código que tenga a mano.
Instrucción, código de operación o lenguaje binario o de máquina, sea cual sea el término que quiera usar para los bits / bytes que se cargan en el procesador para ser decodificados y ejecutados. Un ejemplo
0x5C0B
El lenguaje ensamblador, sería
add r12,r11
Para este procesador en particular. En este caso, eso significa r11 = r11 + r12. Así que puse ese texto, el add r12, r11 en un archivo de texto y uso un ensamblador (un programa que compila / ensambla el lenguaje ensamblador) para ensamblarlo en alguna forma de binario. Como cualquier lenguaje de programación, a veces creas archivos de objetos y luego los vinculas, a veces puedes ir directamente a un binario. Y hay muchas formas de binarios que están en ascii y en formas binarias y una discusión completamente diferente.
Ahora, ¿qué puede hacer en el ensamblador que no forma parte del conjunto de instrucciones? ¿En qué se diferencian? Bueno, para empezar puedes tener macros:
.macro add3 arg1, arg2, arg3
add /arg1,/arg3
add /arg2,/arg3
.endm
.text
add3 r10,r11,r12
Las macros son como funciones en línea, no son funciones que se llaman sino que generan código en línea. No es diferente a una macro C, por ejemplo. Por lo tanto, puede usarlos para guardar algo de escritura o puede usarlos para abstraer algo que desea hacer una y otra vez y desear la capacidad de cambiar en un lugar y no tener que tocar todas las instancias. El ejemplo anterior esencialmente genera esto:
add r10,r12
add r11,r12
Otra diferencia entre el conjunto de instrucciones y el lenguaje de ensamblaje son las pseudo instrucciones, para este conjunto de instrucciones en particular, por ejemplo, no hay ninguna instrucción emergente para sacar cosas de la pila, al menos no con ese nombre, y explicaré por qué. Pero puede guardar algo de escritura y usar una ventana emergente en su código:
pop r12
La razón por la que no hay pop es que los modos de direccionamiento son lo suficientemente flexibles como para que una lectura de la dirección en el registro de origen ponga el valor en el registro de destino e incremente el registro de origen con una palabra. Que en el ensamblador para este conjunto de instrucciones es
mov @r1+,r12
El pop y el resultado de mov en el opcode 0x413C.
Otro ejemplo de las diferencias entre el conjunto de instrucciones y el ensamblador, el cambio de conjuntos de instrucciones, es algo como esto:
ldr r0,=bob
Lo que para este lenguaje ensamblador significa cargar la dirección de bob en el registro 0, no hay instrucciones para eso, lo que el ensamblador hace es generar algo que se vería así si tuviera que escribirlo en ensamblador a mano:
ldr r0,ZZ123
...
ZZ123: .word bob
Esencialmente, en un lugar accesible desde esa instrucción, no en la ruta de ejecución, se crea una palabra que el vinculador completará con la dirección de bob. La instrucción ldr igualmente por el ensamblador o enlazador se codificará con una ldr de una instrucción relativa a la PC.
Esto conduce a toda una categoría de diferencias entre el conjunto de instrucciones y el lenguaje ensamblador.
call fun
El código de máquina no tiene forma de saber qué es la diversión o dónde encontrarla. Para este conjunto de instrucciones con sus muchos modos de direccionamiento (tenga en cuenta que estoy evitando específicamente nombrar los conjuntos de instrucciones que estoy usando, ya que no es relevante para la discusión) el ensamblador o el enlazador, según sea el caso (según el lugar donde finalice la función divertida) siendo relativo a esta instrucción).
El ensamblador puede elegir codificar esa instrucción como relativa a la PC, si la función de diversión está 40 bytes adelante de la instrucción de llamada, puede codificarla con el equivalente de la llamada pc + 36 (quitar cuatro porque la PC tiene una instrucción adelante en el tiempo de ejecución) y esta es una instrucción de 4 bytes).
O el ensamblador puede no saber dónde o qué es la diversión y dejarlo en manos del vinculador, y en ese caso, puede colocar la dirección absoluta de la función algo que sería similar a la llamada # 0xD00D.
Lo mismo ocurre con las cargas y las tiendas, algunos conjuntos de instrucciones tienen parientes cercanos y lejanos de la PC, algunos tienen una dirección absoluta, etc. Y es posible que no le importe elegir, solo puede decir
mov bob,r1
y el ensamblador o enlazador o una combinación de los dos se encarga del resto.
Tenga en cuenta que para algunos conjuntos de instrucciones, el ensamblador y el enlazador pueden suceder al mismo tiempo en un programa. En estos días estamos acostumbrados al modelo de compilar objetos y luego a vincular objetos, pero no todos los ensambladores siguen ese modelo.
Algunos casos más donde el lenguaje ensamblador puede tomar algunos accesos directos:
hang: b hang
b .
b 2f
1:
b 1b
b 1f
1:
b 1b
2:
El hang: b hang tiene sentido, se bifurca a la etiqueta llamada hang. Esencialmente una rama para uno mismo. Y como su nombre lo indica, esto es un bucle infinito. Pero para este lenguaje ensamblador b. significa rama a uno mismo, un bucle infinito, pero no tuve que inventar una etiqueta, escribirla y derivarla. Otro método abreviado es usar los números b 1b significa derivar a 1 atrás, el ensamblador busca la etiqueta número 1 detrás o encima de la instrucción. El b 1f, que no es una rama a sí mismo, significa rama 1 adelante, este es un código perfectamente válido para este ensamblador. Mirará hacia adelante o debajo de la línea de código para una etiqueta número 1: Y puede reutilizar el número 1 como loco en su programa de lenguaje ensamblador para este ensamblador, ahorra en tener que inventar nombres de etiquetas para simples ramas cortas. El segundo b 1b se ramifica al segundo 1. y es una rama a sí mismo.
Es importante comprender que la compañía que creó el procesador define el conjunto de instrucciones y el código de máquina o los códigos de operación o el término que usen para los bits y bytes que el procesador decodifica y ejecuta. Muy a menudo esa compañía producirá un documento con lenguaje ensamblador para esas instrucciones, una sintaxis. A menudo, esa compañía producirá un programa ensamblador para compilar / ensamblar ese lenguaje ensamblador ... usando esa sintaxis. Pero eso no significa que cualquier otra persona en el planeta que elija escribir un ensamblador para ese conjunto de instrucciones tenga que usar esa sintaxis. Esto es muy evidente con el conjunto de instrucciones x86. Del mismo modo, cualquier instrucción de psuedo como la sintaxis de pop anterior o macro u otros atajos como el b 1b deben respetarse de un ensamblador a otro. Y muy a menudo no lo son, se ve esto con ARM, por ejemplo, el símbolo de comentario universal de; no funciona con gnu assembler, tienes que usar @ en su lugar. El ensamblador de ARM utiliza el; (note que escribo mi ensamblador de brazos con; @ para hacerlo portátil). Se pone aún peor con las herramientas gnu, por ejemplo, puedes poner cosas en el lenguaje C como #define y / * comment * / en tu ensamblador y usar el compilador de C en lugar del ensamblador y funcionará. Prefiero mantenerme lo más puro posible para la máxima portabilidad, pero naturalmente, puede elegir utilizar las funciones que ofrece la herramienta.
Cuando consulta el artículo de Wikipedia sobre el lenguaje ensamblador al que se vinculó en su pregunta, hay un ejemplo a continuación que muestra las instrucciones en lenguaje ensamblador y el código objeto correspondiente. Ambas son representaciones diferentes de lo mismo: instrucciones del conjunto de instrucciones de un procesador. Pero solo la columna con el título "Instrucción (sintaxis de AT&T)" contiene lenguaje ensamblador.
Espero que esto lo haga más claro.
El set instrucciones está compuesto por todas las instrucciones que puede ejecutar un procesador, mientras que ensamblaje es el lenguaje de programación que utiliza estas instrucciones para crear programas.
En otras palabras, el conjunto de instrucciones es solo un grupo de bytes que una CPU puede entender, pero no puede hacer nada útil con ellos (piense en las instrucciones como las letras del alfabeto) mientras ensamblar es un lenguaje que le permite combinar estas instrucciones (o letras) para hacer un programa (algo así como un discurso).
Todo está en arquitectura en capas con "interfaces estrictas (la mayoría de las veces) y bien definidas" .
Comenzar desde hardware
Hay muchas capas hasta llegar al procesador.
Capa Quiero decir que partimos de "física-> dispositivos (electrónica) -> Analógico (Amplificador) -> Puertas-> Circuitos Digitales-> Micro-Arquitectura-> Arquitectura (ISA, Procesador)
- Pero Comience desde el procesador, tiene dos partes (como la mayoría de los sistemas integrados). : Hardware y software.
Parte del software que se llama ISA (Arquitectura de conjunto de instrucciones)
Tiene todas las instrucciones que un procesador respetado puede soportar. Significa que ISA está vinculado a un solo procesador (Hardware como x86).
Lo importante es por qué se requiere esta ISA? Igual que dije anteriormente, es una interfaz estricta y bien definida. El procesador no puede ejecutar ninguna instrucción más allá de ISA [estricta]Pero cualquiera que quiera usar este procesador puede usar estos comandos de ISA para realizar su trabajo. [Interfaz bien definida]
Ahora ven a ensamblar, C, ensamblador, compilador ....
La arquitectura en capas sabe que la usamos (Layered Arch) en hardware para implementar un procesador para usted
Puedes leer más acerca de por qué esta arquitectura en capas. Es fácil tratar un gran problema paso a paso.
Igual aquí lo que queremos? ¿Cuál es nuestro objetivo?
Queremos que el usuario pueda utilizar este procesador fácilmente. Aquí el usuario es programador .
Ahora ve la dificultad para programador.
¿Puede un programador recordar todas las instrucciones para un procesador que estén en formato binario? Y el procesador puede cambiar en la próxima aplicación de Intel a IBM (no es una versión específica ahora).
- Así que aquí también tenemos arquitectura en capas [no fija].
- 1) Ensamblador - Compilador
- 2) Ensamblador
El ensamblador es también una capa de lo que tiene: dos interfaces. Lo mismo con el compilador.
Ej: Usted escribe un código en C. El procesador no puede entender este código. Entiende lo que está escrito en formato binario y definido por las instrucciones dadas en ISA. Pero es difícil escribir (mantener | modificar) un programa en instrucción en ISA.
1) Por lo tanto, el usuario escribe un código en C. Este código es comprendido por un compilador de C. Debido a que un usuario está restringido a usar solo la sintaxis dada en C. Eso significa que el compilador C proporciona una interfaz estándar y bien definida para el usuario en un extremo. En el otro y puede utilizar directamente la instrucción ISA u otra interfaz llamada "Ensamblador".
2) Ahora, si está utilizando Assembler, el compilador traducirá todos los códigos C a la sintaxis dada por Assembler. Y la sintaxis que Assembler proporciona al compilador se denomina lenguaje ensamblador. También es una interfaz bien definida y cualquiera puede usarla para programar en lenguaje ensamblador. Y en el otro extremo, el ensamblador convierte toda su sintaxis (Mnemonics | Directives, esas no están presentes en ISA) a instrucciones de código binario en ISA.
Aquí un ejemplo de esta traducción.
- En C = hola.c
- En Código de montaje = hola.s
- En código de objeto = hello.obj (Sin vinculación realizada: más información)
En este archivo, una línea es "Máquina: Micro Dispositivos avanzados X86-64" que proporciona información sobre el procesador en consecuencia, estamos usando ISA y ensamblador. Y el programador de C no es consciente de esto, es libre de codificar en C. Ese es el beneficio de la "Interfaz bien definida".
- En código de máquina = hello.binary (después de vincular: Más información)
Para comparar solo ver
hola.c (programa C)
hello.asm2bin (Tabla de archivos de objetos: mapeo directo de Mnemonics and Binary Instruction)
hello.asm2bin_exe (Tabla de archivos binarios: más mapeo después de vincular)
Verá una línea en estos archivos "Desmontaje de la sección ..." Como lo hace el ensamblador: ensambla la instrucción ISA (patrón de bits) del lenguaje ensamblador, así que aquí vemos la primera instrucción ISA y luego la desmontamos en Mnemonics.
Todos los archivos están en este enlace [Descargar y Abrir]
https://www.dropbox.com/sh/v2moak4ztvs5vb7/AABRTxl7KQlqU2EkkMkKssqYa?dl=0
- En Linux puedes usar vim, emacs para abrir estos archivos.
- En Windows, solo use vim o use la opción "Abrir-> Seleccionar un programa de ....." después de hacer clic derecho en el archivo y seleccionar el editor de texto de su elección.
Un lenguaje ensamblador es más que un superconjunto del conjunto de instrucciones: es una forma de generar archivos de objetos, símbolos, información de depuración, enlaces y también tener una programación estructurada mínima incluso en este nivel. (Construyendo un poco sobre otras respuestas / comentarios aquí)
- Diseño de archivo de objeto. Por ejemplo, secciones: código, datos, solo lectura, depuración, enlace dinámico. La directiva ''org'' común le dice al ensamblador la ubicación de las instrucciones / datos.
- Pre-procesamiento. Esto incluye macros (expansión en línea, repetición) y, a veces, programación estructurada (diseño de estructura, definición de nombres de alias para registros).
- Definición de datos. Incluyendo archivos al por mayor, o definiendo byte / palabra a la vez, por ejemplo, ".byte", ".word", ".dw" dependiendo de su arquitectura.
La mayoría de los compiladores de C generan ensamblado, que luego se pasa al ensamblador para crear archivos de objetos. Si observa la salida de gcc cuando se ejecuta con el indicador ''-S'', verá que se está utilizando la mayoría de los anteriores. Si tiene activada la función de depuración (''-g'') y algún enlace dinámico (predeterminado en estos días) verá una gran cantidad de ensamblajes que no están dedicados solo a las instrucciones.
Un lenguaje ensamblador incluirá mnemónicos para las instrucciones, pero normalmente agrega un poco más, como:
- macros
- alguna forma de definir datos
- formas de definir nombres (por ejemplo, para funciones)
Edición: una instrucción (en sí misma) se codificará en binario para que la CPU la lea. El mnemotécnico es un nombre para la instrucción. Por ejemplo, en lenguaje ensamblador podría escribir "mov ax, 1". La instrucción correspondiente para eso se codificaría (en el caso de un x86) como B8 00000001 (en hexadecimal).
La definición de datos, macros, nombres de funciones, etc., no son instrucciones reales. Una macro (como una macro en C, etc.) le permite definir nombres durante el proceso de ensamblaje. Puede (a menudo) dar como resultado la generación de algunas instrucciones, pero éstas son independientes de la definición de macro en sí. Al igual que en C, cuando define algunos datos que normalmente darán como resultado un registro en el archivo de objeto que especifica una cierta cantidad de espacio para el nombre X, pero no genera instrucciones directamente.
Una computadora (más precisamente el procesador) solo puede hacer cálculos, es decir, realizar operaciones aritméticas y lógicas.
Una sola operación aritmética o lógica se llama una instrucción .
La recopilación de todas las instrucciones se denomina conjunto de instrucciones de esa computadora (más precisamente el procesador).
El conjunto de instrucciones está cableado en el procesador o se implementa mediante una técnica llamada microcódigo .
La computadora solo podía programarse si tenía un idioma, es decir, algo que entendiera. El código binario no es el lenguaje de la computadora. El conjunto de instrucciones basado en código binario es el lenguaje de la computadora.
Un lenguaje no es más que una especificación en papel . El primer lenguaje diseñado en papel fue el lenguaje de máquina. Su implementación en computadora solo fue posible a través del hardware (o la última técnica de microcódigo). Esa implementación se llama conjunto de instrucciones. Todos los demás idiomas se diseñarán sobre el lenguaje de máquina.
Fue difícil trabajar con el lenguaje de máquina, ya que principalmente trabajamos con alfabetos en nuestra vida diaria. Por lo tanto, se decidió introducir un lenguaje mnemónico llamado Lenguaje de ensamblador sobre el lenguaje de máquina. La implementación del lenguaje ensamblador se denominó ensamblador.
[Usted puede preguntarse cómo se escribió el primer ensamblador. El primer ensamblador puede o no estar escrito en lenguaje de máquina. No menciono el concepto de arranque aquí en aras de la simplicidad]
RESUMEN:
El lenguaje ensamblador se convierte a instrucciones establecidas por el ensamblador. Y ambos son lados diferentes de una moneda con una capa de abstracción o código mnemotécnico entre ellos. El lenguaje de máquina es "codificación de bits" del conjunto de instrucciones de un procesador. El lenguaje ensamblador es la "codificación simbólica" del conjunto de instrucciones de un procesador.