En el mundo de la programación en Ensamblador aveces es necesario utilizar ciertos bloques de código de una forma repetitiva y/o ejecutar ciertas instrucciones de acuerdo a ciertas condiciones.
Para ello como en cualquier lenguaje de programación existen lo que conocemos como sentencias cíclicas y condicionales.
Sentencias condicionales:
Como sabemos una sentencia condicional nos permitirá bifurcar nuestros códigos, seleccionando los bloques de código necesarios para la resolución del proceso o tarea a realizar. En ensamblador 8086 manejamos las sentencias condicionales mediante los mnemónicos.
Básicamente CMP y TEST funcionan como nuestro if, comparando o verificando el valor de ciertos registros del procesador.
Todos los demás mnemónicos que podemos ver son utilizados para saltar hacia un grupo de instrucciones según el resultado de la comparación.
Estos elementos de comparación ya los hemos utilizado dentro de las entradas pasadas, veamos un ejemplo rápido:
El código expuesto compara una entrada de datos en el registro al con el valor 18, si el valor de AL (GRATER OR EQUAL IT JUMPS TO) es mayor o igual salta a un conjunto de instrucciones etiquetadas con el label mayor, de lo contrario (JUMPS) solo salta a otro conjunto de instrucciones bajo el nombre de la etiqueta menor.
Acumuladores:
Un acumulador es aquel operando que nos permite agregar o decrementar el valor a una misma variable, los acumuladores mas conocidos en otros lenguajes es el tipico "++" usando en expresiones como "variable++" el cual incrementa en un valor la variable y el "--" usado en expresiones como "variable--" el cual decrementa la variable en una unidad.
En ensamblador poseemos sus homólogos bajo los mnemonicos:
Estructuras ciclicas:
Una estructura cíclica es aquella que repite un bloque de instrucciones una cantidad de veces definida por el programador, es así que podemos imprimir, por ejemplo, un mensaje en pantalla miles de veces con tan solo un par de instrucciones.
Veamos el siguiente ejemplo:
En este caso utilizamos una etiqueta ("while"), no confundir con la instrucción while, esto debido a que las sentencias comúnmente vistas como while, do-while, for no existen tal cual en ensamblador. En fin continuemos, en este caso utilizamos esta etiqueta y el registro CL como contador, de esta manera le colocamos el valor de 10, dentro de la etiqueta ("método") el cual imprimirá la cadena "hola", posteriormente decrementara el valor de CL en una unidad y por ultimo comparara, si el valor en el contador CL (JUMP IF NO ZERO) es diferente de cero, si es diferente a cero el flujo del programa saltara al inicio del método while nuevamente, este ciclo se repetirá 10 veces hasta terminar.
Otra forma de realizar lo anterior es por medio del mnemonico loop, veamos un ejemplo:
En este caso creamos un ciclo sin fin, solo por método didáctico, la cuestión es que el ciclo se repetirá infinitamente hasta que el registro AL ya no pueda contener el valor del numero a imprimir, iniciamos así el ciclo incrementando el valor de num en 1, (variable previamente definida con el valor 0) posteriormente movemos su valor a AL para imprimir el resultado usando la opción call print_num, y finalmente imprimimos el mensaje de hola, una vez hecho esto, el ciclo nuevamente se repetira nuevamente.
Existen otros tantos valores que podemos usar para crear ciclos, aquí tenemos instrucciones similares a Loop para crear ciclos.
LOOPNZ (LOOPNE):
LOOPNE o que es lo mismo LOOPNZ genera un ciclo en donde decrementa el valor de CX en 1 por vuelta, este se estará repitiendo mientras CX sea diferente de CERO y la bandera ZF sea igual a 0.
En este caso hacemos una resta entre registros AL-BL para hacer cambiar el valor de la bandera, en el caso actual tenemos 2-3, lo cual generara un valor de -1, recordemos que ZF es la Bandera de resultado 0 o comparación igual, es decir, en este caso tengo una operación matematica, para que ZF cambie a 1 debo tener como resultado un 0 en la operación, o en su defecto si quiero tener un 0 en la bandera debo tener como resultado cualquier otro valor, en este caso AL-BL=-1, esto quiere decir que ZF debe valer 0 al final de cada interación, permitiendo que el ciclo funcione 9 veces, si cambiamos los valores de la resta para que el resultado sea cero, el ciclo solo se repetirá una sola vez, puesto que ZF habra cambiado a 1, según nuestra definición.
Resultados:
LOOPE (LOOPZ):
LOOPZ o LOOPE que es lo mismo, genera un ciclo en donde decrementa el valor de CX y el cual se repetira mientras CX sea diferente de CERO y en adicion ZF=1.
Resultado:
Si comparamos las pantallas actuales con las anteriores nos daremos cuenta de que, LOOPZ y LOOPNZ son practicamente el mismo bucle, lo unico que los diferencia es la forma en que manejan la bandera ZF.
Al utilizar esta instrucción le indicamos al ensamblador que las lineas deben repetirse mientras cx sea igual y unicamente igual a cero.
Resultado:
El programa anterior imprimirá el mensaje Hola Mundo unas 5 veces, utilizando en este caso a num como variable de control, esta variable es incrementada y comparada en cada ciclo, una vez que valga 5 o mas esta romperá el ciclo y transferirá las instrucciones a la etiqueta fin.
Si quieres conocer mas acerca de las etiquetas de saltos vistas al inicio de la entrada y otras mas te dejo este sitio: https://www.alpertron.com.ar/INST8088.HTM
Para ello como en cualquier lenguaje de programación existen lo que conocemos como sentencias cíclicas y condicionales.
Sentencias condicionales:
Como sabemos una sentencia condicional nos permitirá bifurcar nuestros códigos, seleccionando los bloques de código necesarios para la resolución del proceso o tarea a realizar. En ensamblador 8086 manejamos las sentencias condicionales mediante los mnemónicos.
Básicamente CMP y TEST funcionan como nuestro if, comparando o verificando el valor de ciertos registros del procesador.
Todos los demás mnemónicos que podemos ver son utilizados para saltar hacia un grupo de instrucciones según el resultado de la comparación.
Estos elementos de comparación ya los hemos utilizado dentro de las entradas pasadas, veamos un ejemplo rápido:
cmp al,18 ;Si lo que se encuentra en al>18 JGE mayor ;salta a mayor JMP menor ;sino ve a menor
El código expuesto compara una entrada de datos en el registro al con el valor 18, si el valor de AL (GRATER OR EQUAL IT JUMPS TO) es mayor o igual salta a un conjunto de instrucciones etiquetadas con el label mayor, de lo contrario (JUMPS) solo salta a otro conjunto de instrucciones bajo el nombre de la etiqueta menor.
Acumuladores:
Un acumulador es aquel operando que nos permite agregar o decrementar el valor a una misma variable, los acumuladores mas conocidos en otros lenguajes es el tipico "++" usando en expresiones como "variable++" el cual incrementa en un valor la variable y el "--" usado en expresiones como "variable--" el cual decrementa la variable en una unidad.
En ensamblador poseemos sus homólogos bajo los mnemonicos:
Estructuras ciclicas:
Una estructura cíclica es aquella que repite un bloque de instrucciones una cantidad de veces definida por el programador, es así que podemos imprimir, por ejemplo, un mensaje en pantalla miles de veces con tan solo un par de instrucciones.
Veamos el siguiente ejemplo:
MOV CL, 10 while: print "hola" DEC CL JNZ while
En este caso utilizamos una etiqueta ("while"), no confundir con la instrucción while, esto debido a que las sentencias comúnmente vistas como while, do-while, for no existen tal cual en ensamblador. En fin continuemos, en este caso utilizamos esta etiqueta y el registro CL como contador, de esta manera le colocamos el valor de 10, dentro de la etiqueta ("método") el cual imprimirá la cadena "hola", posteriormente decrementara el valor de CL en una unidad y por ultimo comparara, si el valor en el contador CL (JUMP IF NO ZERO) es diferente de cero, si es diferente a cero el flujo del programa saltara al inicio del método while nuevamente, este ciclo se repetirá 10 veces hasta terminar.
Otra forma de realizar lo anterior es por medio del mnemonico loop, veamos un ejemplo:
mov cl,0 while: inc num mov al, num call print_num print "hola " loop while
En este caso creamos un ciclo sin fin, solo por método didáctico, la cuestión es que el ciclo se repetirá infinitamente hasta que el registro AL ya no pueda contener el valor del numero a imprimir, iniciamos así el ciclo incrementando el valor de num en 1, (variable previamente definida con el valor 0) posteriormente movemos su valor a AL para imprimir el resultado usando la opción call print_num, y finalmente imprimimos el mensaje de hola, una vez hecho esto, el ciclo nuevamente se repetira nuevamente.
Existen otros tantos valores que podemos usar para crear ciclos, aquí tenemos instrucciones similares a Loop para crear ciclos.
LOOPNZ (LOOPNE):
LOOPNE o que es lo mismo LOOPNZ genera un ciclo en donde decrementa el valor de CX en 1 por vuelta, este se estará repitiendo mientras CX sea diferente de CERO y la bandera ZF sea igual a 0.
.model small .stack 64 .data msg1 db 10,13,"hola mundo $" .code mov ax,@data mov ds,ax mov cx,9 comienzo: mov ah,09 lea dx,msg1 ;mov dx,offset msg1 int 21h mov al,2 mov bl,3 sub al,bl loopne comienzo end
En este caso hacemos una resta entre registros AL-BL para hacer cambiar el valor de la bandera, en el caso actual tenemos 2-3, lo cual generara un valor de -1, recordemos que ZF es la Bandera de resultado 0 o comparación igual, es decir, en este caso tengo una operación matematica, para que ZF cambie a 1 debo tener como resultado un 0 en la operación, o en su defecto si quiero tener un 0 en la bandera debo tener como resultado cualquier otro valor, en este caso AL-BL=-1, esto quiere decir que ZF debe valer 0 al final de cada interación, permitiendo que el ciclo funcione 9 veces, si cambiamos los valores de la resta para que el resultado sea cero, el ciclo solo se repetirá una sola vez, puesto que ZF habra cambiado a 1, según nuestra definición.
Resultados:
LOOPE (LOOPZ):
LOOPZ o LOOPE que es lo mismo, genera un ciclo en donde decrementa el valor de CX y el cual se repetira mientras CX sea diferente de CERO y en adicion ZF=1.
.model small .stack 64 .data msg1 db 10,13,"hola mundo $" .code mov ax,@data mov ds,ax mov cx,9 comienzo: mov ah,09 lea dx,msg1 ;mov dx,offset msg1 int 21h mov al,2 mov bl,2 sub al,bl loopz comienzo end
Resultado:
Si comparamos las pantallas actuales con las anteriores nos daremos cuenta de que, LOOPZ y LOOPNZ son practicamente el mismo bucle, lo unico que los diferencia es la forma en que manejan la bandera ZF.
JCXZ:
Al utilizar esta instrucción le indicamos al ensamblador que las lineas deben repetirse mientras cx sea igual y unicamente igual a cero.
.model small .stack 64 .data msg1 db 10,13,"hola mundo $" num db 0 .code mov ax,@data mov ds,ax mov cx,0 comienzo: mov ah,09 lea dx,msg1 ;mov dx,offset msg1 int 21h add num,1d cmp num,5d jge fin jcxz comienzo fin: mov ah,4ch int 21h end
Resultado:
El programa anterior imprimirá el mensaje Hola Mundo unas 5 veces, utilizando en este caso a num como variable de control, esta variable es incrementada y comparada en cada ciclo, una vez que valga 5 o mas esta romperá el ciclo y transferirá las instrucciones a la etiqueta fin.
Si quieres conocer mas acerca de las etiquetas de saltos vistas al inicio de la entrada y otras mas te dejo este sitio: https://www.alpertron.com.ar/INST8088.HTM
Comentarios
Publicar un comentario