jueves, 28 de marzo de 2019

Unidad No.3-Trabajando con Turbo Assembler

Ejecución del programa:



Código:

CR EQU 13
LF EQU 0Ah

DATOS SEGMENT
       MENSAJE DB CR, LF, 'Hola mundo este programa fue compilado por Ivan Gutierrez', CR, LF, '$'
DATOS ENDS
  
PILA SEGMENT STACK
       DB 64 DUP('PILA')
PILA ENDS

CODIGO SEGMENT
    HM PROC FAR
    ASSUME CS : CODIGO, DS : DATOS, SS : PILA
   
    MOV AX, DATOS
    MOV DS, AX
    LEA DX, MENSAJE
   
    MOV AH, 9
    INT 21H
   
    MOV AX, 4C00H
    INT 21H
   
    HM ENDP
   
CODIGO ENDS
END HM   

Programa No.2

Link del programa: https://drive.google.com/open?id=1mjcmgYCnMYn7XRYEfhkArns5sY_r6HbD

Ejecución:



Código:

CR EQU 13
LF EQU 10
IMPRIMIR EQU 9
PIN EQU 4C00H
DOS EQU 21H

DATOS SEGMENT
    TEXTO DB 'EJEMPLO DE USO DE CONSTANTES POR IVAN GUTIERREZ', CR, LF, '$'
   
DATOS ENDS

PILA SEGMENT STACK
    DB 64 DUP ('PILA')
PILA ENDS

CODIGO SEGMENT
    ASSUME CS: CODIGO, DS: DATOS, SS: PILA
    INICIO:
    MOV AX, DATOS
    MOV DS, AX
    MOV DX, OFFSET TEXTO
    MOV AH, IMPRIMIR
    INT DOS
    MOV AX, PIN
    INT DOS
   
CODIGO ENDS
END INICIO

Programa No.3:

Link del programa: https://drive.google.com/open?id=1CpO0zNQ80aSTKuZ-npxtX8WCA6r0GYFh

Ejecución:


Código:

CR EQU 13
LF EQU 10

DATOS SEGMENT
    MENSAJE DB, CR, LF, 'Hola mundo traido por Ivan Gutierrez', CR, LF, '$'
   
DATOS ENDS

PILA SEGMENT STACK
    DB 64 DUP('PILA')
PILA ENDS

CODIGO SEGMENT
    HMF PROC FAR
    ASSUME CS: CODIGO, DS: DATOS, SS: PILA
    MOV AX, DATOS
    MOV DS, AX
    LEA DX, MENSAJE
   
    CALL ESCRIBE
    MOV AX, 4C00H
    INT 21H
   
    HMF ENDP
   
    ESCRIBE PROC
    MOV AH,9
    INT 21H
    RET
    ESCRIBE ENDP
   
CODIGO ENDS
END HMF

Programa No.4:

Link del programa: https://drive.google.com/open?id=11Sw82U12hNgsZbvG000kLgfow_pTTO_c

Ejecución:


Código:

CR EQU 13
LF EQU 10

DATOS SEGMENT
    LINEA1 DB CR, LF, 'Ivan Gutierrez', CR, LF, '$'
    LINEA2 DB 'Tecnologico de Matamoros', CR, LF, '$'
    LINEA3 DB 'Ing. Sistemas Computacionales', CR, LF, '$'
   
DATOS ENDS

PILA SEGMENT STACK
DB 64 DUP('PILA')
PILA ENDS

CODIGO SEGMENT
    LN PROC FAR
   
    ASSUME CS: CODIGO, DS: DATOS, SS: PILA
    MOV AX, DATOS
    MOV DS, AX
    LEA DX, LINEA1
    CALL ESCRIBE
    LEA DX, LINEA2
    CALL ESCRIBE
    LEA DX, LINEA3
    CALL ESCRIBE
    MOV AX, 4C00H
    INT 21H
   
    LN ENDP
   
    ESCRIBE PROC
    MOV AH, 9
    INT 21H
    RET
    ESCRIBE ENDP
   
CODIGO ENDS
END LN 

miércoles, 13 de marzo de 2019

Unidad No.2- Saltos Incondicionales (JMP) y Saltos Condicionales

Salto Incondicional:

Programa 1:


Ejecución del programa:




Código:

org    100h

mov    ax, 5          ; set ax to 5.
mov    bx, 2          ; set bx to 2.

jmp    calc            ; go to 'calc'.

back:  jmp stop      ; go to 'stop'.

calc:
add    ax, bx         ; add bx to ax.
jmp    back           ; go 'back'.

stop:

ret                   ; return to operating system.




Saltos Condicionales:



Programa 2:


Ejecución del programa:



Código:

include "emu8086.inc"

org    100h

mov    al, 25     ; set al to 25. 
mov    bl, 10     ; set bl to 10. 

cmp    al, bl     ; compare al - bl. 

je     equal      ; jump if al = bl (zf = 1). 

printn 'no es igual'        ; if it gets here, then al <> bl, 
jmp    stop       ; so print 'n', and jump to stop. 

equal:            ; if gets here, 
printn 'es igual'        ; then al = bl, so print 'y'. 

stop:

ret               ; gets here no matter what. 

Unidad No.2: Temario U2 y 2.6 ciclos condicionales

2.6 Ciclos Condicionales:
Instruccion LOOP
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 1.

Instrucción LOOPE
Sintaxis:
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
Sintaxis:
LOOPNE etiqueta
Esta instrucción decrementa en uno a CX y transfiere el flujo del programa solo si
ZF es diferente a 0.

Unidad No.2 Ciclos condicionales

Los blucles deben ir acompañados del registro CX.

Control de Bucles (instrucciones simples)
Éstas posibilitan el grupo de control más elemental de nuestros programas. Un bucle es un bloque de código que se ejecuta varias veces. Hay 4 tipos de bucles básicos:
o Bucles sin fin
o Bucles por conteo
o Bucles hasta
o Bucles mientras
Las instrucciones de control de bucles son las siguientes:
·· INC incrementar
·· DEC decrementar
·· LOOP realizar un bucle
·· LOOPZ,LOOPE realizar un bucle si es cero
·· LOOPNZ,LOOPNE realizar un bucle si no es cero
·· JCXZ salta si CX es cero
Instrucciones de Prueba, Comparación y Saltos.
Este grupo es una continuación del anterior, incluye las siguientes instrucciones:
·· TEST verifica
·· CMP compara
·· JMP salta
·· JE, JZ salta si es igual a cero
·· JNE, JNZ salta si no igual a cero
·· JS salta si signo negativo
·· JNS salta si signo no negativo
·· JP, JPE salta si paridad par
·· JNP, JOP salta si paridad impar
·· JO salta si hay capacidad excedida
·· JNO salta si no hay capacidad excedida
·· JB, JNAE salta si por abajo (no encima o igual)
·· JNB, JAE salta si no está por abajo (encima o igual)
·· JBE, JNA salta si por abajo o igual (no encima)
·· JNBE, JA salta si no por abajo o igual (encima)
·· JL, JNGE salta si menor que (no mayor o igual)
·· JNL, JGE salta si no menor que (mayor o igual)
·· JLE, JNG salta si menor que o igual (no mayor)
·· JNLE, JG salta si no menor que o igual (mayor)

Programa 1:


Ejecución del programa:


Código:
; You may customize this and other start-up templates; 
; The location of this template is c:\emu8086\inc\0_com_template.txt

org 100h
include 'emu8086.inc'

mov cx,50 ;es registro que controla el numero de veces de iteraciones 

comienzo: ;debe tener un etiqueta loop
        printn 'letrero'
        
loop comienzo        


ret

Programa No.2:


Ejecución del programa:


Código:

.model tiny

name 'bucle'

.data
    dato db 10,13,'letrero $' 
    
.code
inicio:
      mov cx,50
      comienzo:
              mov dx,offset dato
              mov ah,09
              int 21h
              loop comienzo 
              
              
Programa No.3:


Ejecución del programa:


Código:

.model tiny

name 'bucle'

.data
    dato db 10,13,'letrero $' 
    
.code
inicio:
      mov cx,50
      comienzo:
              lea dx,dato
              mov ah,09
              int 21h
              loop comienzo 

Programa No.4:


Ejecución del programa:


Código:

.model tiny

name 'bucle'

.data
    dato db 10,13,'letrero $' 
    
.code
inicio:
      mov cx,9
      comienzo:
              lea dx,dato
              mov ah,09
              int 21h
              loopne comienzo

martes, 5 de marzo de 2019

BREVE RESUMEN DE LENGUAJE ENSAMBLADOR

0.- MOTIVACION.
El lenguaje ensamblador continúa siendo imprescindible para imple-
mentar fragmentos de código donde la velocidad del ejecutable y/o
miten la inclusión directa en el código fuente de sentencias en
su tamaño sean críticos. Afortunadamente, muchos compiladores per-
ensamblador, de forma que ya no es necesario en la mayor parte de
tablecerse desde el entorno de desarrollo y van implícitas en las
los casos el uso de ensambladores. Como ventaja adicional, no es
necesario conocer las directivas de ensamblador, ya que pueden es-
directivas del compilador, por ejemplo, el compilador Pascal de
1.-REGISTROS DEL 8086.
Borland o el compilador C/C++ de la misma compañía.
Aún así, a muchos programadores les resulta difícil renunciar al
control absoluto de la máquina que permite el lenguaje ensambla-
CX, DX, SI, DI, BP, SP. Existe tambien un registro IP (Instruction
dor.
El 8086 dispone de ocho registros de propósito general, que pode-
mos considerar como memorias implementadas sobre la misma CPU de
registros de segmento, llamados CS, DS, SS, ES y un registro de
acceso muy rápido. Estos registros reciben los nombres de AX, BX, Pointer)que apunta a la siguiente instrucción a ejecutar, formando
continuación. Aparte de los registros generales y de IP, existen
su dirección junto con el registro CS, que citaremos a flags, cuyos bits no son accesibles directamente y que reflejan
una buena práctica de programación usarlos para lo que fueron
los resultados de distintas operaciones.
Cualquiera de los registros de propósito general puede usarse para
escribir a/desde memoria, realizar operaciones, como punteros o
principalmente concebidos.
contadores, pero cada uno tiene una personalidad especial, y es
MOV DS,AX
AX se usa siempre en multiplicaciones y divisiones y es el mas
eficiente para operaciones aritméticas y de movimiento de datos.
memoria. Por ejemplo, para cargar en AL el contenido de la posi-
BX se usa como puntero, y junto con DS referencia posiciones de ción de memoria número 9: MOV AX,0 MOV BX,9
DX es el único registro que puede usarse para acceder a puertos.
MOV AL,[BX]
CX se usa principalmente como contador en los bucles. Estos son
tan frecuentes que existe una instrucción especial, LOOP, que
distinto de cero:
comprueba su valor, volviendo al principio del bucle si es MOV CX,10 BUCLE: instrucciones LOOP BUCLE
sucesivas de memoria cuando se usa con instrucciones de cadena:
Por ejemplo, para escribir 62H en la dirección de puerto 1000H: MOV AL,62H MOV DX,1000H OUT DX,AL
SI se usa como puntero. Su nombre proviene de Source Index, y se
usa principalmente con instrucciones de cadena: CLD
carga en AX el valor de la posición 20 de memoria. SI se incrementa
MOV AX,0 MOV DS,AX MOV SI,20 LODSB
cesivas de memoria.
en una unidad. En combinación con LOOP permite leer posiciones su-
STOSB
DI tambien se usa como puntero. Permite escribir en posiciones CLD MOV DX,0 MOV ES,DX MOV DI,2048
la, y por ello no debe modificarse salvo que se sepa exactamente
escribe el contenido de AL en 0000:2048. Mientras que DI usa a ES
como segmento, SI usa a DS.
de DI cuando se usa con funciones de cadena. BP actua tambien co-
BX, DI y SI actuan como punteros relativos a DS, o a ES en el caso
SP es entre los registros de uso general el mas específico, ya que
mo puntero, pero relativo al segmento de pila SS. no se recomienda su uso, pues apunta al extremo superior de la pi-
De esta forma, el armazón de un programa en ensamblador es el si-
que se está haciendo. 2.-ESTRUCTURA DE UN PROGRAMA EN ENSAMBLADOR.
Expondremos brevemente la estructura de un programa fuente en en-
samblador. Este está compuesto por una serie de segmentos para la
dos.
pila, el código y los datos. Los segmentos no pueden estar anida- Cada uno comienza con el nombre del segmento seguido de la pala-
palabra ENDS.
bra SEGMENT y alguna o algunas cadenas exigidas por el enlazador. Cada segmento termina con el nombre del segmento seguido de la El programa termina con la palabra END seguida del nombre del pun-
labra) seguida del número de palabras que vamos a reservar y la
to de entrada al programa. guiente:
PILA SEGMENT STACK 'STACK'
. .
DATOS SEGMENT 'DATA'
PILA ENDS . .
CODIGO SEGMENT 'CODE'
DATOS ENDS . .
donde [ENTRADA] es el nombre del punto donde se inicia la secuen-
CODIGO ENDS END [ENTRADA] cia de instrucciones.
forma habitual de hacerlo es mediante la sentencia DW (define pa-
Dentro del segmento de pila, se establece el tamaño de ésta. La sentencia DUP (?). Así:
ca el número de veces a incluir consecutivamente expresión2 en el
PILA SEGMENT STACK 'STACK'
DW 100H DUP(?)
establece un segmento de pila con un tamaño de 100H palabras (512
PILA ENDS
bytes), sin especificar el contenido inicial.
Las directivas que se emplean habitualmente para establecer el
tamaño de la pila son:
DW Define Word 2 Bytes.
DB Define Byte 1 Byte.
DQ Define cuádruple palabra 8 Bytes.
DD Define doble palabra 4 Bytes.
La [directiva] puede ser DB, DW, DD, DQ. La expresión puede ser:
La sintaxis de DUP es expresión1 DUP expresión2. expresión1 indi- segmento. Cuando expresión2 es (?) indicamos que no es importante
pila queda inicializada a ceros o a cualquier otro valor particu-
el contenido inicial. No se debe cometer el error que con (?) la lar.
Vayamos por partes: [nombre] es un campo opcional pero absoluta-
Pasemos al segmento de datos. La sintaxis de las líneas conteni- das en este segmento es [nombre] [directiva] expresión(es).
. Una cadena entre comillas
mente conveniente, ya que especificándolo nos podremos referir después a la dirección de la variable simplemente nombrándola. . Un valor numérico
apuntarán durante la ejecución los diferentes registros de segmen-
. Una tabla de valores separados por ","
Así, son válidas las líneas siguientes:
Nada DW (?)
Mensaje DB 'Hola' Peso DB 70
La última línea se puede simplificar con DUP en la forma siguien-
Vector DB 0,0,0,13,120,76,76,76,76,76,76 te:
Considérese la variable como un puntero a un dato del tipo defi-
Vector DB 3 DUP(0),13,120,6 DUP(76)
El segmento de código suele tener una primera línea con la direc-
nido por D[X], y el valor especificado a continuación como el va- lor apuntado.
datos. De esta forma, el segmento de código de un programa .COM
tiva ASSUME, que informa al ensamblador de los segmentos a los que to. Por ejemplo:
ASSUME CS:CODIGO, DS:DATOS, SS:PILA
Si deseamos generar un ejecutable de tipo COM, es necesario cum-
plir ciertas normas. La primera es que el programa fuente debe
la pila. La otra limitación es que el punto de entrada debe estar
contener un solo segmento, donde residirán el código, los datos y en el desplazamiento 100H de dicho segmento. La directiva ORG 100H
Lo habitual es que a continuación forzemos un salto al verdadero
indica al ensamblador que continúe el ensamblado a partir de la dirección dada por el argumento, en este caso 100H. punto de entrada, estando el espacio intermedio ocupado por los
control al sistema operativo. La encargada de realizar esta tarea
comenzaría:
CODIGO SEGMENT 'CODE'
ASSUME CS:CODIGO, DS:CODIGO, SS:CODIGO
ORG 100H Inicio: JMP Entrada .
Entrada PROC
. ; espacio para los datos . . . . Entrada ENDP
Un dato a tener en cuenta es que somos responsables de iniciali-
CODIGO ENDS END Inicio
por ejemplo, para inicializar el registro DS:
zar correctamente los registros para que apnten a los segmentos, MOV AX,DATOS
para terminar el programa, liberando la memoria y devolviendo el
MOV DS,AX Por otro lado, siempre será necesario llamar a una función del DOS
constante y, por defecto, BX indica desplazamientos respecto al
es la función 4CH de INT 21H, de manera que al final del segmento
de código será preciso introducir las siguientes dos líneas:
Existen dieciseis formas de referenciar una posición de memoria.
MOV AH,4CH INT 21H 3.-MODOS DE DIRECCIONAMIENTO.
que se construyen, pues, en realidad, todas se forman mediante la
No nos ocuparemos aquí de sus denominaciones, sino de la forma en
+ + despl
combinación de unos pocos elementos. Así, se podía escribir simbólicamente BX SI
4.1. Instrucciones de transferencia de datos.
BP DI donde despl es una constante o una expresión resoluble en una
segmento DS, mientras que BP indica desplazamientos respecto al
segmento SS.
mento de datos. Se dan una serie de formas equivalentes para refe-
Como ilustración, sea una cadena de caracteres definida en el seg-
CADENA DB 'ABCDEFGHIJKL',0
renciar al elemento número ocho de la cadena: .DATA .CODE MOV AX,@DATA MOV DS,AX ...
MOV BX,OFFSET CADENA
MOV SI,OFFSET CADENA + 8 MOV AL,[SI] ... MOV BX,8 MOV AL,[CADENA+BX] ... MOV AL,[BX+8] ...
Todos los ejemplos anteriores se han puesto con la instrucción MOV
MOV SI,8 MOV AL,[CADENA+SI] ... MOV BX,3 MOV SI,4 MOV AL,[CADENA+BX+SI+1] 4.- JUEGO DE INSTRUCCIONES
MOV AX,Datos
que es con diferencia la mas usada en cualquier programa. Hay que
tener en cuenta sin embargo algunas cosas que no pueden hacerse
En primer lugar, no pueden moverse datos directamente entre dos
con la instrucción MOV. posiciones de memoria. Así MOV Datos1,Datos2 es una expresión ile-
En segundo lugar, no se pueden mover datos directamente de un re-
gal. En su lugar se escriben las dos líneas: MOV AX,Datos2 MOV Datos1,AX
En tercer lugar, no se puede mover una constante directamente a un
gistro de segmento a otro. MOV DS,ES es ilegal. En su lugar pode- mos escribir: MOV AX,ES MOV DS,AX
PUSH AX
registro de segmento. MOV DS,Datos es ilegal. En su lugar escriba- mos MOV DS,AX Finalmente, no se puede usar CS como operando.
MOV pertenece a un primer grupo de instrucciones de transferencia
de datos, entre la memoria y los registro y a/de los puertos de
siguientes:
entrada/salida. Las instrucciones mas usadas de este grupo son las PUSH, POP y sus variantes para almacenar o extraer datos de la pi-
contenidos. Describiremos brevemente cada una de ellas.
la. IN, OUT para obtener datos de un puerto o enviarlos. LEA, LDS, LES para mover direcciones de variables, en lugar de sus
realizarán en orden inverso a las instrucciones PUSH. Por ejemplo,
PUSH se usa para guardar en la pila un dato, y POP para recuperar- lo. Como la pila tiene estructura LIFO, las instrucciones POP se
Algunos ejemplos pueden ser los siguientes:
si se quieren guardar los registro AX y BX y recuperarlos después, la secuencia correcta es PUSH BX . . POP BX POP AX
PUSH y POP también son adecuados para transferir el contenido de
un registro a otro, por ejemplo PUSH AX POP BX
se necesita guardar todos los registro generales para recuperarlos
transfiere AX a BX. Este método es sin embargo mas lento. A veces
POP, se usan las instrucciones PUSHA y POPA. Además de aportar co-
después. En lugar de escribir una serie de PUSH y otra serie de
nes se ejecutan más rápido. Cuando se quiere guardar el registro
modidad al programador y legibilidad al programa, estas instruccio- de indicadores, se usan las formas PUSHF y POPF.
IN acumulador,puerto
Las instrucciones de entrada/salida IN/OUT se usan para comunicar- se con los periféricos del sistema, y tienen el formato OUT puerto,acumulador
donde registro es un registro de propósito general de 16 bits y
donde el acumulador es AX o AL según se trata de bytes o palabras.
IN AL,200 ; pasa a AL el contenido del puerto 200
OUT 20H,AX ; envía al puerto 20H el contenido de AX
Las instrucciones de transferencia de direcciones permiten código
fuente mas compacto sobre todo cuando se trata con direccionamien-
MOV AL,[BX+SI+20]
tos indexados. Por ejemplo, consideremos la instrucción
do le suma 20, usando el valor obtenido como desplazamiento dentro
El micro toma el valor de BX, le suma el valor de SI y al resulta-
MOV DX,BX
del segmento DS para acceder a un byte y transferirlo al registro AL. Esta instrucción lleva implícitas las operaciones:
conjunto, llamada LEA (Load Effective Address) para cargar un des-
ADD DX,SI ADD SI,20 Existe una instrucción mas rápida y compacta que sustituye a este plazamiento. Su sintaxis es
también en una unidad. El resulta se trunca al número de bits del
LEA registro,mem16 mem16 es un operando de memoria de tipo palabra. Por ejemplo
LEA DX,[BX+SI+20]
transfiere a DX el desplazamiento BX+SI+20. La variante LDS es si-
milar. Su sintaxis es LDS reg16,mem32
de orden mas bajo en el registro especificado, y los mas altos en
Lee una palabra doble de 32 bits de la memoria y carga los 16 bits
Supongamos que queremos cargar el segmento de Tabla_, definida co-
DS. Similar a la anterior es LES: funciona exactamente igual salvo que los 16 bits mas altos los guarda en ES.
MOV AX,SEG Etiqueta
mo Etiqueta DD Tabla_ en DX, y su desplazamiento en BX. Una forma de hacerlo es mediante la serie MOV BX,DESPL Etiqueta MOV DX,AX
ra incrementa el operando en una unidad. La segunda lo decrementa
La mejor forma de hacerlo es mediante LDS BX,Etiqueta 4.2. Instrucciones aritméticas. Las instrucciones aritméticas mas simples son INC y DEC. La prime-
de menor tamaño. En este caso pondríamos a cero BH mediante una
operando. Así, si todos los bits del operando están a 1, el opera-
dor INC los pasará a todos a cero. El bit adicional necesario para
nunca modificará AH.
representar el resultado correcto se pierde. De esta forma, INC AL Las instrucciones suma y resta son ADD y SUB, y su sintaxis es
almacenado en destino. En el segundo, fuente se resta de destino,
ADD destino,fuente SUB destino,fuente En el primer caso, se suma fuente a destino, y el resultado queda
de aritmética sobre número fijo de bits, los acarreos se pierden.
y el resultado queda almacenado en destino. En principio, los ope- randos fuente y destino han de ser del mismo tamaño, y al tratarse
ADD BL,AX. En estos casos se procede a la extensión del operando
A veces sin embargo es necesario operar sobre números de distinto tamaño en bits. Por ejemplo, no es posible escribir directamente
el operando, y puede ser un registro de 8 bits o un operando de
instrucción MOV o mediante un XOR. Pero esto es válido solo cuando
estamos tratando con números sin signo. Para extender un número
CWD (Convert Word to Double word).
con signo se recurre a los operadores CBW (Convert Byte to Word) y
se hace entre AL y un operando cualquiera de ocho bits, registro o
Las instrucciones de multiplicación y división son MUL y DIV, y usan el acumulador en todos los casos. La multiplicación de 8 bits
El resultado es de 32 bits, de los cuales los 16 menos significa-
memoria, y el resultado es de 16 bits, quedando almacenado en AX. ¿Que ocurre cuando se multiplica AX por otro operando de 16 bits ? tivos se almacenan en AX y los mas significativos en DX.
sin signo MUL operando
Cuando se divide un operando de 16 bits entre otro de 8, se obtie- ne un cociente de 8 bits y un resto también de 8 bits. El dividen- do se ha de encontrar en AX, mientras que el divisor se indica en
memoria. El cociente se devuelve en AL y el resto en AH. En forma
simbólica podríamos poner AX ¦ Divisor +------
Cuando se divide un número de 32 bits entre otro de 16 bits, co-
AH AL
de encontrarse en DX, y los menos significativos en AX. El divisor
ciente y resto son de 16 bits. Los 16 bits mas significativos han
gistro de 16 bits o un operando de memoria de 16 bits. El cociente
se indica en el operando, y al igual que antes, puede ser un re- de 16 bits se devuelve en AX, y el resto en DX. Simbólicamente:
cación y división. Uno para operandos con signo y otro para ope-
DX¦AX ¦ Divisor +------ DX AX Existen en realidad dos juegos de instrucciones para la multipli-
instrucciones a utilizar. La sintaxis es:
randos sin signo. Es el programador quien decide si los operandos representan números con signo o sin signo, y por tanto el juego de DIV operando
Si el resultado es distinto de cero, el bit n-simo de reg se esta-
con signo IMUL operando
IDIV operando
Otro conjunto de instrucciones son las de manipulación de bits,
que a su vez puede dividirse en operaciones lógicas, de desplaza-
miento y de rotación. Expondremos sólo las primeras. Estas son
lógicas del mismo tamaño. La sintaxis es
AND, OR y XOR y efectúan las mismas operaciones que las funciones AND destino,fuente OR destino,fuente
quier registro: XOR reg,reg es igual que MOV reg,0 , pero es mas
XOR destino,fuente La instrucción XOR es especialmente útil para poner a cero cual- rápida.
ejemplo, para comprobar si el bit n-simo de un registro se encuen-
La instrucción AND pone a cero ciertos bits, de forma que se puede efectuar una determinada operación con el resto de los bits. Por
4.3. Instrucciones de transferencia de control
tra a 1, basta hacer AND reg,mascara, donde mascara es un número binario donde todos los bits son cero, menos el n-simo, que vale 1. ba a uno.
[destino] es la dirección de comienzo. La última instrucción de un
Las instrucciones que conforman un programa se almacenan en orden
correlativo en la memoria, pero, salvo en los casos mas sencillos,
distintas partes de la secuencia. Las instrucciones de control se
no se ejecutan linealmente, sino que el control se transfiere a pueden dividir en: . Transferencia incondicional
4.3.1. Transferencia incondicional
. Transferencia condicional . Bucles Analizaremos cada uno de estos grupos, presentando las instruccio- nes mas frecuentes.
conjunto de instrucciones que se ejecutan mas de una vez pero que
Dentro del primer grupo contamos con las instrucciones CALL, RET y JMP. La primera se usa para llamar a un procedimiento, esto es, un se escriben una sola. Este conjunto de instrucciones se almacenan
procedimiento es RET, que devuelve el control al programa princi-
en memoria a partir de una posición dada, y cada vez que se nece- sita ejecutarlas, se transfiere el control a la primera instruc- ción de la serie mediante la instrucción CALL [destino], donde
instrucciones siguientes
pal. Cuando se llama a CALL, la primera tarea que realiza es guar-
dar en la pila la dirección de la siguiente instrucción, para re-
procedimiento. El operando de CALL es habitualmente una etiqueta ,
cuperarla y continuar el programa cuando se termine de ejecutar el indicando la dirección origen del procedimiento, pero también pue-
de CALL y RET es:
den hacerse llamadas indirectas a través de un registro o un ope- rando de memoria. No entraremos en este punto. El esquema general CALL etiqueta instrucciones siguientes .
Es posible anidar procedimientos, de forma que un procedimiento
. etiqueta: MIPROC PROC instrucciones siguientes . RET MIPROC ENDP pueda llamar a otro, y así sucesivamente. El nivel de anidamiento
MIPROC1 PROC
solo está limitado por el tamaño de la pila, donde se guardan las direcciones de retorno. Por ejemplo: CALL etiqueta1 instrucciones siguientes . . etiqueta1: . CALL etiqueta2
efectúa el salto, se consumen solo tres ciclos de reloj. Los sal-
.
RET
MIPROC1 ENDP
etiqueta2:
instrucciones siguientes
MIPROC2 PROC .
MIPROC2 ENDP
. RET
La instrucción JMP (jump, saltar) se usa para transferir el con-
trol al punto del programa que se desee. Cuando la dirección des-
salto, este se llama corto. En caso contrario, cercano, si destino
tino se encuentra en el rango -128,127 bytes de la instrucción de se encuentra dentro del mismo segmento y lejano si se encuentra en
4.3.2. Transferencia condicional
otro segmento. Los saltos lejanos se generan especificando el seg- mento y desplazamiento del destino. El juego de instrucciones para transferencia condicional es espe-
programas de forma que, siempre que sea posible, se ejecute el ca-
cialmente rico. El ensamblador reconoce algunas instrucciones de transferencia condicional con varios mnemónicos, con objeto de fa- cilitar la tarea al programador. Es un buen hábito construir los
Casi todas las veces, las condiciones de salto en un programa son
so esperado si no se efectúa el salto. La razón es que, si no se tos condicionales son siempre cortos, y su sintaxis es
donde [mnemonico] es de una a tres letras y destino_corto es una
J[mnemonico] destino_corto
etiqueta situada en el rango -128,127 bytes desde la instrucción
de salto. Las únicas condiciones que pueden comprobarse son el es-
nales se refieren a la última operación efectuada. Existen tantas
tado de los flags, lo que equivale a decir que los saltos condicio- instrucciones de salto como flags, pero las mas utilizadas son
tos se puede superar usando la instrucción JMP. Consideremos las
JZ salta si cero JNZ salta si no cero La limitación de los saltos condicionales de que sean saltos cor-
en generar un salto con la condición contraria por encima de un
instrucciones J[x],JN[x], donde J[x] salta si el flag "x" está a uno y JN[x] salta si el flag "x" está a cero. La técnica consiste JMP a la dirección deseada. Por ejemplo, para implementar
JB destino[fuente
J[x] etiqueta_lejana escribimos JN[x] etiqueta JMP etiqueta_lejana etiqueta:
del tipo A]B , A[B , A=B , A[]B , A]=B y A[=B. Por exigencias de
la aritmética de complemento a dos, existen en realidad dos juegos
de instrucciones, según que se comparen números con signo o sin él.
Para comparaciones de números sin signo, se emplean en los mnemó- nicos las letras A (de Above, por encima) y B (de Below, por deba-
tantes comprueban los flags de cero, acarreo y desbordamiento, que
jo), y para las comparaciones de números con signo las letras G (de Greater, mayor) y L (de Less, menor). Las instrucciones resul- han sido previamente establecidos mediante una instrucción CMP. La
BX[AX, las instrucciones adecuadas son
sintaxis de esta instrucción es CMP destino,fuente y compara destino con fuente. Por ejemplo, si queremos comparar los números sin signo contenidos en AX y BX y saltar a etiqueta si CMP BX,AX
JNE destino[]fuente
JB etiqueta y si los números tienen signo, la secuencia es: CMP BX,AX JL etiqueta Los mnemónicos mas usados son .para números sin signo JA destino]fuente JE destino=fuente
denas o para buscar un valor concreto en una zona de memoria.
JBE destino[=fuente
JAE destino]=fuente
JG destino]fuente
.para números con signo
JNE destino[]fuente
JE destino=fuente
JLE destino[=fuente
JL destino[fuente
4.3.3. Instrucciones de bucle
JGE destino]=fuente
Las instrucciones de bucle hacen que se repitan fragmentos de có-
digo un número prefijado de veces. Una forma de hacerlo es median-
comienzo:
te el contador y un salto condicional al final del bucle MOV CX,repeticiones . .
señada para este propósito:
. DEC CX JNZ comienzo Este fragmento puede compactarse usando la instrucción LOOP, di-
LOOP comienzo ; si CX[]0, salta a comienzo
MOV CX,repeticiones comienzo: . . .
Las instrucciones de cadena se utilizan habitualmente para inicia-
; de lo contrario, sigue en esta línea 4.4. Instrucciones de cadena.
trucción LODS. La instrucción mas usada es MOVS (MOVe String), la
lizar una zona de memoria a un mismo valor, para mover un bloque contiguo de datos de una zona a otra de memoria, para comparar ca-
El funcionamiento de este conjunto de instrucciones depende del
"flag de dirección", cuyo valor puede ser alterado por las dos ins-
trucciones siguientes CLD: CLear Direction flag
Las instrucciones de cadena tienen mnemónicos que terminan con la
STD: SeT Direction flag
da caso. Ya que pueden actuar sobre bytes o palabras, es necesario
letra "S", y operan sobre los registros que se especificarán en ca-
La instrucción LODS (LOaD String), en sus versiones LODSB y LODSW,
indicar este extremo, lo que se conseguirá escribiendo la letra "B" o "W" tras la "S" del mnemónico.
cero, SI se incrementa en 1 o 2, y si está a 1 se decrementa en 1
se usa para cargar un byte o palabra desde la dirección indica- da por DS:SI en AL o AX. Si el flag de dirección se encuentra a
de la misma forma que LODS y almacena el contenido del registro
o 2. De esta forma puede recorrerse la memoria en uno u otro sen- tido. La instrucción complementaria es STOS (STOre String). Se usa AL o AX en la dirección de memoria especificada por ES:DI. El re-
+-----------+ STOS
gistro DI se altera según la misma lógica que el SI con la ins- cual sirve para trasladar uno (MOVSB) o dos bytes (MOVSW).
Esta instrucción lee un dato de DS:SI y lo almacena en ES:DI. Des-
pués, los registro SI y DI se modifican según la misma lógica que
Para efectuar operaciones repetitivas con estas funciones, podemos
para las instrucciones LODS y STOS. implementar un bucle que repitiera un número prefijado de veces la
gestionar explícitamente los registro SI y DI porque estos se ac-
operacion a realizar con estas instrucciones. No sería necesario tualizan automáticamente. Sin embargo, el lenguaje ensamblador
cadena que vayamos a usar, antes de la misma. Obsérvese el frag-
permite hacer esto mismo de forma mas compacta mediante la ins- trucción REP. Esta instrucción se coloca en la misma línea que la instrucción de mento de código siguiente:
MOV DI,5678H ; desplazamiento. Dirección de comienzo
CLD ; incrementa DI cada vez MOV AX,1234H ; segmento en que escribe MOV ES,AX ; STOS almacena en ES:DI XOR AL,AL ; pone AL a cero
los siguientes:
MOV CX,200D ; inicializa CX a 200D REP STOSB ; ejecuta 200D veces la orden STOSB ; ahora, CX=0 y DI=5678H+200D En resumen: ¦ AX ¦ AL ¦ -----------] ES:DI [----+
+-----------+ ¦
MOVS
+-----------+ LODS ¦
+-----------+
¦ AX ¦ AL ¦ [----------- DS:SI -----+
comparar dos cadenas. Sus mnemónicos son SCAS (SCAn String),y CMPS
Existen dos instrucciones más que permiten examinar una cadena y
La instrucción SCASB es equivalente a CMP AL,ES:[DI], mientras que
(CoMPare String). Ambas admiten las "versiones" para byte y pala- bra añadiendo las terminaciones B y W.
las operaciones anteriores.
SCASW es equivalente a CMP AX,ES:[DI]. El resultado de estas ope- ración altera los flags y DI se actualiza según la lógica vista en
tre DS:[SI] y ES:[DI], es decir, CMP DS:[SI],ES:[DI]. Al igual que
La sintaxis CMPSB o CMPSW es CMPS mem1,mem2, donde mem1 y mem2 son operandos de memoria. En concreto, CMPS realiza la comparación en- en el caso anterior, estas instrucciones alcanzan su máxima utili-
REPNE (REPeat while Not Equal).
dad al usarlas en combinación con los operadores REPZ (REPeat whi- le Zero, repetir mientras cero) y REPNZ (REPeat while Not Zero). REPZ y REPNZ admiten los sinónimos REPE (REPeat while Equal) y Los usos mas comunes de las instrucciones que hemos presentado son
ENTRADA: AH=2 (nº de servicio)
* Encontrar el primer elemento distinto del contenido del acu-
mulador dentro de un bloque. Para esto se usa REPZ SCAS.
usa REPZ CMPS.
* Encontrar el primer elemento diferente entre dos cadenas. Se
* Encontrar el primer elemento igual entre dos cadenas: REPNZ
* Encontrar la primera ocurrencia del contenido del acumulador dentro de un bloque: REPNZ SCAS. CMPS.
efecto, el PC almacena en la ROM BIOS una enorme cantidad de proce-
5.- USO DE INTERRUPCIONES La filosofía del PC es ésta: dejar que la BIOS haga el trabajo. En
determinada interrupción. Cada interrupción tiene un número y ofre-
dimientos que podemos usar en nuestro provecho, simplemente invo- cándolos. El lenguaje ensamblador permite pasar el control a una
ción puede o no devolver valores.
ce diversos servicios. El número de servicio se especifica en AH, y en otros registros se especifican otros parámetros. La interrup- La instrucción en ensamblador que permite ejecutar interrupciones
lumna determinadas. En este caso:
es INT, y su sintaxis es INT [nº función]. Por ejemplo, la función 10H tiene muchos servicios útiles para controlar el video. Uno de estos servicios consiste en posicionar el cursor en una fila y co- BH=página de video en la que fijar posición
MENSAJE DB 'ESTO ES UN MENSAJE $'
DH=fila DL=columna
Por ejemplo, para colocar el cursor en la fila 10, columna 15, el
SALIDA: No tiene
MOV AH,2 ; nº de servicio
fragmento de código apropiado sería
MOV DH,0AH
MOV BH,0 ; suponemos que 0 es el nº de página activa MOV DL,0FH INT 10H
y servicios de la ROM BIOS. La lista de funciones es tan extensa
Existe abundante bibliografía donde se recogen todas las funciones que puede hacer creer que el emsamblador es mas complicado de lo
escribir un programa en ensamblador con la dificultad para retener
que lo es realmente, al menos al nivel que será usado en este curso. Pero el alumno no deberá confundir la dificultad para o incluso solo localizar la función que en un momento dado sirva a
- Siempre será preciso terminar un programa, para lo que se recurre
nuestros propósitos. Solo a modo de ilustración, se exponen a continuación las funciones mas usuales que aparecen cuando se empieza a programar en ensamblador: a la funcion 4CH de INT 21H: MOV AH,4CH
donde [MENSAJE] se ha definido en el segmento de datos mediante
INT 21H - Casi siempre será preciso mandar mensajes a la pantalla, para lo que se usa la función 9: MOV DX,OFFSET [MENSAJE] MOV AH,9 INT 21H una linea del estilo de
standard:
y $ es el carácter que necesita la función 9 para identificar el
final de la cadena.
no en cada línea, y por eso se añaden al mensaje los caracteres
Cuando hay varios mensajes que mostrar, lo normal es escribir u-
MENSAJE DB 'ESTO ES UN MENSAJE',10,13,'$'
10 y 13, que significan respectivamente salto de línea y salto de carro:
de INT 10H realiza el trabajo. Para ello, BH contendrá el núme-
- Cuando se quiere mostrar un mensaje, muchas veces se desea colo- carlo en una posición determinada de la pantalla. La función 02H
- Ocurre casi siempre que al iniciar un programa deseamos limpiar
ro de la página de pantalla, DH la línea y DL la columna, de 0 a 24 y de 0 a 79 respectivamente. la pantalla. Para ello, sobreescribimos con espacios en blanco y
MOV DI,0 ; apuntamos ES:DI al inicio de la RAM de video
los atributos que deseemos la RAM de video, que en adaptadores a color comienza en la direccion 0B800H: MOV AX,0B800H MOV ES,AX MOV AL,32 MOV AH,07H ; carácter 32, gris sobre negro
- Tambien es frecuente leer una cadena de caractéres de la entrada
MOV CX,2000 ; 2000 caracteres REP STOSW - Casi siempre será preciso leer un carácter desde teclado, de lo que se encarga la función 1. El resultado queda almacenado en AL: MOV AH,1 INT 21H MOV AH,3FH
En el apéndice A se da una relación de las funciones BIOS.
MOV BX,0 MOV CX,[LONGITUD MAXIMA]
MOV DX,[DESTINO DE LA CADENA]
INT 21H AND AX,AX
3FH es la función del DOS que permite leer cadenas. Si BX=0, se
leen desde entrada standard, que es el teclado. La longitud
[DESTINO DE LA CADENA] que es OFFSET [VARIABLE DE CADENA]. Como
máxima se encuentra en CX, y la cadena leida va a parar a AX guarda la longitud de la cadena leida, AND AX,AX comprueba si
MOV CX,[LONGITUD CADENA]
se ha leido algún carácter. - Igualmente frecuente es la escritura de una cadena en la salida standard: MOV AH,40H MOV BX,1
MOV DX,OFFSET [CADENA]
INT 21H

Unidad No.3: Mejora programa # 9: Letras de colores(Versión Ingrid Sauceda)

Ejecución del programa: Código: include 'emu8086.inc' Mostrar Macro Mensaje     LEA DX,Mensaje ;mandamos el mensaje a leer     MO...