2.6 CICLOS CONDICIONALES. En general es posible anidar tantos ciclos como sean necesarios. Esto es muy semejante a lo que ocurra cuando definamos una instrucción que usaba otra instrucción definida antes. 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 las banderas.
LOOP: Tiene un tamaño de 8 bits abarca de 00 hasta FF y tiene signo . Ejecutar un BUCLE consiste en repetir “n” veces una serie de instrucciones de una sección del programa.
Esta instrucción, en el momento que se ejecuta, realiza los siguientes pasos: 1°Decrementa a CX en un uno.(CX=CX-1) 2°Checa el valor de CX, y -SI CX es diferente de cero, realiza el salto correspondiente de acuerdo al valor del desplazamiento. -Si CX es igual a cero, continua con la siguiente instrucción debajo de ella.
2.7 INCREMENTO Y DECREMENTO. Instrucciones de conteo, se utilizan para decrementar o incrementar el contenido de los contadores.
INC: Consiste en sumar uno al contenido de un registro que se especifica en la instrucción. Su esquema es: R ← R+1 Donde "R" representa un registro cualquiera de 8 a 16 bits. Si se trata de un registro doble (de 16 bits) se incrementa el registro de orden bajo (por ejemplo, en el "BC" se incrementa "C"), y si ello hace que este pase a valer "0", se incrementa también el de orden alto. Propósito: Incrementar el operando. Sintaxis: INC destino La instrucción suma 1 al operando destino y guarda el resultado en el mismo operando destino.
DEC: Es la inversa de la anterior, consiste en restar uno al contenido de un registro. Su esquema es:
R ← R-1
Si se trata de un registro doble, se decrementa el de orden bajo y, si esto hace que pase a valer 255 (FFh), se decrementa también el de orden alto. Propósito: Decrementar el operando Sintaxis:
DEC destino
Esta operación resta 1 al operando destino y almacena el nuevo valor en el mismo operando.
2.9 INSTRUCCIONES ARITMÉTICAS. Este tipo de instrucciones realizan operaciones aritméticas con los operandos. Y son: ADD, ADC, DAA, AAA, SUB, SBB, DAS, AAS, NEG, MUL, IMUL, AAM, DIV, IDIV, AAD, CBW, CBW, CWB, INC, INC, DEC. ADD y ADC realizan la suma y la suma con acarreo (bit CF del registro registro de estado) de dos operandos, respectivamente, y guardan el resultado en el primero de ellos. Admiten todos los tipos de direccionamiento direccionamiento (excepto que ambos operando estén en memoria). ADD/ADC ADD/ADC reg, reg reg ADD/ADC ADD/ADC mem, reg ADD/ADC ADD/ADC reg, mem mem ADD/ADC ADD/ADC reg, inmediato inmediato ADD/ADC ADD/ADC mem, inmediato inmediato Ejemplo: ; J = 34+f MOV AX, F ADD AX, AX, 34 MOV J, AX SUB y SBB realizan la resta y la resta con acarreo, respectivamente, de dos operandos y guardan el resultado en el primero de ellos. Admiten todos los modos de direccionamiento, excepto dos operando en memoria. SUB/SBB reg, reg SUB/SBB mem, reg SUB/SBB reg, mem SUB/SBB reg, inmediato SUB/SBB mem, inmediato Ejemplo: ; J = F-34 MOV AX, F SUB AX, 34 MOV J, AX Estas instrucciones afectan a los bits OF, SF, ZF, AF, PF, CF del registro de estado. DAS realizan la corrección BCD empaquetado del resultado de una resta en AL. Actúan de manera similar a la instrucción de ajuste de la suma. NEG realiza la operación aritmética de negado de un operando y guarda el resultado en el mismo operando. Admite todos los tipos de direccionamiento, excepto inmediato. NEG reg NEG mem La operación que realiza es: 0 – operando.
Estas instrucciones afectan a los bits OF, SF, ZF, AF, PF, CF del registro de estado. DAA realizan la corrección BCD empaquetado del resultado de una suma en AL. La mayoría de las computadoras son grandiosas para las matemáticas, esto viene a sorprender que el lenguaje ensamblador solo tiene unos operadores matemáticos relativamente primitivos. No hay símbolos de exponenciación, no hay punto flotante, no hay raíz cuadradas, y no existen funciones SENO y COSENO dentro del grupo de instrucciones del 8086. Las instrucciones Matemáticas en lenguaje ensamblador están restringidas a sumar, multiplicar, dividir y restar valores enteros con signo o sin signo. Instrucciones Generales Mnemónico/Operando
Descripción
Instrucciones de Adición aaa
Ajuste ASCII para adición
adc destino, fuente
Suma con acarreo
add destino, fuente
Suma bytes o palabras
daa
Ajuste decimal para adición
inc destino
Incremento
Instrucciones de Substracción aas
Ajuste ASCII para substracción
cmp destino, fuente
Compara
das
Ajuste decimal decimal para substracción substracción
dec destino
Decrementa byte o palabra
neg destino
Negar (complemento a dos)
sbb destino, fuente
Substrae
sub destino, fuente
Substrae
Instrucciones de Multiplicación aam imul fuente
Ajuste ASCII ASCII para multiplicación multiplicación Multiplicación con enteros
mul fuente
Multiplicar
Instrucciones de División aad
Ajuste ASCII ASCII para división
cbw
Convierte bytes a palabras
cwd
Convierte palabras a dobles palabras
div fuente
Divide
idiv fuente
División de Enteros
Existen dos formas de incrementar el poder matemático del lenguaje ensamblador. Primero, se puede comprar) o escribir) un paquete de funciones matemáticas con rutinas que implementan las funciones matemáticas de alto nivel que se necesitan. Otra solución es comprar un chip coprocesador matemático, aunque esto puede ser muy caro. Como una tercera opción, y probablemente la mejor, es utilizar un lenguaje de alto nivel como Pascal o C para codificar las expresiones de punto flotante. Estos lenguajes vienen con un detector automático de presencia de coprocesador matemático o cambiar a un software emulador para sistemas que carezcan del chip opcional. Después de escribir el programa, se puede combinar el código compilado de alto nivel, con nuestro programa en lenguaje ensamblador. Ya que el coprocesador matemático tiene requerimientos estrictos acerca de los datos y formatos de instrucciones, la mayoría de los compiladores generan código máquina optimizado, y hay poca ventaja en escribir expresiones de punto flotante directamente en lenguaje ensamblador. Pero no tome esto como una pronunciada negativa en matemáticas del lenguaje ensamblador. Aún sin una librería matemática o coprocesador, se pueden utilizar plenamente instrucciones de enteros.
2.10 MANIPULACIÓN DE LA PILA. Uso del Stack El Stack es un segmento especial de memoria que opera en conjunción con varias instrucciones del 8086. Como con todos los segmentos, la localización del stack y su tamaño (hasta 64K) dependen del programador determinarlo. En los programas de lenguaje ensamblador, la forma más fácil de crear un stack es usar la directiva STACK. Un stack tiene tres propósitos principales:
Preservar valores de los registros temporalmente. Almacenar direcciones a las cuales las rutinas regresaran. Almacenar variables dinámicas.
El último de éstos viene a jugar más frecuentemente en los lenguajes de programación de alto nivel, donde las variables son pasadas vía stack hacia y desde, funciones y procedimientos. Similarmente, variables temporales pueden se almacenadas en el stack. Estos usos son raros en la programación pura en lenguaje ensamblador, aunque se puede almacenar variables de memoria de ésta manera si se desea.
Como opera el Stack Conceptualmente, un stack es como una torre de platos en una cocina de un restaurante. El plato de encima de la pila está fácilmente disponible. Pero para tomar los platos de abajo, otros platos de encima primeramente deben ser removidos. Colocar un nuevo plato en la pila es llamado push, Remover un plato de la parte superior de la pila, es llamado pop. Ya que de la manera en que el último plato colocado en el stack es el primer plato disponible a ser removido, éste tipo de stack es llamado stack LIFO o UEPS, por "Last-In-First-Out". No como los platos, los valores en la computadora no pueden moverse físicamente hacia arriba y hacia abajo. Por lo tanto, para simular la acción de un movimiento de los valores del stack, requiere de utilizar registros para localizar la dirección base del Stack y la dirección OFFSET del plato superior - que es, la localidad donde el valor superior de la pila es almacenado. En programación 8086, el registro segmento ss direcciona al segmento de stack base. El registro sp direcciona el desplazamiento OFFSET tope del Stack en dicho segmento. La siguiente figura Ilustra como aparece un stack de 12 bytes en memoria. EL registro ss direcciona la base del stack en el segmento direccionado en 0F00. El registro sp direcciona el desplazamiento (OFFSET) desde esta dirección inicial, en un rango desde 0000 hasta 000A. El ultimo byte del stack esta en desplazamiento 000B. Los elementos en el stack ocupan palabras de 2 Bytes. El programa que prepara éste stack puede declarar STACK 12 y dejar que el ensamblador, enlazador, y DOS calculen exactamente donde estará almacenado el Stack en memoria. No hay que inicializar ss y sp. DOS lo realiza por nosotros cuando carga el programa para ejecutarlo. En la
figura, sp1 muestra donde apunta sp cuando el programa comienza a correr. Nótese que la dirección lógica en ss:sp apunta al byte por debajo del ultimo byte en el stack. Memoria Baja 0000 0002 0004 0006 0008 000A 000C
0F00:
200 100
ss:sp3 ss:sp2 ss:sp1
Fin del segmento Stack En referencia a la figura anterior. Varias acciones ocurren si se ejecutan las siguientes instrucciones: mov push mov push
ax,100 ax bx, 200 bx
; sp2 ; sp3
La instrucción push realiza dos pasos: 1. Substrae 2 de sp 2. El valor del registro especificado es copiado a [ ss:sp]. El orden de estos pasos es importante. Un push primero substrae 2 (no 1) de sp. La primer colocación push, deja a sp en sp2, donde el valor del registro ax es almacenado. Nótese que esta acción deja al puntero del stack direccionado al valor palabra recientemente colocado- pushed - en el stack.
Manipulación del Stack El punto principal de la manipulación del stack es simple: Para cada pus h en un programa, debe haber su correspondiente pop. Igualando pops y pus hes mantiene el stack en forma correcta- en otras palabras, en sincronización con la habilidad del programa para almacenar y recuperar el valor que necesita. Considere lo que sucede si se falla en ejecutar un correspondiente pop para cada pus h. En éste caso, pushes futuros causarán que el stack crezca mas y más largo, eventualmente rebasando el espacio segmento permitido para el programa. Este grave error normalmente termina en un crash sobre escribiendo otras áreas de memoria por el puntero del stack. Un error similar ocurre si se ejecutan más pops que pushes, causando un bajoflujo y también resultar en un crash.
Una forma de prevenir éstos problemas es escribir los programas en pequeños módulos, o subrutinas. En cada módulo, realizar un pus h con todos los registros que se utilizarán. Entonces, justo antes de que ésta sección de código termine, realizar un pop a los mismos registros retirándolos pero en orden inverso. push ax push bx push cx ; ------ Programa objetivo pop cx pop bx pop ax En éste ejemplo, los registros ax, bx y cx, son posiblemente utilizados; por lo tanto, éstos registros son almacenados en el stack para preservar los valores de los registros. Por último, los valores son retirados ( pop) del stack en orden inverso, restaurando los valores originales de los registros y manteniendo el stack en sincronía. PUSH y POP realizan las operaciones de apilado y desapilado en la pila del procesador respectivamente, admiten todos los tipos de direccionamiento (excepto inmediato). Los operandos deben ser siempre de 16 bits. PUSH reg PUSH mem PUSH seg-reg POP reg POP mem POP seg-reg Ejemplos: PUSH AX ;envía a la pila AX POP DS ;carga el primer elemento de la pila en DS
BIBLIOGRAFÍA: http://jsanchezvalles.blogspot.mx/2010/04/instrucciones-de-lenguaje-ensamblador.html http://expo.itch.edu.mx/view.php?f=asm_25 http://www.iuma.ulpgc.es/~armas/asignaturas/calculadoras/contenido/slides_introsoft.p df http://www.itescam.edu.mx/principal/webalumnos/sylabus/asignatura.php?clave_asig=S CC-1014&carrera=ISIC-2010-224&id_d=170 http://www.youtube.com/watch?v=j1HpGAOOfbo http://danimtzc.blogspot.mx/2012/03/saltos-ciclos-operadores-logicos-y-mas.html