1 Fundamentos Del Lenguaje Ensamblador
1 Fundamentos Del Lenguaje Ensamblador
1 Fundamentos Del Lenguaje Ensamblador
Objetivos
1. Enterarse sobre sistemas actuales con funcionalidades soportadas a bajo nivel
2. Saber sobre la evolución de los microprocesadores Intel x86 y AMD
3. Conocer diferentes plataformas de programación a bajo nivel
4. Diseñar e implementar programas simples en ensamblador
Existe un distinto Lenguaje de Máquina para cada CPU. Por ejemplo, podemos mencionar tres
lenguajes completamente diferentes, que sin embargo vienen de la aplicación de los conceptos
anteriores:
Existen muchos ensambladores como por ejemplo: Microsoft MASM el cual se ejecuta en MS-
Windows. Hay otros ensambladores muy buenos para las computadoras basadas en Intel, incluyendo
TASM (Turbo Assembler), NASM (Netwide Assembler), y el ensamblador de GNU.
1.2 Organización de la computadora
1.2.1 El Microprocesador
El microprocesador es un circuito integrado que contiene algunos o todos los elementos necesarios
para conformar una (o más) “unidad central de procesamiento” UCP, también conocido como CPU
(por sus siglas en inglés: Central Process Unit). En la actualidad este componente electrónico está
compuesto por millones de transistores, integrados en una misma placa de silicio.
Está conformado por los siguientes elementos: Memoria, Unidad Aritmetica Logica (ALU), Puertos de
Entrada y Salida (Buses), La Unidad de Control (UC) y un reloj que sincroniza su funcionamiento.
1.2.2 Buses
Buses de comunicación en un circuito impreso. En Arquitectura de computadoras, el bus es un sistema
digital que transfiere datos entre los componentes de una computadora entre computadores. Están
formado por cables o pistas en un circuito impreso, dispositivos como resistencias y condensadores
además de circuitos integrados.
La mayoría de los buses están basados en conductores metálicos por los cuales se trasmiten señales
eléctricas que son enviadas y recibidas con la ayuda de integrados que poseen una interfaz del bus
dado y se encargan de manejar las señales y entregarlas como datos útiles.
1.2.3 Registros
Los registros del procesador se emplean para controlar instrucciones en ejecución, manejar
direccionamiento de memoria y proporcionar capacidad aritmética. Los registros son espacios físicos
dentro del microprocesador con capacidad de 4 bits hasta 64 bits dependiendo del microprocesador
que se emplee. Los bits, por conveniencia, se numeran de derecha a izquierda (15,14,13…. 3,2,1,0),
los registros están divididos en seis grupos los cuales tienen un fin específico. Los registros se dividen
en:
• Registros de segmento
• Registros apuntadores
• Registro índice
• Registro de bandera.
Esta operación debe realizarse sobre algunos datos almacenados en registros de computadora o en
palabras de memoria. La manera en que eligen los operandos durante la ejecución del programa
depende del modo de direccionamiento de la instrucción. El modo de direccionamiento especifica una
regla para interpretar o modificar el campo de dirección de la instrucción antes de que se haga la
referencia real al operando.
Las computadoras utilizan técnicas de modo de direccionamiento para acomodar una o las dos
siguientes consideraciones:
La unidad de control de una computadora está diseñada para recorrer un ciclo de instrucciones que
se divide en tres fases principales:
Modo Implícito.
Modo Inmediato.
Modo De Registro.
Modo Indirecto Por Registro.
Modo De Direccionamiento Directo.
Modo De Direccionamiento Indirecto.
Modo De Direccionamiento Indexado.
Modo De Direccionamiento De Registro Base.
1.3 Interrupciones
Una interrupción es una operación que suspende la ejecución de un programa de modo que el sistema
pueda realizar una acción especial. La rutina de interrupción ejecuta y por lo regular regresa el control
al procedimiento que fue interrumpido, el cual entonces reasume su ejecución.
1.3.1 Hardware
Las interrupciones hardware, ocurren cuando un dispositivo necesita atención del procesador y
genera una señal eléctrica en la línea IRQ que tiene asignada. Esta señal es recogida y procesada
por el controlador de excepciones PIC antes de ser enviada al procesador, lo que puede realizarse de
dos formas, según el tipo de interrupción sea enmascarable o no enmascarable.
Cuando se habla de una interrupción significa que, bajo control del software, el procesador puede
aceptar o ignorar (enmascarar) la señal de interrupción. Para ello se envía una señal a la patilla
INTR, y el procesador la atiende o la ignora en función del contenido de un bit (IF) en un registro
(FLAGS) que puede estar habilitado o deshabilitado.
1.3.2 Software
Los procesadores Intel de la gama x86 y compatibles, disponen de una instrucción INT que permite
generar por software cualquiera de los 256 tipos de interrupción. El proceso seguido es exactamente
el mismo que si se recibe una interrupción hardware en la patilla INTR, salvo que en este caso se
conoce el tipo de interrupción, y no se requiere ningún ciclo INTA.
Este tipo de interrupciones son de prioridad más alta que las de hardware (enmascarables y no
enmascarables), de forma que si se recibe una interrupción hardware mientras que se ejecuta una
software, esta última tiene prioridad.
1.2 Lenguaje máquina y lenguaje ensamblador
1.2.1 Lenguaje máquina
Fue el primer lenguaje utilizado en la programación para las primeras computadoras, pero dejó de
utilizarse por su dificultad y complicación, siendo sustituido por otros lenguajes más fáciles de
aprender y utilizar, y que además reducen la posibilidad de cometer errores.
El código máquina, o lenguaje de máquina, está formado por instrucciones sencillas, que
dependiendo de la estructura del procesador pueden especificar:
El lenguaje ensamblador es un tipo de lenguaje de bajo nivel utilizado para escribir programas
informáticos y constituye la representación más directa del código máquina específico para cada
arquitectura de computadoras legible por un programador
Uso: Fue usado principalmente en los inicios del desarrollo de software, cuando aún no se contaba
con los potentes lenguajes de alto nivel.
Muchos dispositivos programables (como los microcontroladores) aun cuentan con el ensamblador
como la única manera de ser manipulados.
Fuente:http://arquitecturadelcomputadorsemestre6.blogspot.mx/2014/10/lenguaje-maquina-y-lenguaje-ensamblador.html
La principal ventaja de los lenguajes de alto nivel sobre los de bajo nivel es que son más fáciles de
leer, escribir y mantener por humanos.
Ventajas
Resultan en un código fuente más fácil de leer, escribir y mantener por los humanos. En
general, permite emplear menos líneas de código en comparación con lenguaje máquina.
Permiten escribir un código válido ejecutable en distintos tipos de máquinas y sistemas
operativos.
Emplean paradigmas de programación.
Desventajas
Son más lentos de ejecutar, siendo el código máquina más eficiente. De todas maneras esto
depende del diseño del compilador para lenguajes de alto nivel: un buen diseño produce más
eficiencia.
En algunos casos el programa resultante requiere una determinada plataforma para
ejecutarse.
Los primeros lenguajes de programación de alto nivel fueron diseñados en los 50. Actualmente
existen cientos de lenguajes de este tipo como:
Ada
BASIC
COBOL
C (algunos lo consideran de nivel medio)
C++ (algunos lo consideran de nivel medio)
Delphi
FORTRAN
Java
LISP
Modula-2
Perl
php
Prolog
Python
Visual Basic .NET
Ensambladores de una fase. Estos ensambladores leen una línea del programa fuente y
la traducen directamente para producir una instrucción en lenguaje máquina o la ejecuta si
se trata de una pseudoinstrucción. También va construyendo la tabla de símbolos a medida
que van apareciendo las definiciones de variables, etiquetas, etc.
Ensambladores de dos fases. Los ensambladores de dos fases se denominan así debido
a que realizan la traducción en dos etapas. En la primera fase, leen el programa fuente y
construyen una tabla de símbolos; de esta manera, en la segunda fase, vuelven a leer el
programa fuente y pueden ir traduciendo totalmente, puesto que conocen la totalidad de los
símbolos utilizados y las posiciones que se les ha asignado.
1.6 Estructura de un programa en ensamblador
Un programa en lenguaje ensamblador estará formado por una secuencia de sentencias. Cada
sentencia ocupa una sola línea y tiene la siguiente estructura:
Los cuatro campos de una sentencia son opcionales, si no aparece ninguno de ellos (una línea en
blanco) tendríamos una sentencia vacía.
Los archivos de código fuente escritos en lenguaje ensamblador se organizan en líneas. Cada una de
las líneas del archivo puede contener una directiva, una instrucción o ambas cosas a la vez en los
casos en que sea posible.
Todos los archivos fuente tienen que adecuarse a una estructura fija dividida en secciones.
1. .386 - Describe el modelo de CPU para el cual el código está dirigido; en este caso como
estamos haciendo el programa para x86 se puede utilizar la directiva .386. Como nota
adicional hay que poner atención en el punto inicial el cual es requerido antes de cualquier
directiva.
3. include – Tal como es utilizado en otros lenguajes, los “includes” tienen el mismo objetivo
en Ensamblador; el cual es “incluir” en el código las librerías a utilizarse. Para el caso de
Ensamblador sobre Windows (Win32) se utiliza principalmente las librerías e “includes”
relacionadas a las dll’s que conocemos son parte del Sistema Operativo, y me refiero a
windows, kernel32 y user32.
4. .data - La directiva .data se utiliza para hacer la declaración de las variables. Se puede decir
que la directiva – .data será el repositorio de las variables inicializadas del programa. Existen
otras directivas como .DATA? la cual tiene la misma función que .DATA, con la única
diferencia que ésta sirve para almacenar datos no-inicializados. De igual manera se tiene la
directiva .CONST que como puede deducirse sirve para almacenar las constantes que se
quieran utilizar en el programa.
Cada vez que generes un nuevo programa podrías utilizar la siguiente pieza de código
como plantilla:
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
. data
<variables>
.code
start:
<código>
end start
2. El paso de enlace implica convertir un módulo .OBJ en un módulo de código máquina .EXE
3. El último paso es cargar el programa para su ejecución. Ya que el cargador conoce en dónde
está el programa a punto de ser cargado, puede completar las direcciones indicadas en el
encabezado que estaban incompletas.
El editor puede ser cualquier editor de textos que se tenga a la mano, como compilador utilizaremos
el MASM (macro ensamblador de Microsoft) ya que es el más común, y como enlazador utilizaremos
el programa link.
La extensión usada para que MASM reconozca los programas fuente en ensamblador es .ASM; una
vez traducido el programa fuente, el MASM crea un archivo con la extensión .OBJ, este archivo
contiene un "formato intermedio" del programa, llamado así porque aún no es ejecutable pero
tampoco es ya un programa en lenguaje fuente. El enlazador genera, a partir de un archivo .OBJ o
la combinación de varios de estos archivos, un programa executable.
Pueden usar visual studio 2012 o 2015 aunque son algo pesado, es por esta razón que se utilizará el
Visual Masm
Aquí les dejo la página del autor, de donde lo pueden descargar http://www.visualmasm.com/, solo
es necesario bajar el visualmasm.zip los descomprimen e instalan, durante la instalación de sugerirá
en descargar el Masm32 el más reciente e instalarlo en la dirección correcta para que lo reconozca
sin ningún inconveniente
Una vez que tenemos el código asm, tenemos que obtener el obj, este paso se realiza abriendo la
ventana de comandos y escribimos lo siguientes:
Debe escribirse tal y como aparece en la línea anterior, ya que se tiene el archivo .obj debemos
obtener el ejecutable, el cual lo realizaremos con la siguiente línea
Hola_mundo.asm
.386
.model flat,stdcall
option casemap:none
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\msvcrt.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\msvcrt.lib
.data
text1 db "Hola Mundo!", 0Ah, 0 ; 0Ah =\n
.code
start:
invoke crt_printf,ADDR text1
invoke ExitProcess,0
END start
Utilizaremos librerías auxiliares que contienen macros para leer y escribir en pantalla
include c:\masm32\include\msvcrt.inc
includelib c:\masm32\lib\msvcrt.lib
Abrimos la consola
Fuente: https://es.wikipedia.org/wiki/Anexo:Ejemplos_de_implementaci%C3%B3n_del_%C2%ABHola_mundo%C2%BB