ENSAMBLADOR
FAMILIA INTEL X86 (8086)
1º PARTE
* INTRODUCCION:El ensamblador, es un lenguaje de programación de bajo nivel muy apegado a la maquina.
Hoy en dia, algunas empresas de antivirus y videojuegos, siguen programando pequeñas rutinas en ensamblador por su rapidez y apegamiento al computador. Esto es debido, a que un programa en ensamblador, es ejecutado casi directamente por el computador, ya que hablan casi "el mismo idioma".
Programar en ensamblador, es un oficio minucioso de artesanía... seria como el carpintero de lapiz en oreja que va al bosque, tala el árbol, lo lleva al taller, lo pule, lima, da forma y saca el mueble.
Conocer algunos conceptos básicos del lenguaje ensamblador creo que es esencial para cualquier informático... acabado este pequeño curso, sabrán un poco mas, y tendrán otra visión de como funciona internamente un lenguaje de programación.
* INTEL 8086 Y 8088Los intel 8086 y 8088 son dos microprocesadores creados en el año 1978 de 16 bits.
Pueden encontrar mas información sobre ellos en el siguiente enlace:
You are not allowed to view links.
Register or
LoginEn una primera instancia comenzaremos trabajando con este modelo de 8 y 16 bits de memoria, empleando sus segmentos, registros...
* TURBO ASSEMBLERSera el programa que vamos a utilizar. Pueden descargarlo de el siguiente enlace:
You are not allowed to view links.
Register or
LoginLa instalación es sencilla, pueden ver aqui los pasos:
You are not allowed to view links.
Register or
LoginYou are not allowed to view links.
Register or
LoginYou are not allowed to view links.
Register or
LoginYou are not allowed to view links.
Register or
LoginSi todo sale bien, tendremos en INICIO > TODOS LOS PROGRAMAS > instalado el BORLAND TASM.
* NUESTRO PRIMER PROGRAMAPara crear nuestro primer programa, emplearemos el bloc de notas, aunque mas adelante pueden descargarse si quieren otro editor como el notepad++ que la verdad esta bastante bien.
- Abrimos el block de notas y tecleamos el siguiente codigo:
.model tiny
.stack
.data
Message db "hola$"
.code
start:
mov dx,OFFSET Message
mov ax, SEG Message
mov ds,ax
mov ah,9
int 21h
mov ax,4C00h
int 21h
END startYou are not allowed to view links.
Register or
LoginA continuación, hacemos clic en ARCHIVO > GUARDAR COMO y vamos a la ruta siguiente C:\TASM\BIN\ y lo guardamos como nombre.asm (en mi caso prc1.asm)
You are not allowed to view links.
Register or
LoginHasta aquí, tenemos el código en ensamblador ya escrito. Ahora solo nos falta crear el .obj y linkarlo para obtener el .exe
Lo que haremos siempre que vayamos a general el .exe de algún código .asm sera lo siguiente:
- INICIO > EJECUTAR > CMD (se nos abrira la consola msdos)
- (Vamos a la ruta TASM/BIN). En mi caso, para llegar are:
cd..
cd..
cd tasm
cd binYou are not allowed to view links.
Register or
Login- Ahora que estamos en el directorio donde tenemos nuestro codigo, (el prc1.asm) pasaremos a crear el .obj y linkarlo. Para ello usaremos los comandos:
tasm prc1
tlink prc1Si todo sale bien y no se produce ningun error, nos mostrara los mensajes de la imagen:
You are not allowed to view links.
Register or
LoginAhora, ya tenemos generado nuestro prc1.exe
Sin cerrar la ventana del dos, escriban prc1 y se ejecutara el programa. Les mostrara por pantalla el mensaje ("hola") que habíamos escrito.
You are not allowed to view links.
Register or
Login:) Ya tenemos nuestro primer programa en ensamblador!!
2º PARTE
Ahora que tenemos nuestro programa, vamos a pasar a ver que es todo eso que hemos escrito. Puede que al principio les resulte un poco lioso el tema de los bits, los segmentos... etc. Intentare explicar tan solo lo mas importante y de la forma mas entendible que me sea posible. Mas adelante profundizaremos mas en algunas cosas que por ahora tan solo are mención.
* RECORDANDO EL BINARIOAntes de pasar a ver lo que es el lenguaje ensamblador en 80x86, vamos a recordar como se representan los números en una CPU.
La CPU es la Unidad Central de Proceso dentro de un microprocesador, tal informaron en la CPU se representa en binario, usando base 2. Un bit, es el elemento que representa el elemento basico unidad. Asi tenemos:
1 nibble > 0000 > 4 bits
1 byte > 0000 0000 > 8 bits o 2 nibbles
1 word > 0000 0000 0000 0000 > 16 bits, 2 bytes o 4 nibbles.
* REGISTROSLos registros son los principales elementos de almacenamiento de la CPU. En INTEL, existen tres tamaños de registros:
De 8 bits.
De 16 bits.
De 32 bits para versiones superiores al 386.
Además, se especifican 4 tipos de registros básicos y registros de control.
- REGISTROS DE PROPOSITO GENERAL:Son cuatro registros de propósito general:
AX – acumulador
BX – base
CX – contador
DX – datos
Estos registros son de 16 bits, que se dividen en registros de 8 bits etiquetados como AH que contiene el byte alto y AL que contiene el byte bajo. A partir del 386 hay registros de 32 bits que conservan el mismo nombre y una E que le precede, esto seria EAX. Estos registros se pueden usar indistintamente como AL, AH, AX y EAX.
- REGISTROS DE INDICE Y REGISTROS DE PILA:Los registros de indice son de 16 bits, tambien llamados registros de punteros. Los registros de control de pila, BP y SP se usan cuando manejamos una pila (snack). Estos registros les veremos mas adelante...
- REGISTOS DE SEGMENTOS Y OFFSET:En los orígenes del 80x86 se pensó que nadie usaría mas de 1 MByte de memoria, tal que los primeros micros no permitían direccionar mas allá de este numero, es decir, se utilizan 20 bits de direcciones, tal que si queremos mas direccionamiento se podrian usar 2 registros de 16 bits. Esto da un numero binario de 32 bits. Sin embargo, esto es demasiado, por eso se crearon los segmentos y el desplazamiento (offset). Este modo de operación es el denominado modo real y se genero de la siguiente manera:
Dos registros de 16 bits, uno que contiene el segmento y otro el offset. Generan una dirección fisica de 20 bits, para ello, se colocan en posición tal que el registro segmento se mueve 4 posiciones a la izquierda y el offset a la derecha, también 4 posiciones dejando 4 bits a 0 respectivamente. Si se unen, se suman los 2 registros y se obtiene una dirección de 20 bits que nos da la dirección física en memoria.
Por ahora dejaremos esto aqui. Cuando trabajen con los segmentos y los offset entenderán mejor esto que les acabo de contar.
* ENTENDIENDO UN POCO MEJOR NUESTRO PROGRAMAMuestro a continuación nuestro programa:
.model tiny
.stack
.data
Message db "hola$"
.code
start:
mov dx,OFFSET Message
mov ax, SEG Message
mov ds,ax
mov ah,9
int 21h
mov ax,4C00h
int 21h
END startIremos viéndolo linea a linea:
.model tinyEs la directiva de modelo de programación. Por ahora comenzaremos siempre el programa asi.
.stackEs la directiva de asignacion de segmento. Por ahora siempre lo escribiremos.
.dataEs la directiva de asignacion de datos, a partir de aqui, asignaremos las variables que vayamos a utilizar, que en nuestro caso es una:
Message db "hola$"Message contiene el mensaje que mostraremos en pantalla. El simbolo del dolar ($) indica el fin de la cadena, y siempre deberemos de tenerlo.
.codeEs la directiva para el segmento de codigo.
start:Indica el inicio del programa.
mov dx,OFFSET Message
mov ax, SEG MessageLa instruccion mov funciona de la siguiente forma:
mov destino, origen
De esta forma, moveremos a dx el offset de mensaje, y a ax el segmento de mensaje. Ya iran entendiendo el porque de todo esto.
mov ds,axDS:DX apunta al mensaje.
Hasta este punto podemos quedarnos con el siguiente concepto:
mov dx,OFFSET Message
mov ax, SEG Message
mov ds,axque estas tres lineas de codigo, "sirven para guardar nuestro mensaje y posteriormente pueda ser mostrado.
Continuemos;
mov ah,9
int 21hEntra en juego una INSTRUCCION, en este caso, la instruccion 21h.
La int 21h, sirve para "mostrar cosas por pantalla". Para que funcione, es necesario que en AH este el numero de la funcion a llamar. En nuestro caso, para mostrar nuestro mensaje deberemos pasar a AH la función numero 9, por eso, antes de invocar la instruccion 21h, hacemos un mov ah,9.
mov ax,4C00h
int 21hEs la instrucción de comparación para volver al DOS. De momento no veremos mas de estas dos lineas, pero las incluiremos siempre al final de nuestro codigo.
END startFin
Con esta breve explicación, es mas que suficiente por ahora. Pasemos ahora a ver unos cuantos ejemplos de programas en ensamblador, que a base de practicar es como mejor se aprende.
3º PARTE
* PRACTICASPRACTICA 1:Crearemos un programa que nos muestre dos mensajes por pantalla. Abra que incluir un salto de linea entre ambos mensajes.- Este programa es similar al programa de ejemplo que vimos en el 1º capitulo, pero en esta ocasión tenemos que crear dos mensajes y poner un salto de linea.
Comenzaremos nuestro código como casi siempre aremos, definiendo en .data los mensajes:
.model tiny
.stack
.data
Mensaje1 db "estoy aqui",10,13,"$"
Mensaje2 db "ahora salte$"
.codeEn el Mensaje1, aparece entre la cadena y el dolar ($) un "10,13". Esto indica salto de linea. Seria como un "<<endl;" en C++, o mas claro, como si pulsásemos el INTRO en el M.Word.
A continuación, mostramos los dos mensajes como ya sabemos, dentro del start:
start:
mov dx,OFFSET Mensaje1
mov ax, SEG Mensaje1
mov ds,ax
mov ah,9
int 21h
mov dx,OFFSET Mensaje2
mov ax, SEG Mensaje2
mov ds,ax
mov ah,9
int 21h
mov ax,4C00h
int 21h
END startComo vemos, tenemos las dos partes de codigo iguales (una para mostrar cada mensaje) y despues el 4C00h para cerrar bien el programa.
Con esto, ya tendriamos creada nuestra 2º practica. El codigo final seria este:
.model tiny
.stack
.data
Message db "hola",10,13,"$"
Message2 db "salto$"
.code
start:
mov dx,OFFSET Message
mov ax, SEG Message
mov ds,ax
mov ah,9
int 21h
mov dx,OFFSET Message2
mov ax, SEG Message2
mov ds,ax
mov ah,9
int 21h
mov ax,4C00h
int 21h
END start
PRACTICA 2:En la siguiente practica crearemos un programa que nos detecte una tecla pulsada y nos la muestre:
Comenzaremos de la misma forma de siempre:
.model tiny
.stack
.data
Teclea db "Teclea una letra: $"
.codeSeguimos con el start y mostrando nuestro mensaje por pantalla:
start:
mov dx,OFFSET Teclea
mov ax, SEG Teclea
mov ds,ax
mov ah,9
int 21h
Ahora, tenemos que leer una pulsación de teclado. Para ello, existe otra instrucción que es la "int 16h". Para que la instrucción 16h lea un carácter de pantalla, en AH tiene que haber 0. El codigo ascii de la tecla pulsada, se almacena en AL. Podéis ver mas sobre esta instrucción en el siguiente enlace: You are not allowed to view links.
Register or
Login aunque mas adelante iran saliendo ejemplos diferentes y veremos mas de ella.
Por lo tanto, la complejidad de leer una pulsación teclado radica en meter un 0 en AH, invocar la instruccion 16h, y la pulsación quedara almacenada en AL (posteriormente la usaremos)
El codigo es este:
xor ah,ah
int 16hAH por defecto tendra un valor desconocido, lo que es igual a basura. Para meten en AH un 0, tenemos 2 opciones.
1º: hacer un mov ah,0 (para dejar en ah un 0)
2º: hacer un XOR de ah,ah para dejar 0 en AH. Esta es la manera mas pulcra de dejar a 0 cualquier variable. Si saben algo de puertas lógicas lo entenderán. La puerta XOR, tambien llamada oexcluiva, mirando su tabla de la verdad, vemos que cuando en A tenemos lo mismo que en B, el resultado sera 0. Para quien le quede dudas, puede ver la tabla de verdad de la puerta XOR en: You are not allowed to view links.
Register or
LoginPues bien, despues del xor ah,ah, tendremos un 0 en ah, de esa forma ahora llamamos a int 16h y nos guardara una tecla pulsada.
Después de que el usuario puse la tecla, dijimos que quedaba almacenada en AL.
Ahora, para poder mostrar ese carácter pulsado, y que esta almacenado en AL tenemos que hacer lo siguiente:
mov dl,al
mov ah,02h
int 21hPara mostrar un carácter, usaremos la misma instrucción que para mostrar una cadena. La instrucción 21h (int 21h), pero no es lo mismo mostrar un mensaje que un caracter.
Para mostrar un carácter con la instrucción 21h deberemos hacer lo siguiente:
- Meter en AH el numero (la función) 02h (mostrar un solo caracter)
- La función 02h muestra el carácter que este en DL, por lo tanto, mover el dato a mostrar a DL.
Por esta razón que en el código moviese a dl el valor de al, y luego en ah metiese el 02h. Luego llamando a int 21h nos muestra el caracter.
Finalizamos el codigo asi:
mov ax,4C00h
int 21h
END startAqui tenemos el algoritmo completo de nuestra 2º practica:
.model tiny
.stack
.data
Teclea db "Teclea una letra: $"
.code
start:
mov dx,OFFSET Teclea
mov ax, SEG Teclea
mov ds,ax
mov ah,9
int 21h ;hasta aquí mostramos el mensaje
xor ah,ah ;con esto pongo ah en 0
int 16h ;detectar una pulsacion
mov dl,al ;estas tres lineas nos permiten mostrar el caracter de pantalla
mov ah,02h
int 21h
mov ax,4C00h
int 21h
END start* Se me habia olvidado decir hasta ahora, que para los comentarios en ensamblador se usa el "punto y coma" (;)
Mañana mas ejemplos y programas.... ;)