UNIDAD IV: PROGRAMACION BASICA

2.1 Ensamblador ( y ligador ) a utilizar.


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 codigo maquina,  ejecutable directamente por el microprocesador.
El programa lee el fichero escrito en lenguaje ensamblador y sustituye cada uno de los códigos nemotecnicos 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.



Un ligador, es un programa que enlaza todos los programas o módulos obteniendo lo que denominamos programas ejecutables.
Es un programa que enlaza distintos módulos o programas que poseen subprogramas. Ademas incorporan las denominadas rutinas de librerias en caso de solicitarlas el propio programa.
La generacion de un modulo ejecutable a partir de una colección de procedimientos traducidos independientemente requiere un ligador.


Sus principales funciones son:
  • Enlazar código intermedio compilado independientemente en un solo modulo de carga resolviendo las diferencias entre Tokens. 
  • Incorpora las denominadas rutinas de librerías en caso de solicitarlas el propio programa. 
  • Su función es reducir procedimientos traducidos por separado y enlazarlos para que se ejecuten como una unidad llamada programa binario ejecutable.

Clasificación de ensambladores de acuerdo a sus características:

  • Ensambladores Cruzados (Cross-Assembler).


Se denominan así los ensambladores que se utilizan en una computadora que posee un procesador diferente al que tendrán las computadoras donde va a ejecutarse el programa objeto producido.

El empleo de este tipo de traductores permite aprovechar el soporte de medios físicos (discos, impresoras, pantallas, etc.), y de programación que ofrecen las máquinas potentes para desarrollar programas que luego los van a ejecutar sistemas muy especializados en determinados tipos de tareas.



  • Ensambladores de una fase.
Estos ensambladores leen una línea del programa fuente y la traducen directamente para producir una instrucción en Lenguaje maquina o la ejecuta si se trata solo de una pseudoinstruccion. También va construyendo la tabla de símbolos a medida que van apareciendo las definiciones de variable, etiquetas etc. 
Debido a su forma de traducción, estos ensambladores obligan a definir los símbolos antes de ser empleados para que cuando aparezca una referencia a un determinado símbolo en una instrucción, se conozca la dirección de dicho símbolo y se pueda traducir de forma correcta. Estos Ensambladores son sencillos baratos y ocupan poco espacio pero tiene el inconveniente indicado


  • 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.


  • Ensambladores Residentes.
Son aquellos que permanecen en la memoria principal de la computadora y cargan, para su ejecución, al programa objeto producido. Este tipo deensamblador tiene la ventaja de que se puede comprobar inmediatamente el programa sin necesidad de transportarlo de un lugar a otro, como se hacía encross-assembler, y sin necesidad de programas simuladores.



  • ENSAMBLADORES MACROENSAMBLADORES
Son ensambladores que permiten el uso de microinstrucciones (macros). Debido a que su potencia, normalmente son programa robustos que no permanecen en memoria una vez generado el programa objeto. Puede variar la complejidad de los mismos dependiendo de las posibilidades de definición y manipulación de las macroinstrucciones, pero normalmente son programas bastantes complejos, por lo que suelen ser ensambladores residentes.

  • MICRO ENSAMBLADORES
Generalmente, los procesadores utilizados en las computadoras tienen un repertorio fijo de instrucciones es decir, que el interprete de las mismas interpretaba de igual forma un determinado codigo de operación. El programa que indica al interprete de instrucciones de la UCP como debe actuar se denomina microprograma. El programa que ayuda a realizar este microprograma se llama micro ensamblador. Existen procesadores que permiten la modificación des sus microprogramas, para lo cual se utilizan micro ensambladores.




2.2 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 jmp, instrucción loop, instrucción cmp, instrucción cmps e instrucción de conteo.

INSTRUCCION 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|

Propósito: Salta en forma incondicional.

Sintaxis:

JMP Destino

Salta hasta la etiqueta Destino en forma automática, quiere decir que no necesita cumplir con algún tipo de condición.

Ejemplo:



INSTRUCCION LOOP

La instrucción Loop requiere un valor inicial en el registro CX, en cada interació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 elvalor 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 limite,el ensamblador envia un mensaje como un salto relativo fuera de rango. 


Propósito: Generar un ciclo en el programa.

Sintaxis:

LOOP Etiqueta

La instrucción loop decrementa CX en 1, y transfiere el flujo del programa a la etiqueta dada como operando si CX es diferente a 0.

Ejemplo:



INSTRUCCION 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}|

Propósito: Compara los operandos.

Sintaxis:

CMP operando1, operando2

Si los operandos son iguales entonces pone a la bandera ZF en cero (ZF=0), si los operandos son diferentes pone a ZF en uno (ZF=1).

Ejemplo:

La arquitectura de los procesadores x86 obliga al uso de segmentos de memoria para manejar la información, el tamaño de estos segmentos es de 64kb. La razón de ser de estos segmentos es que, considerando que el tamaño máximo de un número que puede manejar el procesador esta dado por una palabra de 16 bits o registro, no sería posible accesar a más de 65536 localidades de memoria utilizando uno solo de estos registros, ahora, si se divide la memoria de la pc en grupos o segmentos, cada uno de 65536 localidades, y utilizamos una dirección en un registro exclusivo para localizar cada segmento, y entonces cada dirección de una casilla específica la formamos con dos registros, nos es posible accesar a una cantidad de 4294967296 bytes de memoria, lo cual es, en la actualidad, más memoria de la que veremos instalada en una PC.
Para que el ensamblador pueda manejar los datos es necesario que cada dato o instrucción se encuentren localizados en el área que corresponde a sus respectivos segmentos. El ensamblador accesa a esta información tomando en cuenta la localización del segmento, dada por los registros DS, ES, SS y CS, y dentro de dicho registro la dirección del dato específico.


2.3 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:



2.4 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.


2.5 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

Ejemplos de saltos incondicionales:

  • 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:
Ejemplos de saltos condicionales:
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).

2.6 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:

LOOP etiqueta
La instrucción loop decrementa CX en 1, y transfiere el flujo del programa a la etiqueta dada como operando si CX es diferente a 1.
Instrucción LOOPE
Propósito: Generar un ciclo en el programa considerando el estado de ZF

LOOPE etiqueta 
Esta instrucción decrementa CX en 1. Si CX es diferente a cero y ZF es igual a 1, entonces el flujo del programa se transfiere a la etiqueta indicada como operando.
Instrucción LOOPNE
Propósito: Generar un ciclo en el programa, considerando el estado de ZF

LOOPNE etiqueta 
Esta instrucción decrementa en uno a CX y transfiere el flujo del programa solo si ZF es diferente a 0.

2.7 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.

2.8-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.


2.9 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.


2.10 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. 

.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 
Int 21h ; 
END Inicio 
END

2.11 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

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
Int 21h ;
END Inicio
END

2.12 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.

2.13 DESPLAZAMIENTO Y ROTACIÓN.



Las instrucciones de desplazamiento son cuatro: shl, shr, sar y sal; y su objetivo es desplazar los bits de un 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)
 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.

2.14 OBTENCIÓN DE UNA CADENA CON LA REPRESENTACIÓN HEXADECIMAL.



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.

2.15 CAPTURA Y ALMACENAMIENTO DE DATOS 

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.


No hay comentarios.:

Publicar un comentario