Ensamblador (y ligador) a utilizar
Ensamblador. El lenguaje ensamblador es un lenguaje de bajo
nivel que se comunica directamente con el hardware de la máquina. El termino
ensamblador se refiere a un tipo de
programa informático que
se encarga de
traducir un fichero
fuente escrito en un
lenguaje ensamblador, a
un fichero objeto
que contiene código
máquina, ejecutable directamente
por el microprocesador.
El programa lee el fichero escrito en lenguaje ensamblador y sustituye cada uno de los códigos nemotécnicos que aparecen por su código de operación correspondiente en sistema binario para la plataforma que se eligió como destino en las opciones especificas del ensamblador.
Enlazador: es parte del proceso de ejecución, convierte el código máquina y enlaza losdistintos módulos del programa.
Características
- El código escrito en lenguaje ensamblador posee una cierta dificultad de ser entendido ya que su estructura se acerca al lenguaje máquina, es decir, es un lenguaje de bajo nivel.
- El lenguaje ensamblador es difícilmente potable, es decir, un código escrito para un microprocesador, puede necesitar ser modificado, para poder ser usado en otra máquina distinta.
- Con el lenguaje ensamblador se tiene un control muy preciso de las tareas realizadas por un microprocesador por lo que se pueden crear segmentos de código difíciles y/o muy ineficientes de programar en un lenguaje de alto nivel, ya que, entre otras cosas, en el lenguaje ensamblador se dispone de instrucciones del CPU que generalmente no están disponibles en los lenguajes de alto nivel.
Podemos distinguir entre dos tipos de ensambladores:
Ensambladores modulares: 32 bits o de alto nivel, son
ensambladores que aparecieron como respuesta a una nueva arquitectura de
procesadores de 32 bits, muchos de ellos teniendo compatibilidad hacia atrás
pudiendo trabajar con programas con estructuras d 16bits.
Ensambladores básicos:
Son de muy bajo nivel, y su tarea consiste básicamente en ofrecer nombres
simbólicos a las distintas instrucciones y parámetros.
Un ligador es un programa que enlaza todos los programas o
módulos obteniendo lo que denominamos
programa ejecutable, es un
programa que enlaza
distintos módulos o programas que poseen subprogramas, además
incorporan las denominadas rutinas de librerías en caso de solicitarlas el
propio programa.
Sus principales funciones son:
Enlazar código intermedio compilado independientemente en un
solo módulo de carga resolviendo
las diferencias entre Tokens, es
reducir procedimientos traducidos
por separado y enlazarlos para
que se ejecuten como una unidad llamada programa binario ejecutable.
Ciclos numéricos
Un ciclo, conocido también como iteración, es la
repetición de un proceso un cierto número de veces hasta que alguna condición
se cumpla. En estos ciclos se utilizan los brincos condicionales basados en el estado de la bandera.
Los ciclos numéricos que se utilizan son los
siguientes: instrucción mp,
instrucción loop, instrucción cmp,
instrucción cmps e instrucción de
conteo.
INSTRUCCIÓN JMP
Es una instrucción basada comúnmente para la transferencia de
control, un salto es incondicional "ya que la operación transfiere el
control bajo cualquier circunstancia. También vacía el resultado de la
instrucción previamente procesada: por lo que un programa con muchas
operaciones de saltos puede perder velocidad de procesamiento, el formato
general para la instrucción JMP Es:
[Etiqueta] |JMP| (Dirección corta, cercana o lejana)
Instrucción LOOP
La instrucción LOOP
requiere un valor inicial en el
registro CX, en cada iteración, LOOP de
forma automática disminuye 1 de CX.
Si el valor en el CX es cero, el control pasa a la
instrucción que sigue; si el valor en
el CX no es cero, el control pasa a la
dirección del operando.
La distancia debe ser un salto corto, desde
-128 hasta +127 bites. Para una operación que exceda este límite, el
ensamblador envía un mensaje como un salto relativo fuera de rango. El formato
general de la instrucción LOOP
Instrucción
CMP
La instrucción CMP
por lo común es utilizada para comparar dos campos de datos, uno de los
cuales están contenidos en un registro. El formato general para el CMP es:
[Etiqueta]
CMP {registro / memoria},
{registro / memoria / inmediato}
Instrucción
CMPS
CMPS compara
el contenido de una localidad de memoria (direccionada por el DS; SI),
dependiendo de la bandera de dirección, CMPS incrementa o disminuye también los
registros SI y DI en 1 para bytes, en “para palabras " en 4 para palabras
dobles. La operación establece las banderas
AF, CF, OF, PF, SF, y ZF.
Instrucción
de conteo
Se
utilizan para decrementar o incrementar el contenido de los contadores:
DEC:
esta operación resta 1 al operando destino y almacena el nuevo valoren el
mismo operando.
INC:
la instrucción suma 1 al operando del destino y guarda el resultado en el
mismo operando destino.
Son
utilizadas para transferir el flujo del proceso al operando indicado.
JLE:
salta si es menor o igual o salta si no es más grande. El salto se
realiza si ZF =1 o si SF es diferente a OF.
JC:
salta si hay acarreo. El salto se
realiza si CF= 1
JE: salta si es igual o salta si
es cero, el salto se realiza si ZF esta activada.
Tipos de Ciclos
LOOP (bucle).
Sintaxis:
LOOP desplazamiento
Indicadores:
Decrementa el registro contador CX; si CX es cero, ejecuta la siguiente
instrucción, en caso contrario transfiere el control a la dirección resultante
de sumar a IP + desplazamiento. El desplazamiento debe estar comprendido entre
-128 y +127.
Ejemplo:
MOV CX,10
BUCLE:.......
.......
LOOP BUCLE
Con las mismas
características que la instrucción anterior:
LOOPE/LOOPZBucle si
igual, si cero. Z=1 y CX<>0
LOOPNE/LOOPNZ Bucle
si no igual, si no cero. Z=0 y CX<>0
TITLE P08LOOP (COM)
Ilustración de LOOP
.MODEL SMALL
.CODE
ORG
100H
MAIN
PROC
NEAR
MOV
AX,01
;Iniciación de AX,
MOV
BX,01
;BX y
MOV
CX,01
;CX a 01
MOV
CX,10
;Iniciar
A20:
;Número de
iteraciones
ADD
AX, 01
;Sumar 01 a AX
ADD
BX, AX
;Sumar AX a BX
SHL
DX, 1
;Multiplicar por
dos a DX
LOOP
A20
;Iterar si es
diferente de cero
MOV
AX, 4C00H
;Salida a DOS
MAIN ENDP
END
MAIN
Captura básica de cadenas
Dentro del lenguaje ensamblador no existe el tipo de dato
cadena (string en otros lenguajes), por lo que para utilizarla es necesario
tratar a las cadenas como un conjunto de caracteres reservados bajo el nombre
de una sola variable.
El lenguaje ensamblador cuenta con instrucciones que por su
naturaleza sirven para el manejo de cadenas, estas son:
MOVSB:
Mueve un byte desde una localidad de memoria hasta otra.
MOVSW:
Mueve una palabra desde una localidad de memoria hasta otra.
LODSB:
Carga en la parte baja del registro acumulador (AL) el valor
de la localidad de memoria determinada por DS:SI.
LODSW:
Carga en el registro acumulador (AX) el valor de la
localidad de memoria determinada por DS:SI.
Ejemplo:
Comparación y prueba
La comparación y prueba son instrucciones especiales con las
que cuenta el microprocesador, estas son CMP y TEST respectivamente.
Comparación (CMP):
Esta instrucción compara los dos valores que se le den como
parámetros y modifica las banderas de signo (SF), de cero (ZF) y de acarreo
(CF) según sea necesario.
Ejemplo:
CMP ah,10h: Compara el valor almacenado en el registro
ah con el valor 10 hexadecimal.
Prueba (TEST):
Verifica que los valores que se le introduzcan como
parámetros sean iguales relizando la operación lógica AND, no almacena ningún
resultado pero modifica banderas según sea necesario.
Ejemplo:
TEST al, 1: Verifica que el valor almacenado en al sea
1.
Saltos.
Los saltos
son instrucciones que permiten al programador cambiar el orden de ejecución del
programa según sea necesario, dentro de ensamblador existen dos tipos de salto
principales: condicionales e incondicionales.
Saltos
Incondicionales:
Los saltos
incondicionales se utilizan mediante la instrucción JMP, la cual transfiere el
control a la línea especificada después de la palabra JMP, la cual puede ser un
valor directo o una etiqueta.
También se
puede contar como un salto incondicional la instrucción CALL, la cual llama una
procedimiento y al terminarla devuelve el control a la línea siguiente de donde
se inicio la llamada a procedimiento, pero eso se ve con más detalle en la
sección 3.1.
Ejemplo:
·
Salto: Etiqueta a la que se hará referencia para el
salto incondicional.
·
JMP Salto: Instrucción que indica que el flujo del
programa continuara desde la ubicación de la etiqueta Salto.
Saltos
Condicionales:
Los saltos
condicionales transfieren el control del programa a la ubicación que se les dé
como parámetro si al hacer una comparación se cumple la condición establecida
en el salto, los saltos condicionales son los siguientes:
JA
(Jump if Above):
Salta cuando
el valor es superior, su condición es equivalente al salto JNBE (Jump if Not
Below or Equal).
JAE
(Jump if Above or Equal):
Salta cuando
el valor es superior o igual, su condición es equivalente al salto JNB (Jump if
Not Below).
JB
(Jump if Below):
Salta cuando
el valor es menor, su condición es equivalente al salto JNAE (Jump if Not Above
or Equal).
JBE
(Jump if Below or Equal):
Salta cuando
el valor es menor o igual, su condición es equivalente al salto JNA (Jump if
Not Above).
JE
(Jump if Equal):
Salta cuando
el valor es igual.
JZ
(Jump if Zero):
Salta cuando
el valor es cero.
JNE
(Jump if Not Equal):
Salta cuando
el valor no es igual.
JNZ
(Jump if Not Zero):
Salta cuando
el valor no es cero.
JG
(Jump if Greater):
Salta cuando
el valor es mayor, su condición es equivalente al salto JNLE (Jump if Not Less
or Equal).
JGE
(Jump if Greater or Equal):
Salta cuando
el valor es mayor o igual, su condición es equivalente al salto JNL (Jump if
Not Less).
JL
(Jump if Less):
Salta cuando
el valor es menor, su condición es equivalente al salto JNGE (Jump if Not
Greater or Equal).
JLE
(Jump if Less or Equal):
Salta cuando
el valor es menor o igual, su condición es equivalente al salto JNG (Jump if
Not Greater).
Ejemplo:
·
Salto: Etiqueta a la que se hará referencia para el
salto condicional.
· CMP al, bl: Comparación entre el valor almacenado en al y
el almacenado en bl.
· JG Salto: Instrucción que indica que el flujo del
programa continuara desde la ubicación de la etiqueta Salto si el valor de al
es mayor al de bl.
Ciclos condicionales.
Dentro de la
programación existen ocasiones en la que es necesario ejecutar una misma
instrucción un cierto número de veces, el cual no siempre es conocido por el
programador o puede cambiar durante la ejecución del programa, para lo que
existen los ciclos condicionales, los cuales una vez se cumpla la condición que
tienen establecida, dejaran de ejecutarse como ciclo y permitirán que el
programa continúe con su flujo normal.
En ensamblador no
existen de forma predefinida estos ciclos, pero pueden crearse haciendo uso de
los saltos incondicionales, generando ciclos que se repetirán hasta que se
cumpla la condición definida por el programador.
Ejemplo:
·
mov
al, 0: Asigna
el valor cero al registro al.
·
ciclo: Etiqueta a la que se hará
referencia para el ciclo condicional.
·
INC
al: Aumenta
en 1 el valor del registro al.
·
CMP
al, bl : Comparación
entre el valor almacenado en al y el almacenado en bl.
·
JL
ciclo: Instrucción
que indica que el flujo del programa continuara desde la ubicación de la
etiqueta ciclo si el valor de al es menor al de bl.
Incremento y decremento.
En ensamblador
existen dos instrucciones que cumplen con el propósito de aumentar o reducir el
valor contenido dentro de un registro.
INC:
Incrementa
en uno el valor contenido dentro del registro que se le dé como parámetro.
INC al: Aumenta en 1 el valor del registro al.
DEC:
Reduce en
uno el valor contenido dentro del registro que se le dé como parámetro.
DEC al: Reduce en 1 el valor del registro al.
Captura de cadenas con formato.
El capturar
cadenas con formato permite el movimiento, comparación o búsqueda rápida entre
bloques de datos, las instrucciones son las siguientes:
MOVC:
Esta
instrucción permite transferir un carácter de una cadena.
MOVW:
Esta
instrucción permite transferir una palabra de una cadena.
CMPC:
Este comando
es utilizado para comparar un carácter de una cadena.
CMPW:
Esta
instrucción es utilizada para comparar una palabra de una cadena.
SCAC:
Esta
instrucción permite buscar un carácter de una cadena.
SCAW:
Esta
instrucción se utiliza para buscar una palabra de una cadena.
LODC:
Esta
instrucción permite cargar un carácter de una cadena.
LODW:
Esta
instrucción es utilizada para cargar una palabra de una cadena.
STOC:
Esta
instrucción permite guardar un carácter de una cadena.
STOW:
Esta
instrucción es utilizada para guardar una palabra de una cadena.
Instrucciones aritméticas.
Dentro de
ensamblador se pueden llevar a cabo las 4 instrucciones aritméticas básicas,
cada una de ellas cuenta con su propia función:
Instrucción
de Suma ADD:
Suma los operandos
que se le dan y guarda el resultado en el primer operando.
Ejemplo
·
ADD
al, bl: Suma
los valores guardados en los registros al y bl, almacenando el resultado en al.
Instrucción
de Resta SUB:
Resta el primer
operando al segundo y almacena el resultado en el primero.
Ejemplo:
·
SUB
al, bl: Resta
el valor de AL al de BL y almacena el resultado en AL.
Instrucción
de multiplicación MUL:
Multiplica el
contenido del acumulador por el operando, a diferencia de los métodos
anteriores, solo es necesario indicar el valor por el que se multiplicará, ya
que el resultado siempre es almacenado en el registro AX.
Ejemplo:
·
MUL
DX: Multiplica
el valor del registro acumulador (AX) por el de DX.
Instrucción
de división DIV:
Divide un numero
contenido en el acumulador entre el operando fuente, el cociente se guarda en
AL o AX y el resto en AH o DX según el operando sea byte o palabra
respectivamente. Es necesario que DX o AH sean cero antes de la operación por
lo que es necesario utilizar el ajuste de división antes del la instrucción
DIV.
Ejemplo:
·
AAM: Ajuste ASCII para la división.
·
DIV
bl: Instrucción
que divide los valores en ax y bl.
.COMMENT
Programa: PushPop.ASM
Descripción: Este programa demuestra el uso de las instrucciones para el manejo de la pila, implementando la instrucción XCHG con Push y Pop
Manipulación de la pila.
La pila es un grupo de localidades de memoria que se reservan para
contar con un espacio de almacenamiento temporal cuando el programa se está
ejecutando.
La pila es una estructura de datos del tipo
LIFO (Last In First Out), esto quiere decir que el último dato que es introducido en ella, es el primero que saldrá al sacar datos de la pila.
Para la manipulación de la pila ensamblador cuenta con dos
instrucciones especificas, las cuales son las siguientes:
Push:
Esta instrucción permite almacenar el contenido del operando
dentro de la última posición de la pila.
Ejemplo:
Push ax El valor contenido en ax es almacenado en el
último espacio de la pila.
Pop:
Esta instrucción toma el último dato almacenado en la pila y lo
carga al operando.
Ejemplo:
Pop bx El valor contenido en el último
espacio de la pila se almacena en el registro
El siguiente ejemplo muestra
como implementar la instrucción XCHG por medio de las instrucciones Push y Pop.
Recuerde que la instrucción XCHG intercambia el contenido de sus dos
operandos.
Programa: PushPop.ASM
Descripción: Este programa demuestra el uso de las instrucciones para el manejo de la pila, implementando la instrucción XCHG con Push y Pop
Obtención de cadena con representación decimal.
En este modo, los datos son
proporcionados directamente como parte de la instrucción.
Ejemplo:
Mov AX,34h ;
Copia en AX el número 34h hexadecimal Mov CX,10 ;
Copia en CX el número 10 en decimal
.COMMENT
Programa: PushPop.ASM
Descripción: Este programa demuestra el uso de las instrucciones para el manejo de la pila, implementando la instrucción XCHG con Push y Pop
MODEL tiny
.CODE
Copia en AX el número 34h hexadecimal Mov CX,10 ;
Copia en CX el número 10 en decimal
.COMMENT
Programa: PushPop.ASM
Descripción: Este programa demuestra el uso de las instrucciones para el manejo de la pila, implementando la instrucción XCHG con Push y Pop
MODEL tiny
.CODE
Inicio: ;Punto de entrada al
programa
Mov AX,5 ;AX=5
Mov BX,10 ;BX=10
Push AX ;Pila=5
Mov AX,BX ;AX=10
Pop BX ;BX=5
Mov AX,4C00h ;Terminar programa y salir al DOS
Push AX ;Pila=5
Mov AX,BX ;AX=10
Pop BX ;BX=5
Mov AX,4C00h ;Terminar programa y salir al DOS
Int 21h ;
END Inicio
END
END Inicio
END
Instrucciones lógicas.
Ensamblador
cuenta con un grupo de cuatro instrucciones lógicas a nivel de bit, las cuales
con excepción de la primera requieren de dos operandos, estas son las
siguientes:
NOT:
La instrucción NOT o negación
requiere un solo operando y su función es cambiar el estado de los bits del mismo,
es decir, cambiar los ceros por unos y los unos por ceros.
Ejemplo:
NOT ax Se aplica la
negación al valor del registro ax.
AND:
Esta instrucción también conocida
como producto lógico requiere de dos operandos y su valor será igual a uno
cuando los bits que se comparen ambos sean uno.
Ejemplo:
AND ax,bx Se aplica el
producto lógico a los valores de ax y bx.
OR:
La instrucción OR también
conocida como suma lógica requiere de dos operandos y su valor será uno si
alguno de los bits que compara es uno.
Ejemplo:
OR ax,bx Se aplica la suma lógica
a los valores de ax y bx.
XOR:
La instrucción XOR o suma lógica
exclusiva requiere dos operandos, los cuales se comparan y el resultado
obtenido es uno cuando uno de los bits es uno y el otro cero.
Ejemplo:
XOR ax,bx
Se aplica la instrucción XOR a los valores de ax y bx.
Desplazamiento y rotación.
Las instrucciones de desplazamiento son cuatro: shl, shr, sar y
sal; y su objetivo es desplazar los bits de uno operando un determinado número
de posiciones a la izquierda o a la derecha. La estructura de los operandos
manejados por estas instrucciones y su significado es idéntico para las cuatro
instrucciones.
·
SHL (Shift Left = desplazamiento a la izquierda)
Se desplazan a la izquierda los bits del operando destino
tantas posiciones como indique el operando fuente. El desplazamiento de una
posición se realiza de la siguiente forma: el bit de mayor peso del operando se
desplaza al bit CF del registro de estado, el resto de los bits se desplazan
una posición hacia la izquierda, y la posición de menor peso se rellena con un
0
·
SAL (Shift Arithmetic Left = desplazamiento
aritmético a la izquierda)
El objetivo de un desplazamiento aritmético a la izquierda
es multiplicar un operando, interpretado con signo, por una potencia de 2.
Para llevar a cabo este tipo de desplazamiento, hay que desplazar
los bits del operando hacia la izquierda introduciendo ceros por su derecha.
Nota: En realidad, este tipo de
desplazamiento es idéntico al llevado a cabo por la instrucción shl; por tanto,
sal y shl son de hecho la misma instrucción y se codifican con el mismo código
máquina.
·
SHR (Shift Right =
desplazamiento a la derecha)
La instrucción shr funciona de la misma forma
que shl, pero desplazando los bits a la derecha en lugar de a la izquierda.
·
SAR (Shift Arithmetic Right =
desplazamiento aritmético a la derecha)
Obtención de una cadena con la representación hexadecimal.
Esta
instrucción desplaza los bits del operando destino a la derecha tantos bits
como indique el operando fuente. Esta forma de funcionamiento es similar a la
de la instrucción shr; sin embargo, ambas instrucciones se diferencian en que
sar, en vez introducir ceros por la izquierda del operando, replica el bit de
mayor peso (bit de signo) en cada desplazamiento.
Obtención de
una cadena con la representación hexadecimal La conversión entre numeración
binaria y hexadecimal es sencilla. Lo primero que se hace para una conversión
de un número binario a hexadecimal es dividirlo en grupos de 4 bits, empezando
de derecha a izquierda. En caso de que el último grupo (el que quede más a la
izquierda) sea menor de 4 bits se rellenan los faltantes con ceros. Tomando
como ejemplo el número binario 101011 lo dividimos en grupos de 4 bits y nos
queda: 10; 1011 Rellenando con ceros el último grupo (el de la izquierda):
0010; 1011 después tomamos cada grupo como un número independiente y
consideramos su valor en decimal: 0010 = 2; 1011 = 11 Pero como no podemos
representar este número hexadecimal como 211 porqué sería un error, tenemos que
sustituir todos los valores mayores a 9 por su respectiva representación en
hexadecimal, con lo que obtenemos: 2BH (Donde la H representa la base
hexadecimal) Para convertir un número de hexadecimal a binario solo es
necesario invertir estos pasos: se toma el primer dígito hexadecimal y se
convierte a binario, y luego el segundo, y así sucesivamente hasta completar el
número.
La
conversión entre numeración binaria y hexadecimal es sencilla. Lo primero que
se hace para una conversión de un número binario a hexadecimal es dividirlo en
grupos de 4 bits, empezando de derecha a izquierda. En caso de que el
último
grupo (el que quede más a la izquierda) sea menor de 4 bits se rellenan los
faltantes con ceros.
Captura y almacenamiento de datos numéricos.
Las
variables numéricas son muy útiles en ensamblador de la misma forma que en
otros lenguajes de programación, ya que permiten al programador hacer
operaciones aritméticas con datos que se desconocen al momento de la
compilación.
La
utilización de datos numéricos es similar a la de cadenas, con la diferencia de
que en vez de declarar las variables como db, se declaran como dw, lo cual
significa que son variables numéricas.
Enlazador: es parte del proceso de ejecución, convierte el código máquina y enlaza los
distintos módulos del programa
Comentarios
Publicar un comentario