You are on page 1of 154

CAPITULO 12

PROCEDIMIENTOS

En el captulo 6, aprendiste como utilizar un programa con procedimientos, en este captulo


aprenders a usar las directivas e instrucciones que definen y llamas procedimientos. Despus de cubrir
estos conceptos bsicos, pasar informacin entre procedimientos y linkear partes separadas en un
programa completo.
Nuevos Trminos
Parmetros. Un campo dato que es mandado de un procedimiento a otro.
Paso. Mandar un campo dato de un procedimiento a otro.
Parmetro de entrada. Un parmetro pasado del procedimiento que hace la llamada al procedimiento
invocado.
Parmetro de salida. Un parmetro pasado del procedimiento que fue llamado de regreso al
procedimiento que invoco.
Tabla de salto. Una lista de direcciones, cada una representa una locacin a la cual el programa puede
saltar.
12.1 Disear procedimientos que usan procedimientos.
Un buen diseador de programas divide un programa en procedimientos. Por ejemplo, digamos que
quieres escribir un programa que cuenta el nmero de lneas en un archivo. El programa puede consistir
de un procedimiento principal que procese cada lnea. Este proceso podra llamar uno o dos
procedimientos, uno de lectura de lneas del archivo y uno que despliegue los resultados.
Aqu hay algunas reglas que puedes seguir para dividir un programa:
Disea tus programas para que cada procedimiento ejecute solo una funcin.
Haz procedimientos pequeos.
En lenguaje ensamblador, cada procedimiento est definido por las directivas PROC y ENDP. Un
procedimiento es llamado por una instruccin CALL y regresa al programa que hizo la llamada
ejecutando una instruccin RET.

12.2 Definir un procedimiento: PROC y ENDP.


Cada procedimiento debe estar definido entre las directivas PROC y ENDP, estas no generan cdigo
mquina, en su lugar PROC y ENDP son direcciones que le indican al ensamblador el inicio y el fin de un
procedimiento.
Este es el formato de la directiva PROC
1

nombre

PROC

tipo

El nombre es cualquier nombre que desees darle al procedimiento, diferente de un nombre reservado. El
tipo puede ser NEAR y FAR. Si el procedimiento es llamado por un procedimiento que reside en un
segmento diferente, debes especificar el tipo como FAR. De otra forma usa el tipo NEAR. Si no
especificas un tipo, el tipo por omisin es NEAR. Usualmente slo debes especificar el tipo de un
procedimiento si es FAR. Es importante recordar que DOS inicia un programa de ensamblador llamando
al programa principal. Entonces ya que DOS est en un segmento diferente, el procedimiento principal de
cada programa debe ser de tipo FAR.
La directiva ENDP marca el final de cada procedimiento. El formato es:
nombre

ENDP

El nombre debe ser el mismo que tenga el principio del procedimiento, por ejemplo
DISPLAY
PROC
-- sentencias -DISPLAY
ENDP
Aqu hay un esqueleto de un procedimiento. El procedimiento se llama DISPLAY y es de tipo NEAR:
; inicio de procedimiento: DISPLAY
DISPLAY
PROC
;

-- sentencias ---

; fin de procedimiento: DISPLAY


DISPLAY
ENDP

12.3 El formato de un Procedimiento.


Estrictamente hablando, las directivas PROC y ENDP son todo lo necesario para definir un
procedimiento. Sin embargo, hay otros estatutos que son usados de rutina.
Primero, es til que cada procedimiento se imprima en una pagina nueva, use la directiva PAGE al
principio del procedimiento.
Segundo, cada procedimiento debe estar documentado con los siguientes comentarios estndar:
El nombre del procedimiento
El propsito del procedimiento
Que parmetros de entrada necesita el procedimiento
Que salida genera el procedimiento
Que otros procedimientos invoca
2

Tercero, cada procedimiento debe salvar y restaurar todos los registros como parte su funcin. Esto se
hace con las instrucciones PUSHA y POPA (ver capitulo 9).
Cuarto, cada procedimiento debe finalizar con la instruccin RET para regresar al programa que hizo la
llamada.
La figura 12-1 muestra el esqueleto de un procedimiento tpico que puedes usar como modelo. El
procedimiento se llama DISPLAY y es de tipo NEAR.
Figura 12-1 El esqueleto de un procedimiento
PAGE
;----------------------------------------------------------------------------------------; DISPLAY
;
; Proposito:
;
-el proposito del procedimiento va aqu
;
; Entrada:
;
-la descripcion de la entrada va aqui
;
; Salida:
;
-la descripcin de la salida va aqu
;
; Procedimientos:
;
-la descripcin de los procedimientos a llamar va aqu
;----------------------------------------------------------------------------------------; inicio del procedimiento: DISPLAY
DISPLAY
PROC
; salvar los registros
PUSHA
; Las instrucciones del procedimiento van aqu
; restaurar registros
POPA
; regresar al procedimiento principal
RET
; fin del procedimiento: DISPLAY
DISPLAY
ENDP

12.4 Llamar a un procedimiento: CALL.


Para llamar a un procedimiento, usa la instruccin CALL. Este es su formato:
CALL

direccin

La direccin puede ser directa o indirecta. Usualmente, la direccin es simplemente el nombre del
procedimiento, por ejemplo:
CALL

DISPLAY

Aqu hay un ejemplo de un direccionamiento indexado. En este ejemplo TABLA[BX] contiene la


direccin del procedimiento;
CALL

TABLA[BX]

Muchas de las veces es ms simple que utilices el nombre, el direccionamiento indirecto e indexado te
permite hacer llamadas ms complejas. Estas se revisaran ms adelante en la seccin tablas de salto.

12.5 La direccin de Regreso.


Como mencione en el captulo 3, la direccin de regreso es la locacin a la cual el procedimiento
regresa cuando su ejecucin termina. Esta direccin de regreso es metida a la pila por la instruccin
CALL. As la instruccin CALL ejecuta lo siguiente:
Meter la direccin de regreso en la pila
Saltar a la direccin del procedimiento.
Cuando el procedimiento que fue llamado regresa, el procesador espera encontrar la direccin de regreso
en la pila.. El procesador pone la direccin de regreso como la direccin inmediata a la instruccin
CALL.
Si una llamada a un procedimiento de tipo FAR, el procesador mete una direccin completa en la pila
(direccin del segmento y offset).
12.6 Reglas para usa la instruccin CALL.
Existen dos reglas que debes seguir para indicarle al ensamblador si un procedimientos NEAR o
FAR:
Primero, cuando definas un procedimiento que ser llamado en otro segmento, debes especificar el
procedimiento de tipo FAR.
Segundo, si hay alguna ambigedad en la instruccin CALL, debes indicarle al ensamblador si la
direccin representa una direccin completa (FAR) o slo un desplazamiento (NEAR). Est situacin se
presenta cuando usas una direccionamiento indirecto, esto es, cuando el operando de la instruccin CALL
contiene la direccin del campo dato que contiene la direccin del procedimiento.
Aqu hay un ejemplo. Digamos que declaras un campo dato llamado ADDR1 que contenga la direccin
del procedimiento a llamar. Si el procedimiento es NEAR y su nombre es DISPLAY1, puedes definir la
directiva del dato as:
ADDR1

DW

DISPLAY1

El ensamblador puede inicializar ADDR1 para el offset de DISPLAY1. Debido a que el offset es una
palabra en longitud, debemos usar la directiva DW para declarar ADDR1 como una palabra.

Sin embargo, digamos que tenemos otro campo dato, ADDR2, que contiene la direccin de un
procedimiento FAR llamado DISPLAY2. Es este caso, ADDR2 debe contener la direccin del segmento
y el offset. As debemos definir ADDR2 como una palabra doble:
ADDR2
DD
DISPLAY2
Si ADDR1 y ADDR2 contiene las direcciones de los procedimientos, podemos usar estos valores con
direccionamiento indirecto. En otras palabras, debemos decirle al procesador que para llamar a los
procedimientos sus direcciones estn contenidas en ADDR1 y ADDR2. Para hacer esto, copia las
direcciones a un registro especifico, encerrado entre parntesis cuadrados, como el operando de la
instruccin CALL. Usaremos el registro BX.
Debemos asegurarnos que el ensamblador sabe cuando BX est apuntando a una direccin NEAR (una
palabra) o a una direccin FAR (una palabra doble). Para hacer esto, usamos el operador PTR. Si un
direccionamiento indirecto apunta a un offset, usamos WORD PTR. Si un direccionamiento indirecto
apunta a un direccin completa, usamos DWORD PTR.
Con el ejemplo anterior usamos un apuntador NEAR (ADDR1), puede usar la instruccin:
LEA
CALL

BX,ADDR1
WORD PTR [BX]

La primera instruccin copia el offset de ADDR1 a BX. La segunda llama al procedimiento cuya
direccin est contenida en el campo dato al cual BX est apuntando. Debido a que est es una llamada
NEAR, debemos decirle al ensamblador que el campo dato tiene una longitud de palabra.
Con el ejemplo del procedimiento apuntando a un FAR (ADDR2), podemos usar las siguientes
instrucciones:
LEA
CALL

BX,ADDR2
DWORD PTR [BX]

Debido a que esta llamada es FAR, debemos especificar que el campo dato al cual BX esta apuntando es
una palabra doble.
Esta tcnica es til si quieres obtener la direccin de una instruccin CALL mientras el programa se
ejecuta.

12.7 Regresar de un procedimiento: RET.


Debes asegurarte que cada procedimiento regrese al lugar de donde fue llamado. (Hasta el programa
principal que regresa a DOS). Para esto use la instruccin RET. Este es su formato:
RET

valor-pop

El valor-pop es un valor inmediato descrito despus en la seccin intitulada Sacar parmetros de la pila.
Muchas de las veces la instruccin RET no necesita operando.
La instruccin RET espera la direccin de regreso que est en el tope de la pila. La instruccin hace lo
siguiente:
5

Saca la direccin de regreso de la pila


Salta a la direccin de regreso
Si el procedimiento es de tipo FAR, el procesador debe sacar dos palabras de la pila. Si el procedimiento
es de tipo NEAR, el procesador necesita sacar solo una palabra de la pila. El ensamblador coloca
instrucciones diferentes RET cuando detecta si un procedimiento en NEAR o FAR, estas instrucciones le
indican si tiene que recuperar una o dos palabras de la pila.

12.8 Puntos de Entrada y Salida.


Como mencione en el captulo 6, la direccin en la cual el procedimiento inicia es llamado el punto
de entrada. Cada procedimiento - incluyendo el programa principal - deben tener al menos un punto de
entrada y una instruccin RET.
Es posible que un procedimiento tenga ms de un punto de entrada pero no es recomendable.
Algunos procedimientos pueden tener uno o ms puntos de salida lgica, como por ejemplo si se detecta
una entrada invalida. En tales casos debes saltar a la instruccin RET al final del procedimiento, esto
asegura que solo se tenga un punto de regreso.
Disea tus procedimientos para que tengan un slo punto de entrada y salida como lo muestra la figura
12-2.
Figura 12-2 Los puntos de entrada y salida

12.9 Paso de Parmetros en Registros.


Los procedimientos se comunican mandando datos de envo y regreso. Estos campos dato son
llamados parmetros . Podemos decir que un procedimiento pasa parmetros de un procedimiento a otro.
Un parmetro de entrada es pasado por el procedimiento que llama y un parmetro de salida es
regresado cuando el procedimiento llamado termina.
Existen dos mtodos estndar para paso de parmetros. Primero si hay pocos parmetros a pasar se
pueden usar los registros. Por ejemplo digamos que el procedimiento ADD_LIST suma una lista de
nmeros. ADD_LIST requiere dos pedazos de informacin: el tamao de la lista y la direccin de la lista.
Un modo comn es que reciba el tamao en el registro AX y la direccin en el BX.

Digamos que las variables LIST y CONT representan la lista y su tamao. La llamada al procedimiento
podra ser as:
; poner los parametros de entrada para ADD_LIST
MOV
AX,CONT
LEA
BX,LIST
; llamar al procedimiento
CALL
ADD_LIST
Al principio del procedimiento ADD_LIST pondramos estos comentarios:
;
;
;

Entrada:
AX -- el nmero de campos de la lista
BX -- la direccin de la lista a ser sumada

Un procedimiento tambin puede pasar parmetros de salida en los registros. Sin embargo el
procedimiento debe poner los parametros despus de que los registros sean restaurados; o de otra manera
el comando POPA sobrescribira los valores de los parmetros.
Por ejemplo, digamos que ADD_LIST guarda el resultado de la suma en la variable SUM. Este valor ser
pasado al procedimiento que invoco in el registro CX.
; restaurar registros
POPA
; actualizar el parmetro de salida
MOV
CX,SUM
; regresar al procedimiento anterior
RET
Al principio del procedimiento habra estos comentarios:
;
;

Salida:
CX -- la suma de la lista

12.10 Pasar Parametros de Entrada por medio de la Pila.


Si no hay suficientes registros para pasar los parmetros lo mejor es utilizar la pila. El
procedimiento que llama empuja los valores a la pila. El procedimiento invocado accesa la pila
directamente, haciendo innecesario el uso de registros. El procedimiento llamado puede entonces
modificar los valores en la pila en orden de pasar los parametros de regreso al procedimiento que llamo.
Se deben meter los parametros en la pila antes de hacer la llamada. Aqu hay un ejemplo de la llamada a
un procedimiento, llamado CALCULO, el cual requiere 6 parametros. Los parametros son nombrados de
p1 a p6, y en la prctica pueden ser registros, campos dato o valores inmediatos.
; poner parametros de entrada para CALCULO
PUSH
P1
PUSH
P2
PUSH
P3
7

PUSH
PUSH
PUSH
; llamar a CALCULO
CALL

P4
P5
P6
CALCULO

12.11 Usar el registro BP para accesar los Parametros de la Pila.


Accesar los parametros de la pila es ms complicado. Esto es debido a que la instruccin CALL
ejecutada despus de la introduccin de los parametros de entrada. Esto significa que el procedimiento
invocado no puede sacar de la pila los parametros sin perder la direccin de regreso.
Por supuesto, es posible sacar la direccin de regreso, guardarla y despus recuperar los parametros, sin
embargo hay una forma ms sutil de hacer esto, la cual es accesar la pila directamente usando el registro
BP.
Esto funciona as, al principio del procedimiento invocado, la direccin del tope de la pila se copia al
registro BP usando la instruccin:
MOV

BP,SP

El procedimiento puede usar ahora a BP como la direccin base de la pila. En particular, los parametros
pueden ser seleccionados como [BP+2], [BP+4], [BP+6], etc.
Si la pila consiste de una lista de palabras con una en su propio espacio. El registro SS mantiene la
direccin del segmento. El registro SP contiene un offset en el segmento. SP apunta al tope de la pila.
El primer push copia datos a la palabra en la direccin ms alta, el siguiente push copia datos en la
siguiente direccin ms alta, y as la pila crece hacia abajo hasta su base una palabra a la vez.
La figura 12-3 muestra la pila con seis parmetros de entrada, un procedimiento ha sido llamado y BP
est puesto a SP.
Figura 12-3 Seis parametros en la pila

La figura 12-3 muestra a la pila despus de haber metido seis parametros a ella, un procedimiento ha sido
invocado, y BP y SP estn direccionadas.
8

Como puedes ver, Una vez que BP est puesta a SP, los parmetros pueden ser accesados como
SS:[BP+2], SS:[BP+4], etc. Entonces el procesador asume que te refieres al segmento de pila y usa BP
con su incremento como offset.
Una vez que BP est direccionado, el procedimiento puede empujar ms datos en la pila y cambiando el
valor de SP. Sin afectar el acceso a los parametros. De hecho esto sucede cuando la instruccin PUSHA
salva los registros al inicio de un procedimiento.
Esto es ilustrado en la figura 12-4. El diagrama muestra a la misma pila despus de que el procedimiento
ha metido los valores de los registros. Note que BP permanece sin cambio para el acceso a los
parametros.
Figura 12-4 BP sin cambio en la Pila

Para ilustrar esto, aqu hay un ejemplo de algunas instrucciones que estaran al inicio de un procedimiento
que espera seis parametros metidos en la pila. Este ejemplo copia los valores de los parametros a los
registros. Note que BP debe ser copiado a BP antes de salvar los registros, (debido a que el comando
PUSHA cambia el valor de SP):
; inicio del procedimiento: CALCULO
CALCULO
PROC
; apuntar BP al tope de la pila
MOV
BP,SP
; salvar registros
PUSHA
; copiar los parametros de entrada a los registros
MOV
AX,[BP+12]
MOV
BX,[BP+10]
MOV
CX,[BP+8]
MOV
DX,[BP+6]
MOV
DI,[BP+4]
MOV
SI,[BP+2]
9

Un ltimo punto: La discusin anterior supone que el procedimiento es de tipo NEAR. En otras palabras,
la direccin de regreso ocupa 1 palabra en la pila, si el procedimiento fuera FAR, la direccin de regreso
sera de 2 palabras en la pila, y las direcciones de los parmetros seran [SP+4], [SP+6], [SP+8], etc.

12.12 Regresar Parametros usando la Pila.


Es posible usar la pila para regresar parametros de salida al procedimiento que llamo. Sin embargo
no es posible meterlos a la pila, ya que quedaran sobre la direccin de regreso. Mejor usa directamente el
registro BP para accesar la pila directamente y modificar los parametros de entrada directamente. Cuando
regrese el procedimiento que llamo puede examinar esos valores.
Aqu hay un ejemplo usando los procedimientos MAIN y CALCULO descritos antes. MAIN empuja seis
parametros en la pila. CALCULO usa estos valores para ejecutar los clculos y entonces copia los
resultados en el ltimo parmetro metido a la pila, usando BP para accesarla directamente.
Si AX contiene el valor del parmetro de salida, la secuencia puede ser as:
; salvar el parmetro de entrada
MOV
[BP+2],AX
; restaurar los registros
POPA
; regresar al MAIN
RET
As, la entrada de la pila que reside en [BP+2] ha sido transformada de parmetro de entrada a parmetro
de salida. Despus del retorno, MAIN podra sacar de la pila para examinar el resultado. As su secuencia
podra ser:
; poner los parametros de entrada en la pila
PUSH
P1
PUSH
P2
PUSH
P3
PUSH
P4
PUSH
P5
PUSH
P6
; llamar al procedimiento CALCULO
CALL
CALCULO
; copiar el resultado a AX
POP
AX
; sacar el resto de los parametros de entrada
POP
TEMP
POP
TEMP
POP
TEMP
POP
TEMP
POP
TEMP
10

Note que el MAIN debe sacar todos los parmetros que meti, en este caso con un campo dato temporal
TEMP.

12.13 Sacar parametros de la Pila


En el ltimo ejemplo de la seccin anterior, el programa que hacia la llamada examinaba los
parametros de salida sacando de la pila despus del regreso. Sin embargo en muchos casos, la pila puede
contener parametros de entrada pero no de salida.
En tales casos la instruccin RET puede sacar varios valores de la pila automticamente como parte del
regreso, puedes hacer esto especificando el nmero de bytes a ser sacados con un operando inmediato. El
formato de la instruccin RET es:
RET

valor-pop

Donde valor-pop es el nmero de bytes a ser sacados durante el retorno.


Aqu hay un ejemplo. Digamos que el procedimiento llamado MAIN llama a un procedimiento llamado
HAZ_TABLA para construir cierto tipo de tabla. HAZ_TABLA requiere seis parametros de entrada y
ninguno de salida.
; poner los parametros de entrada para HAZ_TABLA
PUSH
P1
PUSH
P2
PUSH
P3
PUSH
P4
PUSH
P5
PUSH
P6
; llamar a HAZ_TABLA para construir la tabla
CALL
HAZ_TABLA
Al final de HAZ_TABLA, puedes usar el siguiente estatuto para regresar al procedimiento MAIN:
; sacar los parametros de la pila y regresar a MAIN
RET
12
Este RET no solo regresa al procedimiento anterior, tambin saca 12 bytes de la pila. Por supuesto esto
debe estar perfectamente coordinado. La instruccin RET al final del procedimiento HAZ_TABLA debe
sacar el mismo nmero de bytes que fueron empujados por MAIN.
Para referencia, aqu estn los pasos que sigue un RET normal
Sacar la direccin de regreso
Saltar a la direccin de regreso
Cuando se especifican un nmero de bytes, estos son los pasos
11

Sacar la direccin de regreso


Sacar el nmero de bytes requeridos
Saltar a la direccin de regreso

12.14 Usar la bandera de Acarreo para indicar un Error.


Ya aprendimos dos modos de pasar informacin entre procedimientos, usando registros o la pila.
Estos dos mtodos son buenos para pasar datos. Sin embargo, existe un pedazo de informacin que
puedes querer pasar del procedimiento llamado al que hizo la llamada: Como se si todo termino
satisfactoriamente?
El modo estndar de determinar esto es limpiando a activando la bandera de acarreo. Si el procedimiento
llamado termino exitosamente, ponemos CF a 0. Si un error ocurri ponemos CF a 1. As el
procedimiento que hizo la llamada puede cerciorarse si todo sali bien.
Aqu hay un ejemplo. Un procedimiento MAIN llama a otro procedimiento READ_DATA para leer
algunos datos de un archivo. Si la operacin tuvo xito READ_DATA regresa 0 en CF. Si la operacin
fallo por alguna causa, READ_DATA pone CF a 1.
Aqu hay algunos estatutos que podras usar al final de READ_DATA para implementar el manejo de
errores:
; indicar que un error ha ocurrido
BAD_DATA:
STC
JMP
RETURN_READ_DATA
; indicar que no ocurri ningn error
GOOD_DATA:
CLC
; restaurar los registros y regresar al MAIN
POPA
RET
Dentro del procedimiento MAIN, digamos que un mensaje de error ser desplegado sin los datos no se
pueden leer.
; poner los parametros de entrada
-- las instrucciones de entrada van aqu --; llamar a READ_DATA para leer un archivo
CALL
READ_DATA
; checar el error
JC

DISPLAY_ERROR_MESSAGE

12

Bajo algunas circunstancias, no es suficiente saber que un error ocurri, sino saber que tipo de error fue
puedes regresar un cdigo de error en algn registro para que el procedimiento principal comunique cual
fue la falla.

12.15 Tablas de Salto.


Una tabla de salto es una lista de direcciones, cada cual representa una locacin a la cual un
programa puede saltar. La tabla de saltos son usadas comnmente para guardar una lista de direcciones de
varios procedimientos. Un programa puede usar tal tabla para escoger el procedimiento a llamar basado
en las condiciones actuales.
Aqu hay un ejemplo. Digamos que un programa procesa algunos datos y entonces escribe los datos como
salida. El programa puede escribir los datos a la impresora, pantalla, o a disco. Los procedimientos que
hacen esto son WRITE_PRINTER, WRITE_DISPLAY y WRITE_FILE respectivamente.
Despus los datos son procesados, el programa le pide al usuario que teclee el nmero del dispositivo de
salida. Este nmero es grabado en la variable OPCION, 1 para impresora, 2 para pantalla y 3 a disco. As
el programa necesita llamar a uno de tres procedimientos, basados en el valor de OPCION.
Un modo de hacer esto es usar un CASE:
; case OPCION=1: llamar a WRITE_PRINTER
; case OPCION=2: llamar a WRITE_DISPLAY
; case OPCION=3: llamar a WRITE_FILE
CMPOPCION,1
JE
L1
CMPOPCION,2
JE
L2
CMPOPCION,3
JE
L3
JMP
L4
L1:
; opcion=1
CALL
WRITE_PRINTER
JMP
L4
L2:
; opcion=2
CALL
WRITE_DISPLAY
JMP
L4
L3:
; opcion=3
CALL
WRITE_FILE
L4:
Un mtodo simple es usar una tabla de saltos. Primero ponemos una tabla en el segmento de datos que
contenga los offsets de los tres procedimientos:
JUMP_TABLE LABEL WORD
DW
WRITE_PRINTER
DW
WRITE_DISPLAY
DW
WRITE_FILE
Puedes hacer referencia a la direccin de estos procedimientos relativa al valor de JUMP_TABLE. Esto
es, basados en el valor de OPCION, podemos llamar al procedimiento correcto como sigue:
13

OPCION
1
2
3

Usa la direccin en
JUMP_TABLE+0
JUMP_TABLE+2
JUMP_TABLE+4

Aqu est el plan. Podemos copiar la direccin de la tabla de datos a un registro (BX por ejemplo).
Despus adicionamos 0, 2 o 4 al registro, dependiendo del valor de OPCION. Finalmente debemos usar el
contenido del registro con un direccionamiento indirecto para llamar al procedimiento apropiado.
Para copiar la direccin de la tabla de salto en BX, podemos usar la instruccin LEA
LEA

BX,JUMP_TABLE

Ahora, necesitamos adicionar 0,2 o 4 a BX dependiendo del valor de OPCION. La forma ms fcil es
copiar OPCION al registro AX, restarle 1 y multiplicarlo por 2:
MOV
DEC
SHL
ADD

AX,OPCION
AX
AX,1
BX,AX

Las instrucciones sern descritas en captulos posteriores.


Ahora BX apunta a la direccin correcta. Puedes usar direccionamiento indirecto para hacer la llamada:
CALL

WORD PTR [BX]

Pongamos todo junto:


; escribir a un dispositivo seleccionado por OPCION
;
1 -> impresora (llama a WRITE_PRINTER)
;
2 -> pantalla (llama a WRITE_DISPLAY)
;
3 -> archivo (llama a WRITE_FILE)
LEA
BX,JUMP_TABLE
MOV
AX,OPCION
DEC
AX
SHL
AX,1
ADD
BX,AX
CALL
WORD PTR [BX]
Note que es mucho ms fcil que usar el constructor CASE.
Si vas a usar tablas de salto, hay dos puntos importantes que debes comprender. Primero, en el ejemplo
anterior supusimos que el procedimiento es NEAR, por eso accesamos la tabla con multiplos de 2.
Si usas una tabla de saltos con direcciones FAR, debes hacer tres cambios. Definir la tabla de datos con
DD (palabras dobles). accesar la tabla de saltos en multiplos de 4. Puedes hacer esto con la instruccin
SHL as
SHL

AX,2

Tienes que asegurarte que la llamada al procedimiento es un del tipo doble palabra:
14

CALL

DWORD PTR [BX]

La segunda cosa importante que debes cmprender es que el valor que tenga opcin siempre debe
corresponder a algunas de las opciones en la tabla de salto, impidiendo que el selector tenga un valor
invalido.
12.16 Linkear programas que estn separados en varias partes.
Cuando escribes un programa grande, es til poder ensamblar el programa separadamente. Por
ejemplo digamos que un programa grande tiene 30 procedimientos. Si uno de los procedimientos tuviera
que ser cambiado ocasionalmente tendramos que rensamblar el programa completo.
La solucin es dividir el programa en dos partes. Un aparte mantiene el procedimiento que necesitamos
cambiar, y las otras partes el resto del programa. Puedes ensamblar ambas partes separadamente y usar el
linker para encadenar los dos modulos objeto en un slo ejecutable.
Aqu hay un ejemplo, digamos que tienes un programa con varios procedimientos. El archivo
SMALL.ASM contiene un procedimiento y el archivo LARGE.ASM contiene el resto del programa. Para
crear un load module, debes seguir los siguientes pasos:
Primero esnambla ambos programas tecleando
MASM
MASM

LARGE;
SMALL;

Asumiendo que los archivos estn bien, obtendremos dos modulos objeto: LARGE.OBJ y SMALL.OBJ.
Para correr el programa, necesitas crear un load module con estos objs. Para hacer esto teclea:
LINK

LARGE+SMALL,PROGRAM;

Este comando crea un programa ejecutable con el nombre PROGRAM.EXE


Cuando necesites cambiar el procedimiento, solo necesitas rensamblar SMALL.ASM tecleando
MASM SMALL;
No necesitas rensamblar a LARGE.ASM ya que an tienes por ahi el obj llamado LARGE.OBJ, todo lo
que necesitas es volver a encadenar el programa completo
LINK

LARGE+SMALL,PROGRAM;

12.17 Como escribir programas que tienen partes separadas.


Si puedes dividir un programa en partes separadas, cada una consiste de uno o ms segmentos cada
uno almacenado en su propio archivo. La estructura de sus partes es muy parecida a lo que sera el mismo
programa contenido en un archivo grande. La diferencia principal es que debes decirle al ensamblador
cuales nombre de una parte sern referenciados en otra. Para hacer esto, puedes usar las directivas
EXTRN y PUBLIC.

15

Estas dos directivas son complementarias. EXTRN le dice al ensamblador cuales nombres sern definidos
en una parte diferente de un programa (esto es, cuales nombres son externos). PUBLIC le dice al
ensamblador cuales nombres pueden ser referenciados por otras partes del programa. La idea es que cada
referencia externa requiere dos directivas: una directiva PUBLIC, donde el nombre est definido, y una
directiva EXTRN, donde el nombre es usado.
El formato de la directiva EXTRN es:
EXTRN nombre:tipo
Si el nombre representa un campo dato, el tipo debe ser u n BYTE; WORD, DWORD, QWORD, y
TBYTE. Si el nombre representa una etiqueta, el tipo debe ser NEAR o FAR. El tipo es necesario ya que
le dice al ensamblador como trabajar con el nombre.
Aqu hay dos ejemplos:
EXTRN MSG2:BYTE
EXTRN EXTERNAL_PROCEDURE:FAR
El primer ejemplo le dice al ensamblador que el nombre MSG2 representa un campo dato (de tipo byte)
que est definido externamente de est parte del programa. El segundo ejemplo le dice al ensamblador
que EXTERNAL_PROCEDURE representa un procedimiento (de tipo far) que est definido
externamente para esa parte del programa.
Una vez que un nombre aparece en un directiva EXTRN, puedes usarlo sin volverlo a definir y el
ensamblador no considerar la referencia como un error. El ensamblador asume que todas las referencias
a ser definidas externamente sern resueltas por el linker.
Cuando un programa usa referencias externas, el ensamblador pone un mensaje al inicio del modulo
objeto. Este mensaje le dice al linker cuales nombres sern definidos en otros mdulos objeto.
El formato de la directiva PUBLIC es:
PUBLIC

nombre

Esta directiva identifica nombre que pueden ser usados como referencias externas en otras partes del
programa. Aqu hay dos ejemplos:
PUBLIC
PUBLIC

MSG2
EXTERNAL_PROCEDURE

Cuando un programa declara tales nombres, el ensamblador pone un mensaje al inicio del modulo objeto.
El mensaje le dice al linker cuales nombres de su modulo objeto sern usados como referencias externas
por otros mdulos objeto.
Como regla general, es buena idea juntar todas las directivas EXTRN y PUBLIC. Esto asegura que el
ensamblador conoce todos los nombres especiales antes de que aparezcan en el programa.
La figura 12-6 y 12-7 muestran las dos partes de un programa que puede ensamblarse separadamente y
juntos. La primer parte consiste del segmento de pila, un segmento de datos, y el segmento de cdigo
conteniendo el programa principal. La segunda parte consiste de un segmento de cdigo conteniendo el
procedimiento llamado EXTERNAL_PROCEDURE.
16

La lgica del programa principal es:


Despliega el mensaje (MSG1).
Llama a EXTERNAL_PROCEDURE.
Despliega el mensaje (MSG1) de nuevo.
El procedimiento EXTERNAL_PROCEDURE despliega un mensaje por s mismo. El proceso para
obtener el programa ejecutable es el siguiente:
MASM
MASM

FIRST;
SECOND;

Ahora linkeamos los dos programas juntos:


LINK

FIRST+SECOND,PROGRAM;

Si ejecutas el programa PROGRAM veras los siguiente mensajes:


Hello from program #1.
Hello from program #2.
Hello from program #1.
Figura 12-6 Programa FIRST primera parte del programa completo.
PAGE
58,132
;-----------------------------------------------------------------------------------; programa para demostrar el uso de referencias externas
; ----------------------------------------------------------------------------------; ajustar el titulo y el conjunto de instrucciones
TITLE
programa que usa referencias externas
.286
;-------------------------------------------------------------- segmento STACK
SSEG
SEGMENT STACK
DB
32 DUP(STACK---)
SSEG
ENDS
;--------------------------------------------------------- nombres EXTERNAL
EXTRN
EXTERNAL_PROCEDURE:FAR
;------------------------------------------------------------- nombres PUBLIC
PUBLIC
MSG2
;--------------------------------------------------------------- segmento DATA
DSEG
SEGMENT
MSG1
DB
Hello from procedure # 1, 0DH, 0AH,$
MSG2
DB
Hello from procedure # 2, 0DH, 0AH,$
DSEG
ENDS
;--------------------------------------------------------------- segmento CODE
CSEG
SEGMENT CODE
ASSUME
CS:CSEG, SS:SSEG; DS:DSEG, ES:DSEG
PAGE
;---------------------------------------------------------------------------------; MAIN (programa principal)
;

17

; Proposito:
;
Demostrar el uso de referencias externas
;
; Entrada:
;
-- ninguna -;
; Salida:
;
Tres mensajes son desplegados en la pantalla
;
; Nombres Externos:
;
EXTERNAL_PROCEDURE (peocedimiento) - despliega un mensaje;
;---------------------------------------------------------------------------------; Procedimiento: MAIN
MAIN
PROC

FAR

; Salvar la direccion para poder regresar a DOS


PUSH
DS
PUSH
0
; Actualizar el registro de segmento
MOV
AX,DSEG
MOV
DS,AX
MOV
ES,AX
; Desplegar mensaje #1
MOV
LEA
INT

AX,9H
DX,MSG1
21H

; Llamar al procedimiento externo para imprimir el mensaje # 2


CALL
EXTERNAL_PROCEDURE
; Desplegar mensaje #1 otra vez
MOV
AX,9H
LEA
DX,MSG1
INT
21H
; Regresar a DOS
RET
; Fin de procedimiento: MAIN
MAIN
ENDP
; Fin de segmento de cdigo
CSEG
ENDS
;--------------------------------------------------------------- Fin de programa
END
MAIN

Figura 12-7 Segunda parte del programa en dos partes SECOND


PAGE
58,132
;----------------------------------------------------------------------------------------; un ejemplo de un procedimiento externo
;----------------------------------------------------------------------------------------; ajustar el titulo y el conjunto de instrucciones
TITLE
programa externo
.286
;--------------------------------------------------------- nombres EXTERNAL

18

EXTRN
MSG2:BYTE
;------------------------------------------------------------- nombres PUBLIC
PUBLIC
EXTERNAL_PROCEDURE
;--------------------------------------------------------------- segmento CODE
CSEG
SEGMENT CODE
ASSUME
CS:CSEG
PAGE
;---------------------------------------------------------------------------------; EXTERNAL_PROCEDURE
;
; Proposito:
;
Demostrar como funciona un procedimiento externo
;
; Entrada:
;
-ninguna;
; Salida:
;
El mensaje se despliega en pantalla
;
; Nombre externos:
;
MSG2 (dato - el mensaje deplegado)
;----------------------------------------------------------------------------------------; inicio del procedimiento: EXTERNAL_PROCEDURE
EXTERNAL_PROCEDURE
PROC
FAR
; salvar los registros
PUSHA
; despliega el segundo mensaje
MOV
AH,9H
LEA
DX,MSG2
INT
21H
; restaurar registros
POPA
; regresar al procedimiento principal
RET
; fin del procedimiento: EXTERNAL_PROCEDURE
EXTERNAL_PROCEDURE ENDP
; fin de segmento de cdigo
CSEG
ENDS
; fin de programa
END

{_____________o___________}

CAPITULO 13

ARITMETICA

19

Este captulo cubre la aritmtica de nmeros con signo y sin signo, establecidas en el captulo 8. Sin
embargo los nmeros de punto flotante (notacin cientfica) y los nmeros de punto fijo requieren tipos
de hardware diferente.
El procesador principal slo puede trabajar con nmeros de punto fijo. Dicho de otra manera el
procesador no trabaja con nmeros con fracciones a menos que los simules con nmeros enteros. Por
tanto para el curso de ensamblador bsico solo cubrir los nmeros con signo.
Nuevos Trminos
Nmero de punto fijo. Un nmero en el cual el punto decimal est fijo, tambin llamados nmeros
enteros.
Nmeros de punto flotante. Un nmero en el cual su punto decimal puede estar en cualquier posicin;
tambin llamados nmeros fraccionales.
Nmero sin signo. Un nmero de punto fijo cuyo valor puede ser positivo o cero.
Nmero con signo. Un nmero de punto fijo cuyo valor puede ser positivo negativo o cero.
Complemento. Un patrn de bits que tiene exactamente los valores opuestos a otro patrn de bits.
Complemento a dos. Un nmero que se obtiene al complementar un patrn de bitas y sumarle 1.

13.1 Nmeros con signo y sin signo.


Existen dos tipos de nmeros de punto fijo: nmeros sin signo que pueden representar valores
positivos y el cero; y nmeros con signo que pueden representar nmeros positivos y negativos
incluyendo al cero.
Los nmeros con signo y sin signo pueden ser almacenados en bytes o palabras. Los nmeros con signo
son almacenados en su equivalente en binario. Por ejemplo el equivalente binario de 57 es 1110001B. Si
su valor fuera almacenado en un byte quedara como:
00111001
o como una palabra:
0000000000111001
Para encontrar el rango de posibilidades para los nmeros con signo, podemos examinar el patrn de bits
menor y mayor. Para nmeros con signo para bytes sera
00000000B a 11111111B esto es de 0 a 255.
Para nmeros sin signo almacenados como palabras, el rango es:
0000000000000000B a 1111111111111111B esto es de 0 a 65535.
La tabla 13-1 resume los rangos decimales para los nmeros con signo y sin signo.
20

Tabla 13-1 Los rangos de los nmeros con signo y sin signo
Unidad de almacenamiento
Sin signo
Con signo
Byte
0 a 255
-128 a 127
Word
0 a 65535
-32768 a 32767

13.2 El sistema del complemento a dos.


Representar nmeros con signo requiere un esquema nmeros positivos, negativos y al cero. Podra
parecer simple que dejramos el bit de ms a la izquierda del byte o la palabra para indicar el signo: 0
para positivos y 1 para negativos. Los otros bits representan la magnitud del nmero.
Por ejemplo, considere almacenar los valores +57 y -57 en un byte. Si usamos el esquema descrito
anteriormente, tenemos:
+57 ---------> 00111001
-57 ---------> 10111001
Desafortunadamente, hay problemas con este esquema. La ms importante es que hay dos posibles
representaciones del cero:
00000000 y

10000000

Para resolver este problema, los diseadores de computadoras usan un esquema llamado complemento a
dos. Sin embargo antes de que comprendas este esquema, debes entender el trmino complemento de bits.
El complemento de un patrn de bits es el patrn que contiene exactamente sus valores opuestos; cada 0
es cambiado a 1 y cada 1 por un cero. Aqu hay algunos ejemplos.
Patrn de bits
01110
1010101
000
11111111

Complemento
10001
0101010
111
00000000

Para calcular el complemento a dos de un nmero, debes obtener su complemento y sumarle 1. Por
ejemplo el complemento a dos de 00111001B (57 decimal):
patrn original
complemento
comp. a dos

00111001
11000110
+
1
11000111

Esta regla puede ser usada para obtener el complemento a dos de cualquier patrn de bits, sin embargo
hay una regla extra que debes considerar cuando calculas el complemento a dos de cero.
patrn original
complemento

00000000
11111111
+
1
100000000
La regla extra es ignorar los acarreos de 1 generados por el complemento de cero.
21

13.3 Usar el complemento a dos para representar nmeros con signo.


El procesador utiliza el complemento a dos para representar nmeros con signo. El esquema es que,
mientras un nmero positivo es representado por su valor binario, un nmero negativo es representado
por el complemento a dos de su nmero positivo. El bit de ms a la izquierda indica el signo: 0 positivo 1
negativo.
En otras palabras, el negativo de un nmero es su complemento a dos. Aqu hay algunos ejemplos de
valores de 8 bits.
Valor decimal
57
-57
127
-127
0

valor binario
complemento a dos
00111001
11000111
11000111
00111001
01111111
10000001
10000001
01111111
00000000
00000000

13.4 Descifrando nmeros en complemento a dos.


Cuando escribes un programa el complemento a dos de los nmeros negativos no representa ningn
problema, debido a que puede usar decimales con signo cuando es necesario. Sin embargo cuando
pruebas un programa con un debugger, necesitas interpretar los valores negativos en los registros y
locaciones de memoria. En tales casos, necesitas calcular el complemento a dos del nmero para
encontrar valor absoluto.
Aqu hay un ejemplo. Digamos que pruebas un programa con nmeros con signo, y AX contiene el
siguiente patrn de bits:
1001010110100010B
Sabes que el numero es negativo ya que empieza con 1, para encontrar su valor calculas el complemento
a dos.
patrn original 1001010110100010
complemento
0110101001011101
+
1
comp. a dos
0110101001011110
Convirtiendo el complemento a dos a decimal encontramos que su valor es 27230. As el numero original
tenia el valor -27230.
Por supuesto estos valores en el debugger estarn en hexadecimal. Debes convertir estos valores a binario
hacer el complemento y despus obtener su valor en decimal.
Aqu hay un ejemplo: El programa trabaja con nmeros con signo y el registro AX contiene C04AH:
C

A
22

1100

0000

0100

1010

Despus obtenemos el complemento a dos


patrn de bits 1100000001001010
complemento 0011111110110101
+
1
comp. a dos
0011111110110110
El numero en decimal es 16310, o sea -16310 originalmente
Digamos que una palabra tiene la primera parte del numero con signo en la locacin 10A0H y su segunda
palabra en la locacin posterior si estos valores fueran 5CH y B7H respectivamente cual es el numero que
representa:
B 7
5
1011 0111

C
0101

1100

patrn original 1011011101011100


complemento
0100100010100011
+
1
comp. a dos
0100100010100100
en decimal era el -18596.
Puedes usar la siguiente regla para los dgitos hexadecimales. Un nmero con signo en hex es positivo si
empieza con los dgitos:
0

Y es negativo si empieza con los dgitos:


8

13.5 Usar saltos condicionales con nmeros con signo y sin signo.
Existen un conjunto de saltos condicionales para nmeros con signo y otro para nmeros sin signo.
Primero que todo debes asegurarte que el valor del nmero no sobrepasa el rango permitido. Para hacer
esto, usa el salto condicional apropiado despus de la operacin aritmtica.
Con nmeros sin signo, las instrucciones JC y JNC prueban las condiciones de rebose:
JC salta si el valor sin signo se sobrepaso
JNC salta si el valor sin signo no se sobrepaso
Estas instrucciones prueban la bandera de acarreo (CF), si el valor se sobrepaso la bandera CF esta puesta
a 1 , sino la bandera esta a 0.
Con nmeros con signo, las instrucciones JO y JNO prueban las condicin de sobreflujo:
JO salta si el valor con signo se sobrepaso
23

JNO salta si el valor con signo no se sobrepaso


Estas instrucciones prueban la bandera de sobreflujo (OF), si el valor se sobrepaso OF esta 1, sino esta a
0.
Por ejemplo digamos que quieres sumar la variable VALOR al registro AX y despus comprobar si el
resultado no fue muy grande. si lo fue saltamos a la etiqueta de ERROR. Si estas usando nmeros con
signo puedes usar
ADD
JC

AX,VALOR
ERROR

Si estas usando nmeros sin signo puedes usar


ADD
JO

AX,VALOR
ERROR

La tabla 13-3 muestra los saltos condicionales disponibles para ambos tipos de nmeros.
13-3 Saltos condicionales para nmeros sin signo
Opcode
Significado
JC
salta si sobreflujo
JNC
salta si no sobreflujo
JB (JNAE)
salta si debajo (no arriba ni igual)
JA (JNBE)
salta si arriba (no abajo o igual)
JBE (JNA)
salta si debajo o igual (no arriba)
JAE (JNB)
salta si arriba o igual (no abajo)
JE
salta si igual
JNE
salta si no igual
Saltos condicionales para nmeros con signo
Opcode
Significado
JO
salta si sobreflujo
JNO
salta si no sobreflujo
JL (JNGE)
salta si menor que (no mayor que o igual)
JG (JNLE)
salta si mayor que (no menor o igual)
JLE (JNL)
salta si menor o igual (no mayor que)
JGE (JNL)
salta si mayor o igual (no menor)
JE
salta si igual
JNE
salta si no igual
Cuando comparas dos nmeros, asegrate de usar el salto condicional adecuado. Por ejemplo, si quieres
comparar el valor del registro AX con al variable TOTAL sin signo. Digamos que quieres saltar si AX e
mayor que TOTAL puedes usar.
CMP
JA

AX,TOTAL
L1

Si estas usando nmeros con signo puedes usar:


CMP
JG

AX,TOTAL
L1
24

El ltimo tipo de salto condicional se aplica solo a los nmeros con signo. Puedes usar las instrucciones
JS y JNS para checar la bandera de signo (SF)
JS salta si SF esta puesta a 1
JNS salta si SF esta puesta a 0
Si el resultado de la operacin previa fue positivo SF tendr un valor de 0. Si el resultado es negativo SF
tendr un 1.

13.6 Adicin y substraccin: ADD y SUB.


La suma y resta son conceptualmente simples. Usa la instrucciones ADD y SUB. El formato es:
ADD
SUB

operando1, operando2
operando1, operando2

El segundo operando es sumado o restado del primero. El resultado es almacenado en el primer operando,
remplazando el valor original.
Aqu hay algunos ejemplos:
ADD
SUB

AX,VALOR
AX,VALOR

En el primer ejemplo la instruccin ADD calcula (AX+VALOR) y guarda el resultado en AX. La


segunda instruccin resta (AX-VALOR) y guarda tambin el resultado en AX.
Los operandos deben ser del mismo tipo: ambos bytes o palabras. El primer operando puede ser un
registro, o un campo dato (locacin de memoria). El segundo operando puede ser un registro, un campo
dato, o un valor inmediato. Sin embargo no puedes sumar directamente dos campos dato
ADD

VALOR1,VALOR2

Si VALOR1 y VALOR2 son campos dato, debes copiar uno a un registro:


MOV
ADD

AX,VALOR2
VALOR1,AX

13.7 Sumar y restar una palabra y un byte.


Las instrucciones ADD y SUB requieren que ambos operandos sean de la misma longitud, ya sea
byte o palabra. Sin embargo, es til poder restar o sumar una palabra y un byte. en tales casos, necesitas
expander el byte a una palabra. Los pasos son los siguientes:
1. Copiar el byte a la parte derecha de AX.
2. Ajustar la parte izquierda de AX apropiadamente. (tener cuidado si el nmero tiene signo)
25

3. Usar AX en lugar del byte en el calculo.


Aqu hay un ejemplo. Digamos que quieres sumar dos campos dato BYTE_VALOR de un byte y
WORD_VALOR de una palabra. Si son nmeros sin signo, las instrucciones son
MOV
MOV
ADD

AL,BYTE_VALOR
AH,0
AX,WORD_VALOR

Si estas trabajando con nmeros con signo, la instruccin CBW puede ayudarte a poner AH al valor
complementado en dos apropiado. La instruccin CBW puede entenderse como convertir byte a word.
As, si quieres hacer lo mismo que en el ejemplo anterior usando nmeros con signo:
MOV
CBW
ADD

AL,BYTE_VALOR
AX,WORD_VALOR

CBW trabaja solo con AH y AL. La instruccin examina el valor de AL y hace que AX tenga el mismo
valor complementado de AL. Si AL es positivo AH esta como cero, si AL es negativo, AH esta puesta
toda a unos.

13.8 Sumar y Restar nmeros muy grandes: ADC y SBB.


Algunas veces necesitas sumar o restar nmeros que son mucho mayores que los rangos de bytes o
palabras, aunque no tengas coprocesador puedes utilizar las palabras dobles y cudruples para estas
operaciones. Sin embargo tendrs que usar instrucciones regulares y trabajar sobre los nmeros grandes
una palabra a la vez. En tales casos puedes usar las directivas DD y DQ para definir los nmeros.
Aqu hay un ejemplo del uso de palabras dobles. Quieres sumar 123456789 a 987654321. Define los
campos dato como sigue:
DFIRST
DSECOND

DD
DD

987654321
123456789

En hex, los valores son 3ADE68B1H Y 075BCD15H. Aqu esta almacenados los valores en las palabras
dobles:

Note que los bytes estn almacenados en orden inverso. Las dos palabras de DFIRST pueden ser
direccionadas como DFIRST y DFIRST+2; las dos palabras de DSECOND pueden ser direccionadas
como DSECOND y DSECOND+2. Para ejecutar la suma, debemos sumar una palabra a la vez. Como los
bytes estn almacenados en orden inverso, debes sumar de izquierda a derecha. Los pasos son los
siguientes:
Sumar la palabra de la izquierda de DSECOND en la palabra de la izquierda de DFIRST.
Sumar la palabra de la derecha de DSECOND a la palabra de la derecha de DFIRST.
26

La primera suma puede generar un acarreo. Si es as el acarreo debe ser sumado a la segunda suma. La
instruccin ADD siempre avisa si hay un acarreo activando la bandera CF.
Hay una instruccin que hace este trabajo llamada ADC, la cual significa suma y acarrea. As puedes usar
ADC para hacer las sumas izquierdas y ADC para las derechas. Veamos el cdigo.
; sumar palabras dobles: DFIRST<---DFIRST+DSECOND
MOV
AX,WORD PTR DSECOND
ADD
WORD PTR DFIRST,AX
MOV
AX,WORD PTR SECOND+2
ADC
WORD PTR DFIRST+2,AX
Nota- La instruccin MOV no modifica el valor de CF.
Si quieres usar palabras cudruples, el patrn es el mismo. Como las palabras, el ensamblador almacena
las palabras dobles y cudruples en orden inverso. Primero define dos campos dato con su valores:
QFIRST DQ
543210987654321
QSECOND
DQ
123456789012345
Ahora, sume las dos nmeros una palabra a la vez, de izquierda a derecha. Use ADD para la primera
adicin y use ADC para todas las subsecuentes adiciones y sus acarreos.
; sumar quadwords: QFIRST<-- QFIRST+QSECOND
MOV
AX,WORD PTR QSECOND
ADD
WORD PTR QFIRST,AX
MOV
AX,WORD PTR QSECOND+2
ADC
WORD PTR QFIRST+2,AX
MOV
AX,WORD PTR QSECOND+4
ADC
WORD PTR QFIRST+4,AX
MOV
AX,WORD PTR QSECOND+6
ADC
WORD PTR QFIRST+6,AX
La substraccin es similar a la adicin. La diferencia es que no hay acarreos sino prestamos. Con la resta
CF esta activa a 1 si hay un prstamo en la posicin de ms a la izquierda; sino CF esta puesta a 0.
La instruccin SBB es anloga al ADC. El valor de CF es tomado en cuenta durante la resta. As puedes
restar nmeros grandes una palabra a la vez de izquierda a derecha usando SUB para la primera resta y
SBB para la dems. Aqu hay dos ejemplos, que muestran como restar palabras dobles y cudruples.
; restar palabras dobles: DFIRST<-- DFIRST-DSECOND
MOV
AX,WORD PTR DSECOND
SUB
WORD PTR DFIRST,AX
MOV
AX,WORD PTR DSECOND+2
SBB
WORD PTR DFIRST+2,AX
; restar palabras cudruples: QFIRST<-- QFIRST-QSECOND
MOV
AX,WORD PTR QSECOND
SUB
WORD PTR QFIRST,AX
MOV
AX,WORD PTR DSECOND+2
SBB
WORD PTR QFIRST+2,AX
MOV
AX,WORD PTR QSECOND+4
27

SBB
MOV
SBB

WORD PTR QFIRST+4,AX


AX,WORD PTR QSECOND+6
WORD PTR QFIRST+6,AX

13.9 Sumar y restar 1 de un nmero: INC y DEC.


El procesador tiene dos instrucciones que pueden incrementar o decrementar 1 a un numero estas
son INC y DEC. Su formato es:
INC operando
DEC operando
El operando puede ser un campo dato o un registro. Aqu hay algunos ejemplos:
INC AX
DEC AL
INC CH
DEC
DI
INC TOTAL
DEC TABLE[BX]+4
INC y DEC son usadas especialmente con ciclos cuyos valores deben ser incrementados o decrementados
en 1 cada vez que se ejecute el ciclo. El siguiente ejemplo tiene un ciclo que llama al procedimiento
READ_CARACTER hasta que la bandera de acarreo CF tiene un valor de 1. El campo dato CONT es
usado para contar el numero de veces que el procedimiento es invocado.
; repeat
;
call READ_CARACTER
; until CF=1
; cont = numero de invocaciones
CLC
MOV
CONT,0
L1:
CALL
READ_CARACTER
INC
CONT
JNC
L1
13.10 Cambiar el signo de un nmero: NEG.
Una de las operaciones fundamentales que puedes ejecutar en un numero con signo es cambiar su
signo de negativo a positivo o viceversa. Para hacer esto usa la instruccin NEG, su formato es:
NEG operando
El operando puede ser un campo dato o un registro: Aqu hay algunos ejemplos:
NEG
NEG
NEG

AX
VALOR
SI
28

NEG

CL

13.11 Multiplicacin: MUL y IMUL.


Existen dos instrucciones para multiplicar: MUL para nmeros sin signo e IMUL para nmeros con
signo. Excepto por la diferencia entre los tipos, el comportamiento de las instrucciones es el mismo. El
formato es
MUL
operando
IMUL
operando
El operando puede ser un registro o un campo dato, y puede ser de tipo byte o word. Para multiplicar el
procesador necesita dos operandos, si especificas un operando byte, el procesador asume que el otro
operando est en AL, si especificas un operando word, el procesador asume que el otro operando est en
AX.
Por ejemplo, si BVALOR es un campo dato de tipo byte, la siguiente instruccin multiplica AL por
VALOR:
MUL

BVALOR

si WVALOR es un campo dato de tipo word, la siguiente instruccin multiplica AX por WVALOR
MUL

WVALOR

Cuando multiplicas, el resultado puede ser el doble de grande que los operandos. Cuando multiplicas un
byte por otro, el procesador siempre genera un resultado de 2 bytes, la parte izquierda est en AH, y la
derecha en AL.
Aqu hay un ejemplo. Digamos que AL tiene un valor de 100 (64H) y BVALOR contiene 10 (0AH).
antes de la multiplicacin, AX contiene
AH
??

AL
64

Despus de la multiplicacin, el resultado es 1000 (3E8H) y AX contiene


AH
03

AL
E8

Cuando multiplicas una palabra por otra el procesador siempre genera un resultado de 4 bytes. La parte
izquierda queda en DX y la derecha en AX. Aqu hay un ejemplo. Digamos que WVALOR contiene 1000
(3E8H) y AX contiene 55555 (D903H). Antes de la multiplicacin DX:AX contiene
DX
????

AX
D903

Despus de la multiplicacin , el resultado es 55555000 (34FB3B8H) y DX:AX contiene


DX
034f

AX
B3B8
29

Muchas de las veces el resultado es suficientemente pequeo para ocupar el operando original. De hecho,
cuando multiplicas un byte por otro, si el resultado cabe en AL puedes ignorar AH. Similarmente cuando
multiplicas palabras, si el resultado cabe en AX se puede ignorar a DX.
Para ayudarte a determinar cuando puedes ignorar la parte izquierda del resultado, MUL e IMUL activan
las bandera CF y OF. Si el resultado es bastante pequeo para ocupar a AL (bytes) o AX (words), CF y
OF estn puestas a 0. Si el resultado es ms grande, CF y OF estn a 1.
Aqu hay un ejemplo que multiplica CX por, AX usando nmeros sin signo,. Despus de la
multiplicacin, AX se copia a RESULT1. Si el resultado est extendido hasta DX, DX se copia a
RESULT2.
MUL
MOV
JNC
MOV

CX
RESULT1,AX
L1
RESULT1,DX

L1:

13.12 Usar IMUL para multiplicar por un valor inmediato.


Puedes usar una variacin de la instruccin IMUL para multiplicar por un valor inmediato. Esta
variacin trabaja con valores con signo y sin signo. En formato es:
IMUL
IMUL

operando, valor-inmediato
destino,operando,valor-inmediato

El operando y destino pueden ser cualquiera de estos registros:


AX BX CX DX SP

BP SI

DI

El procesador multiplica el operando por el valor inmediato. Si un destino es especificado, el resultado es


copiado a destino, sino, el resultado reemplaza al operando.
Aqu hay algunos ejemplos:
IMUL
IMUL

AX,10
SI,BX,-5

El primer ejemplo multiplica AX por 10. El segundo multiplica BX por -5 y el resultado se copia en SI.
BX permanece sin cambios.
Cuando usas est variacin de IMUL, el resultado siempre es colocado en un registro de una palabra. Si
el resultado cabe en una palabra, IMUL limpia las banderas de acarreo y de sobreflujo (CF y OF) en 0. Si
el resultado no cabe, IMUL pone las banderas CF y OF a 1.
Sin embargo est variacin solo retiene los 16 bits de ms a la derecha del resultado, as siempre cabra el
resultado en la palabra.
13.13 Multiplicar una palabra por un byte.
30

El modo ms fcil de multiplicar un byte por una palabra es copiar el byte a AL y entonces ajustar
AH al valor apropiado, si estas usando nmeros sin signo, por 0s en AH. Si estas usando nmeros con
signo, usa la instruccin CBW.
Aqu hay dos ejemplos. El primero usa MUL para multiplicar dos campos dato sin signo: UBYTE es de
tipo byte u UWORD es de tipo palabra.
; multiplicar ubyte por uword
MOV
AL,UBYTE
MOV
AH,0
MUL
UWORD
El segundo ejemplo usa IMUL para multiplicar dos nmeros con signo: SBYTE es de tipo byte y
SWORD es de tipo word.
; multiplicar sbyte por sword
MOV
AL,BYTE
CBW
IMUL
SWORD

13.14 Divisin: DIV y IDIV.


Existen dos instrucciones para dividir: DIV para nmeros sin signo e IDIV para nmeros con signo.
Estas instrucciones tiene el siguiente formato:
DIV operando
IDIVoperando
Puedes dividir una palabra entre un byte o una palabra doble entre una palabra. Existen dos resultados el
cociente y el residuo, ambos son nmeros enteros.
La instruccin IDIV est diseada para que el signo del residuo sea el mismo del cociente. Por ejemplo, si
divides -53 entre 7 el resultado es: un cociente de -7 y un residuo de -4.
El operando que especificas es el divisor. El dividendo puede ser el contenido del registro AX o DS:AX.
Si especificas un operando de tipo byte, DIV e IDIV asumen que AX contiene el dividendo de una
palabra. El cociente es colocado en AL y el residuo en AH. Si especificas un operando de tipo palabra,
DIV e IDIV asumen que DX:AX contiene el dividendo de la doble palabra. El cociente es colocado en
AX y el residuo en DX.
Aqu hay dos ejemplos. El primer ejemplo divide 53 entre BVALOR. BVALOR en un campo dato de tipo
byte con un valor de 10. Primero copio 53 a AX. Entonces usa DIV para ejecutar la divisin.
; dividir 53 / BVALOR
MOV
AX,53
DIV
BVALOR
El resultado es el siguiente AL contiene el cociente 5 y AH contiene el residuo 3.
31

El segundo ejemplo usa nmeros con signo y divide DVALOR entre WVALOR. DVALOR es de tipo
palabra doble y tiene un valor de -500003. WVALOR es de tipo word con un valor de 100. Primero copio
DVALOR a DX:AX. Entonces usa la instruccin IDIV para hacer la operacin.
Para copiar una palabra doble a DX:AX, debes usar dos instrucciones mov con el operador PTR, solo
recuerda que los datos estn al revs as que:
; dividir DVALOR / WVALOR
MOV
DX,WORD PTR DVALOR+2
MOV
AX,WORD PTR DVALOR
IDIV
WVALOR
El resultado es AX con un valor de -5000 y DX con un valor de -3.
Durante una divisin, una condicin de sobreflujo ocurre cuando el resultado es muy grande para ser
colocado en el registro AL o AX. La causa ms comn es la divisin entre cero. As debemos evitar
cualquier posible divisin entre cero:
; divisin que prueba la divisin entre cero
CMP
BVALOR,0
JE
L1
MOV
AX,WVALOR
DIV
BVALOR
L1:

13.15 Dividir un byte entre un byte o una palabra entre una palabra.
Las instrucciones DIV e IDIV solo pueden dividir una palabra entre un byte o una palabra doble
entre una palabra. Si quieres dividir un byte entre un byte o una palabra entre una palabra, debes extender
el dividendo a la longitud correcta.
La forma ms fcil es copiar el dividendo a AL o AX y entonces ajustar AH o DX dependiendo si el
numero tiene signo o no. A continuacin hay cuatro ejemplos que ilustran las posibilidades. El primer
ejemplo usa DIV para dividir un byte sin signo entre otro. Los campos dato UBYTE1 y UBYTE2 son
nmeros sin signo de tipo byte.
; dividir UBYTE1 / UBYTE2
MOV
AL,UBYTE1
MOV
AH,0
DIV
UBYTE2
El segundo ejemplo usa IDIV para dividir un numero con signo entre otro los dos de tipo byte.
; dividir SBYTE1 / SBYTE2
MOV
AL,SBYTE1
CBW
IDIV
SBYTE2
El tercer ejemplo usa DIV para dividir un numero sin signo entre otro de tipo word.
32

; dividir SBYTE1 / SBYTE2


MOV
AX,UWORD1
MOV
DX,0
DIV
UWORD2
El cuarto ejemplo usa IDIV para dividir dos nmeros con signo de tipo word.
; dividir SWORD1 / SWORD2
MOV
AX,SWORD1
CWD
DIV
SWORD2
{_____________o___________}

33

CAPITULO 14

ARITMETICA DECIMAL

En este captulo aprenders a usar las instrucciones para ejecutar aritmtica bsica en decimal.
Nuevos Trminos
Nmero decimal. Un nmero en el cual los dgitos decimales son almacenados como entidades
separadas.
Nmero decimal sin empacar. Un numero decimal en el cual sus dgitos estn almacenados uno por
byte.
Numero decimal empacado. Un numero decimal en el cual cada dos dgitos estn almacenados en un
byte.
Numero decimal codificado en binario. abreviado BCD; representacin binaria del cdigo decimal.

14.1 Nmeros decimales.


Como sabes, los nmeros con signo y sin signo son almacenados en binario, los cuales son
representados como valores hexadecimales. Los nmeros decimales son almacenados como entidades
separadas de dgitos. Existen dos maneras de hacer esto. Si cada dgito decimal ocupa un byte el numero
es llamado decimal sin empacar, si cada dos dgitos decimales estn representados por un byte se dice que
el numero es decimal empacado.
La figura 14-1 contiene un ejemplo que muestra el numero 54321 (D431H) almacenado como numero sin
signo, numero decimal sin empacar y numero decimal empacado.
Figura 14-1 La maneras de almacenar un decimal 54321
Sin signo
hex:
D 4
3
1
binario:
1101 0100 0011 0001
Decimal sin empacar
hex:
0
5
0
4
0
3
0
2
0
1
binario:
0000 0101 0000 0100 0000 0011 0000
Decimal empacado
hex:
0
5
4
3
2
1
binario:
0000 0101 0100 0011 0010 0001

0010

0000

0001

14.2 Cuando usar nmeros decimales.


Existen dos condiciones bajo las cuales es preferible usar aritmtica decimal en lugar de binaria.
Primero, hay algunas veces cuando los nmeros que usas representan valores estrictamente decimales. El
ejemplo ms comn es ejecutar clculos financieros con pesos (dlares) y centavos. Si se manejaran en
base dos las conversiones provocaran errores de calculo intolerables hablando de nmeros enteros.
La segunda condicin es cuando los nmeros deben ser ledos o escritos, antes de que los nmeros sean
escritos, estos deben ser convertidos a caracteres. De hecho no puedes escribir el numero 54321; en su
34

lugar debes escribir los caracteres 5, 4, 3, 2, 1. Similarmente solo los caracteres y no los
nmeros pueden ser ledos.
Como explique en el capitulo 2, cada carcter est representado por una cadena de 8 bits del cdigo
ASCII. Debido a que solo hay 10 dgitos decimales, puedes escribir a leer nmeros usando los diez
cdigos ASCII, vea la tabla 14-1.
Tabla 14-1 Cdigo ASCII de los diez dgitos
Carcter Hex
Binario
0
30
0011 0000
1
31
0011 0001
2
32
0011 0010
3
33
0011 0011
4
34
0011 0100
5
35
0011 0101
6
36
0011 0110
7
37
0011 0111
8
38
0011 1000
9
39
0011 1001
Es fcil ver que la conversin entre ASCII y decimal empacado no podra ser ms simple. As cuando
lees y escribes nmeros, es ms fcil trabajar con aritmtica decimal para facilitar las conversiones a
ASCII. Muchas de las veces es aun ms fcil utilizar decimal empacado, ya que ocupan menos espacio y
se ejecutan ms rpido
Sin embargo el procesador no puede ejecutar aritmtica decimal directamente, debes usar las operaciones
estndar ADD, SUB, DIV y MUL, y el procesador provee instrucciones especiales para ajustar valores de
decimal a binario.
Las instrucciones de ajuste siempre operan en el contenido del registro AL. As cuando uses aritmtica
decimal, el primer operando debe estar en AL.
La aritmetica decimal est limitada a dos pasos importantes: primero, debes trabajar solo con un byte a la
vez. As si estas usando nmeros decimales sin empacar, debes procesar un dgito a la vez. Si estas
usando nmeros decimales empacados, puedes procesarlo dos dgitos a la vez.
Segundo, los nmeros decimales empacados solo pueden ser sumados y restados. Si quieres dividir y
multiplicar, debes convertir estos nmeros a sus equivalentes sin empacar.

14.3 Adicin decimal: AAA y DAA.


Para sumar nmeros decimales un byte a la vez, copia uno de los operandos a AL, suma con la
instruccin ADD, y ajusta el resultado para convertirlo a un numero decimal valido.
Si estas sumando nmeros sin empacar usa la instruccin AAA para hacer el ajuste, si usas nmeros sin
empacar usa la instruccin DAA
Aqu hay dos ejemplos de sumas usando campos dato de tipo byte. U1 y U2 son nmeros sin empacar; P1
y P2 son nmeros empacados:
35

U1
U2
P1
P2

DB
DB
DB
DB

7H
6H
95H
07H

Note que cada byte sin empacar ocupa un dgito; cada byte empacado ocupa dos dgitos.
El primer ejemplo de abajo muestra la suma de dos nmeros sin empacar. El segundo ejemplo muestra
como sumar dos nmeros empacados.
; suma de dos nmeros sin empacar
MOV
AL,U1
ADD
AL,U2
AAA
; suma de dos nmeros empacados
MOV
AL,P1
ADD
AL,P2
DAA
Hay algunas veces que el resultado de la suma no cabe en AL, en los nmeros sin empacar esto ocurre
cuando la suma es mayor de 9. Con los nmeros empacados, esto pasa cuando la suma es mayor que 99.
En la siguiente seccin veremos como sumar nmeros decimales multibytes.

14.4 Sumar nmeros multibytes decimales sin empacar.


Para sumar dos nmeros decimales sin empacar multibytes, debemos sumar un byte a la vez de
derecha a izquierda. Despus de cada suma debemos hacer el ajuste respectivo. Para todas menos la
primer suma debemos tomar en cuanta en contenido de CF.
Esta seccin contiene un ejemplo que suma dos nmeros decimales sin empacar de tres bytes U1 y U2, el
resultado queda en U1. U1 y U2 estn definido como sigue
U1
U2

DB 0H,5H,2H,1H
DB 0H,4H,8H,4H

El ejemplo suma U2 y U1 un byte a la vez, de derecha a izquierda. Cada adicin involucra cuatro pasos.
1.- Copiar un byte de U1 a AL.
2.- Sumar un byte de U2 a AL.
3.- Ajustar el resultado.
4.- Copiar el resultado ajustado a AL.
La primera adicin usa ADD, las subsecuentes adiciones usan ADC para contar el posible acarreo de byte
a byte.
Es importante recordar que puede haber un acarreo hasta en la ultima suma. Estamos sumando dos
nmeros de tres dgitos y obtenemos un numero de cuatro (521 + 484 = 1005). Una forma de resolver
esto es con un dgito extra (el primer cero) donde se copiara el acarreo extremo si lo hay.

36

Como sabemos si se produce ese dgito extra. Si el ajuste produce un resultado que es muy grande para
AL, la instruccin AAA hace dos cosas
pone CF a 1
suma 1 a AH
As, si pones un cero en Ah en el ultimo ajuste, AAA dejar Ah con un valor de cero o 1. Todo lo que
tienes que hacer es esperar hasta el ultimo ajuste y entonces copiar AH al dgito extra del resultado.
; suma de dos dgitos multibytes sin empacar: U1<--U1+U2
; --- suma U2+3 a U1+3
MOV
AL,U1+3
ADD
AL,U2+3
AAA
MOV
U1+3,AL
; --- suma U2+2 a U1+2
MOV
AL,U1+2
ADC
AL,U2+2
AAA
MOV
U1+2.AL
; --- suma U2+1 a U1+1
MOV
AL,U1+1
ADC
AL,U2+1
MOV
AH,0
AAA
MOV
U1+1,AL
; --- ajustar el dgito de mas a la izquierda de U1
MOV
U1,AH
14.5 Sumar nmeros multibytes decimales empacados.
Hay un par de diferencias entre las tcnicas de suma multibyte de nmeros decimales sin empacar y
empacados.
Primero, debes usar un ajuste diferente a AAA, DAA. Segundo, debes procesar dos dgitos a la vez
(debido a que cada byte contiene dos dgitos). Tercero, debes depender de la bandera de acarreo para
saber si hay un acarreo extremo en la ultima suma.
El siguiente ejemplo, ilustra como sumar dos nmeros empacados de tres bytes, P1 y P2, el resultado
queda en P1.
P1
P2

DB 00H,56H,43H,21H
DB 00H,45H,68H,54H

Esta operacin es 564321 + 456854 = 1021175.


; suma de dos dgitos multibytes empacados: P1<--P1+P2
; --- suma P2+3 a P1+3
MOV
AL,P1+3
ADD
AL,P2+3
DAA
37

MOV
P1+3,AL
; --- suma P2+2 a P1+2
MOV
AL,P1+2
ADC
AL,P2+2
DAA
MOV
P1+2.AL
; --- suma P2+1 a P1+1
MOV
AL,P1+1
ADC
AL,P2+1
DAA
MOV
P1+1,AL
; --- if CF=1 pon el dgito de mas a la izq. de P1 a 1
; --- else
pon el dgito de mas a la izq. de P1 a 0
JC
L1
JNC
L2
L1:
MOV
P1,1
JMP
L3
L2:
MOV
P1,0
L3:

14.6 Substraccin decimal: AAS y DAS.


La substraccin decimal es similar a la suma decimal. Procesas los nmeros byte por byte, de
derecha a izquierda. El numero desde el cual estas substrayendo es copiado a AL.
Como en la suma decimal, debe ajustar despus de cada resta. Si estas restando decimales sin empacar,
usa la instruccin AAS. Si estas restando decimales empacados usa DAS, estos asumen que el resultado
del calculo previo est en AL:
Aqu hay dos ejemplos. El ejemplo usa bytes, U1 y U2 son nmeros sin empacar, P1 y P2 son nmeros
empacados:
U1
U2
P1
P2

DB
DB
DB
DB

7H
6H
95H
07H

El primer ejemplo resta dos nmeros sin empacar


; resta dos nmeros sin empacar AL<--U1-U2
MOV
AL,U1
SUB
AL,U2
AAS
El segundo ejemplo resta dos nmeros empacados
; resta dos nmeros empacados AL<--P1-P2
MOV
AL,P1
38

SUB
DAS

AL,P2

Si el numero que estas restando es mayor que el numero en AL, AAS y DAS ponen la bandera de acarreo
en 1 para indicar el prstamo. AAS tambin puede restar 1 de AH. Si no hay prstamo, AAS y DAS
ponen CF a 0.

14.7 Restando nmeros decimales multibytes sin empacar.


Para restar dos nmeros de este tipo, debes restar los bytes uno a la vez, de derecha a izquierda.
Despus de cada resta, debes hacer el ajuste. En la ultima resta debes tomar en cuenta el valor de la
bandera de acarreo CF.
Esta seccin contiene un ejemplo de resta de dos nmeros de tres bytes sin empacar, U1 y U de tipo byte
U1
U2

DB 5H,2H,1H
DB 4H,8H,4H

El ejemplo resta U de U2, un byte a la vez con un proceso de cuatro pasos:


1.- Copia un byte de U1 a AL.
2.- Substrae un byte de U2 desde AL.
3.- Ajusta el resultado.
4.- Copia el resultado a U1.
La primera resta usa SUB, las restas subsecuentes usan SBB para tomar en cuenta el posible prstamo. Si
hay un prstamo extremo se debe saltar a una condicin de error que maneje el problema adecuadamente.
; resta de nmeros decimales sin empacar: U1 <-- U1-U2
MOV
AL,U1+2
SUB
AL,U2+2
AAS
MOV
U1+2,AL
; --- resta U2+1 de U1+1
MOV
AL,U1+1
SBB
AL,U2+1
AAS
MOV
U1+1,AL
; --- resta U2 de U1
MOV
AL,U1
SBB
AL,U2
AAS
MOV
U1,AL
; si la ultima resta genero un prestamo (CF=1)
; salta a una condicin de error
JC
ERROR_RESTA

39

14.8 Restando nmeros decimales multibytes empacados.


Hay un par de diferencias entre las tcnicas de resta multibyte de nmeros decimales sin empacar y
empacados.
Primero, debes usar un ajuste diferente a AAS, DAS. Segundo, debes procesar dos dgitos a la vez
(debido a que cada byte contiene dos dgitos).
El siguiente ejemplo, ilustra como restar dos nmeros empacados de tres bytes, P1 y P2, el resultado
queda en P1.
P1
P2

DB 56H,43H,21H
DB 45H,68H,54H

; resta de nmeros decimales empacados: P1 <-- P1-P2


MOV
AL,P1+2
SUB
AL,P2+2
DAS
MOV
P1+2,AL
; --- resta P2+1 de P1+1
MOV
AL,P1+1
SBB
AL,P2+1
DAS
MOV
P1+1,AL
; --- resta P2 de P1
MOV
AL,P1
SBB
AL,P2
DAS
MOV
P1,AL
; si la ultima resta genero un prestamo (CF=1)
; salta a una condicin de error
JC
ERROR_RESTA

14.9 Multiplicacin decimal.


Debes multiplicar nmeros decimales un byte a la vez. Copia uno de los operandos a AL. Despus
multiplcalo por otro operando usando la instruccin MUL, y despus lleva a cabo el ajuste.
EL procesador solo puede multiplicar nmeros decimales sin empacar. As la nica instruccin de ajuste
es AAM, si quieres multiplicar nmeros empacados tendrs de desempacarlos primero.
Ya que cada operando tiene un rango de 0 a 9, el resultado est en el rango de 0 a 81. El primer dgito es
colocado en AH; el segundo dgito es colocado en AL. Si el resultado es 9 o menor, AH contendr un 0.
No existe sobreflujo posible para el resultado.
Aqu hay un ejemplo que multiplica dos campos dato, U1 y U2, cada uno contiene un dgito decimal sin
empacar.
40

U1
DB 7H
U2
DB 6H
; multiplicar AH:AL <-- U1+U2
MOV
AL,U1
MUL
U2
AAM
La instruccin AAM tiene un uso inesperado que puede ser til: AAM puede tomar un numero binario de
AL y sepralo en dos nmeros decimales. AAM permite hacer esto dividiendo AL entre 10 y poniendo el
cociente en AH y el residuo en AL. Esto significa que puedes usar a AAM para dividir a AL entre 10
cuando lo necesites.
14.10 Divisin decimal: AAD.
La divisin decimal divide dos nmeros decimales sin empacar por un nmero decimal de un dgito
sin empacar. A diferencia de las otras operaciones decimales, la divisin requiere un ajuste antes de la
ejecucin de la operacin. Para hacer esto use la instruccin AAD.
AAD asume que el registro AH:AL contiene los dos dgitos decimales sin empacar. EL primer dgito en
AH y el segundo en AL. AAD prepara el numero convirtiendo los dos bytes en un byte sin signo en
binario. Esto permite ejecutar la divisin con la instruccin DIV.
Una vez que DIV hace s trabajo, el cociente es colocado en AL. Si el cociente es nueve o menor el valor
binario en AL es el mismo que su valor sin empacar, si el cociente es mayor que 9 debes convertir el
valor de AL en dos dgitos decimales sin empacar.
EL modo ms fcil de hacer esto es usar la instruccin AAM. El nico problema de AAM es que destruye
el contenido de AH. debes asegurarte salvar el contenido de AH antes de usar a AAM.
Aqu hay un ejemplo que divide U2 entre U1, U2 contiene dos dgitos decimales sin empacar, U1
contiene un dgito decimal sin empacar; los dos son de tipo byte.
U1
U2

DB 3H
DB 4H,7H

El siguiente ejemplo divide U2 entre U1. El cociente es almacenado como dos dgitos decimales sin
empacar en AH:AL. El residuo es almacenado en un dgito sin empacar en BL. La divisin es 47/3,
obteniendo 15 de cociente y 2 de residuo.
; division decimal sin empacar U2 / U1
; AH:AL <--- cociente, BL <--- residuo
MOV
AH,U2
MOV
AL,U2+1
AAD
DIV
U1
MOV
BL,AH
AAM
{_____________o___________}
41

CAPITULO 15

TRABAJAR CON STRINGS

Los strings pueden ser utilizados para almacenar caracteres, nmeros con signo, etc. Existen algunas
operaciones que funcionan con los strings. El procesador tiene un par de instrucciones que hacen
operaciones bsicas e importantes directamente. En este captulo aprenders cuales son esas instrucciones
y como utilizarlas.
Nuevos Trminos
String. Una secuencia de bytes o palabras.
tabla de traduccin. Una secuencia de bytes cuyos valores son usados con la instruccin XLAT para
substituir un byte por otro.
15.1 Como definir un String.
Para definir un string se pueden usar las directivas DB o DW. Puedes definir string que sean
constantes o variables. Aqu hay algunos ejemplos:
STRING
ZEROS
ARRAY
LIST

DB
DW
DW
DB

100 DUP(*)
50 DUP(0)
75 DUP(?)
abcde

Cuando sea posible usa DUP para definir al string, as podrs hacer uso de LENGTH, la cual es muy til
con algunos comandos de strings. Si no utilizas el DUP, no podrs usar el atributo LENGTH.

15.2 Las cinco instrucciones bsicas de Strings.


Hay cinco instrucciones que forman la base de todas las operaciones que puedes hacerle a un string.
Estas estn descritas en la tabla 15-1. Ellas operan en strings, un elemento (byte o word) a la vez.
Tabla 15-1 Las instrucciones bsicas de los strings
Instrucciones
Funcin
Descripcin
MOVSB
Move
Copia un elemento a otro
MOVSW
CMPSB
Compare
Compara de un elemento a otro
CMPSW
SCASB
Scan
Busca un valor especifico
SCASW
LODSB
Load
Copia al registro AX (AL)
LODSW
STOSB
Store
Copia desde el registro AX (AL)
STOSW
42

15.3 Operandos usados en las instrucciones de strings.


Cada instruccin de strings requiere dos operandos. Sin embargo, no necesitas especificar los
operados, en su lugar, el procesador automticamente usa los valores de ciertos registros. Por ejemplo l
instruccin MOVSB y MOVSW asumen que SI contiene el desplazamiento del string a ser copiado y DI
contiene el desplazamiento de la nueva locacin.
La tabla 15-2 muestra los registro usados por las instrucciones, SI y DI siempre contienen los
desplazamientos de los strings. AL y AX siempre contiene o reciben el valor actual. Para trabajar con
strings, primero preparas los registros, y entonces usas la instruccin.
Tabla 15-2 Operandos de las instrucciones para strings
Instrucciones
Primer operando
Segundo operando
MOVSB
offset en SI
offset en DI
MOVSW
CMPSB
offset en SI
offset en DI
CMPSW
SCASB
AL o AX
offset en DI
SCASW
LODSB
AL o AX
offset en SI
LODSW
STOSB
offset en DI
AL o AX
STOSW
15.4 Preparar SI y DI para instrucciones con strings.
El procesador pone restricciones de como puedes usar a SI y DI. SI puede referir a un string en el
segmento de datos o extra. Sin embrago, a menos de que especifiques otra cosa, el procesador asume que
SI se refiere al segmento de datos y DI siempre se refiere al segmento extra.
Para muchos programas lo mejor es que el segmento de datos y el segmento extra sean el mismo
segmento, esto facilita el uso de las instrucciones para strings. Para hacer esto el ASUME pude estar
definido como:
ASSUME CS:CSEG, SS:SSEG, DS:DSEG, ES:DSEG
Cuando actualices los registros, copia el registro de segmento DS al segmento de datos y extra.
; actualizar los registros de segmento
MOV
AX,DSEG
MOV
DS,AX
MOV
ES,AX
Como los segmentos de datos y extra son el mismo, es simple copiar desplazamientos a SI y DI. Por
ejemplo si STRING1 es el string fuente y STRING2 es el string destino, puedes usar la instruccin LEA
como sigue:
LEA

SI,STRING1
43

LEA

DI,STRING2

15.5 Preparar SI y DI con segmentos extra y de datos.


Cuando el programa tiene segmento de datos y extra separados, se pueden hacer varias
posibilidades. El operando fuente (SI) y el destino (DI) pueden estar en el segmento extra o de datos. Est
seccin describe estas posibilidades y como tratarlas, el string fuente es STRING1 y el string destino es
STRING2.
Cuando el string fuente est en el segmento de datos, puedes ajustar a SI de la siguiente manera:
LEA

SI,STRING1

Cuando el string fuente o destino est en el segmento extra, debes mostrar explcitamente que ES es el
registro de segmento:
LEA
LEA

SI,ES:STRING1
DI,ES:STRING2

Como mencione en la ltima seccin, cuando usas una instruccin de strings, el procesador supone que el
registro SI se refiere al segmento de datos. Si el cdigo fuente est en el segmento extra, debes especificar
ES antes de SI.
Cuando es string destino est en el segmento de datos, la situacin es ms compleja. Esto es debido a que
el procesador demanda que, con instrucciones, DI se refiere solo al segmento extra. La solucin es hacer
que el segmento extra sea temporalmente igual al segmento de datos.
Para hacer esto, presta ES y ajstalo al mismo valor de DS. Por supuesto primero debes salvar el
contenido de ES para restaurarlo despus. El mejor modo de salvar a ES es ponerlo en la pila, y despus
de la operacin string sacarlo de nuevo a su lugar. Una vez que el segmento extra es temporalmente igual
a DS puedes usar LEA para copiar el offset de DI.
; salvar el contenido de ES
PUSH
ES
; copiar DS a ES
PUSH
DS
POP
ES
; ejecutar la operacin string
LEA
DI,STRING2
-- otras instrucciones -; restaurar el contenido de ES
POP
ES
Hay otro mtodo elegante para manejar la misma situacin. Primero declara un campo dato de palabra
doble para guardar la direccin completa del string. Por ejemplo si el string destino es de 100 bytes, los
estatutos del segmento de datos seran como estos:
STRING2
DB
100 DUP(?)
STRING_ADDR
DD
STRING2
44

Cuando ajustes ES y DI, puedes usar una instruccin LES para copiar la direccin completa a DI:
; salvar el contenido de ES
PUSH
ES
; ejecutar la operacin string
LES
DI,STRING_ADDR
-- otras instrucciones -; restaurar el contenido de ES
POP
ES

15.6 Instrucciones de repeticin de strings: REP, REPE y REPNE.


Cada una de las cinco instrucciones bsicas operan con un byte o word a la vez. Para procesar el
string completo necesitan ejecutar la instruccin repetidamente, para cada byte o word en el string. Para
hacer esto, use la instruccin REP directamente antes de cada instruccin. REP le dice al procesador que
ejecute la instruccin repetidamente, por ejemplo
REP

MOVSB

Para usar REP, debes colocar en CX el nmero de veces que quieres ejecutar la instruccin string, por
ejemplo para ejecutar 100 veces la instruccin MOVSB usa
REP

MOV
MOVSB

CX,100

REP usa la siguiente lgica: mientras CX sea diferente de 0, resta 1 de CX y ejecuta la instruccin string.
Existen dos variaciones de REP que son usadas en las instrucciones CMPSB, CMPSW y SCASB,
SCASW. Estas instrucciones comparan dos valores.
REPE repite mientras CX sea diferente de 0 y mientras los bytes de los string a comparar
sean iguales. REPE es til para buscar un byte o word que no sea igual a un valor particular.
REPNE repite mientras CX sea diferente de 0 y mientras los bytes o words de los strings a
comparar no sean iguales. REPNE es til para buscar un byte o word que cheque con un
valor particular.
Es conveniente tener un modo general de ajustar el valor de CX, esto puedes hacerlo si usas el atributo
LENGTH.

15.7 Especificar la direccin de la operacin del string: CLD y STD.


Cuando ejecutas una operacin string repetidamente, los valores en estos registros de los registros
DI y SI deben ser actualizados para apuntar a cada byte o word en secuencia.
Por ejemplo, considere la siguiente instruccin para copiar un string a otro. EL string consiste de 100
bytes:
45

LEA
SI,STRING1
LEA
DI,STRING2
MOV
CX,100
REP
MOVSB
SI contiene el desplazamiento del primer byte a ser copiado. DI contiene el desplazamiento del destino. Si
y DI son actualizados automticamente por la instruccin MOVSB, como lo hacen todas las operaciones
con strings
Aqu esta como funciona. Despus de hacer su trabajo la instruccin string examina la bandera de
direccin (DF). La cual se puede poner a un valor de 1 con la instruccin STD o a 0 con la instruccin
CLD. Si DF est limpia a 0, la instruccin incrementa los registros en 1 para bytes o en 2 para palabras, si
DF est en 1 la instruccin incrementa los registros. As puedes barrer un string de atrs hacia adelante o
viceversa.
Aqu hay dos ejemplos, ambos copian STRING1 de 100 bytes a STRING2. El primer ejemplo inicia de
adelante hacia atrs, byte por byte. El segundo ejemplo copia de atrs hacia adelante.
; copia un string de bytes (adelante)
LEA
SI,STRING1
LEA
DI,STRING2
MOV
CX,LENGTH STRING1
CLD
REP
MOVSB
; copia un string de bytes (atrs)
LEA
SI,STRING1+99
LEA
DI,STRING2+99
MOV
CX,LENGTH STRING1
STD
REP
MOVSB
El esquema general para usar una instruccin string es
1.- Preparar los registros SI, DI, AX, AL.
2.- Ajustar CX al numero de elementos en el string.
3.- Limpiar la bandera CF.
4.- Ejecutar REP (REPE o REPNE) seguida de la instruccin de strings.
Cuando procesas un string hacia atrs, es conveniente referirse al ltimo elemento en el string usando los
operadores SIZE, TYPE, + y -.
; copia un string de bytes (atrs)
LEA
SI,STRING1 + SIZE STRING1- TYPE STRING1
LEA
DI,STRING2 + SIZE STRING2 - TYPE STRING2
MOV
CX, LENGTH STRING1
STD
REP
MOVSB

15.8 Copiar un string: MOVSB y MOVSW.


46

Las instrucciones MOVSB y MOVSW copian un string de un offset a otro. MOVSB copia bytes y
MOVSW copia words. Estas instrucciones usan los registros DI y SI. Si deben contener el offset del
string a ser copiado (la fuente). DI debe contener el offset al cual el string se debe copiar (el destino).
Aqu hay un ejemplo. Digamos que STRING1 es un string de bytes. Para copiar STRING1 a STRING2
hacia adelante, usa
; copiar un string ce bytes
LEA
SI,STRING1
LEA
DI,STRING2
MOV
CX,LENGTH STRING1
CLD
REP
MOVSB
Si STRING1 contiene palabras, debes usar MOVSW en lugar de MOVSB. Muchas veces, cuando copias
hacia adelante limpiando la bandera de direccin a 0. Sin embargo, si la fuente es ms grande que el
destino, debes ser cuidadoso. En tales casos, la fuente puede cambiar por la operacin de copia. Si la
fuente es una direccin ms baja que el destino, la operacin puede cambiar algo de la fuente antes de que
tenga oportunidad de ser copiada.
Aqu hay un ejemplo: Digamos que STRING es un string de bytes. Quieres copiar el string entero a una
locacin 5 bytes ms alta. Considere que pasa con las siguientes instrucciones:
; copia un string suprimiendo locaciones (hacia adelante)
LEA
SI,STRING
LEA
DI,STRING+5
MOV
CX,LENGTH STRING
CLD
REP
MOVSB
Los primeros cinco bytes son copiados como siguen:
STRING ---> STRING+5
STRING+1 ---> STRING+6
STRING+2 ---> STRING+7
STRING+3 ---> STRING+8
STRING+4 ---> STRING+9
Sin embargo note que pasa ahora. EL siguiente byte a ser copiado es STRING+5 que ha sido cambiado.
De hecho, una vez que pasas STRING+4 todos los valores originales de la fuente sern cambiados antes
de copiarlos. La solucin es iniciar al final del string y copiar hacia atrs.
; copia un string hacia atrs suprimiendo locaciones
LEA
SI,STRING + SIZE STRING - TYPE STRING
LEA
DI,STRING + SIZE STRING - TYPE STRING + 5
MOV
CX,LENGTH STRING
STD
REP
MOVSB
Utiliza las siguientes guas para el orden:
1.- Si la fuente y destino no se sobreescriben, MOVSB y MOVSW no cambian el valor de la fuente.
47

2.- Copia hacia atrs si todas estas condiciones se presentan:


a) La fuente y el destino estn en el mismo segmento
b) La fuente y el destino se sobreescriben
c) El offset de la fuente es menor que el offset del destino
15.9 Comparar un string con otro: CMPSB y CMPSW.
Las instrucciones CMPSB y CMPSW comparan un string con otro. SI debe contener el offset del
primer string y DI el offset del segundo. Existen dos posibilidades para comparar strings. Si quieres ver si
los strings son iguales, usa REPE; si quieres ver si los strings son diferentes, usa REPNE.
Aqu hay dos ejemplos para compara un string de bytes de otro. El primer ejemplo checa si los strings son
iguales, el segundo ejemplo se utiliza para checar si los strings son diferentes.
; compara dos strings para ver si son iguales (adelante)
LEA
SI,STRING1
LEA
DI,STRING2
MOV
CX,LENGTH STRING1
CLD
REPE
CMPSB
; compara dos strings para ver si son diferentes (adelante)
LEA
SI,STRING1
LEA
DI,STRING2
MOV
CX,LENGTH STRING1
CLD
REPNE CMPSB
Es importante comprender que una operacin de comparacin puede terminar de dos maneras
una igualdad (REPE) o diferencia (REPNE) han sido encontradas
La comparacin termino de procesar las cadenas completamente.
Una vez que la comparacin termina es importante distinguir cual fue el caso. Puedes hacer esto usando
un salto condicional: JE para probar si la comparacin fue igual; JNE para probar si la comparacin fue
diferente.
Aqu hay un ejemplo que ilustra este punto. El ejemplo compara dos strings. Si son iguales AX es puesta
a cero, si son diferentes AX contiene 1.
; compara dos strings para iguales (adelante)
LEA
SI,STRING1
LEA
DI,STRING2
MOV
CX,LENGTH STRING1
CLD
REPE
CMPSB
; if los strings son iguales AX<--0
; sino
AX<--1
JE
L1
MOV
AX,1
JMP
L2
48

L1:
L2:

MOV

AX,0

a veces es til saber cual palabra o byte causo la terminacin. Todo lo que tienes que hacer es examinar
SI, sin embargo SI contiene el valor de la siguiente posicin (byte o word) que iba a examinar. Por
ejemplo, digamos que comparas dos strings de bytes y cuando la operacin concluye, SI tiene un valor de
57. As la diferencia est en el byte 56. En general si comparas bytes tienes que restar 1 a SI o 2 si son
palabras.
Aqu hay un ejemplo que compara dos strings para igualdad, si los strings son iguales, AL es puesta a 0,
si los strings son diferentes, AL est puesta al segundo string en el elemento que no es igual al primer
string.
; compara dos strings para igualdad (adelante)
LEA
SI,STRING1
LEA
DI,STRING2
MOV
CX,LENGTH STRING1
CLD
REPE
CMPSB
; if son iguales AL <--- 0
; sino AL <--- elemento diferente del primer cadena
JE
L1
DEC
SI
MOV
AL,STRING2[SI]
L1:
JMP
L2
L2:
MOV
AL,0
Este ejemplo compara strings que contiene bytes. Para usar palabras, todo los que tienes que hacer es
cambiar AL por AX, cambiar CMPSB por CMPSW, y restar dos de SI en lugar de 1.
en algunos casos, puedes procesar los strings hacia atrs. Todo los que tienes que hacer es ajustar la
bandera a 1 en lugar de 0. El siguiente ejemplo procesa los strings hacia atrs, checando si son diferentes
en cada posicin.
;compara dos strings para ver si son diferentes (atrs)
LEA
SI,STRING1 + SIZE STRING1 - TYPE STRING1
LEA
DI,STRING2 + SIZE STRING2 - TYPE STRING2
MOV
CX,LENGTH STRING1
STD
REPNE CMPSW
15.10 Buscar un valor especifico en un string: SCASB y SCASW.
Las instrucciones SCASB y SCASW buscan un valor en un string. SCASB para bytes y SCASW
para words. Estas instrucciones son muy parecidas a CMPSB y CMPSW, solo que las primeras
instrucciones comparan un string contra un mismo valor.
SCASB usa los registros AL y DI. SCASW usa los registros AX y DI. AL o AX contiene el valor a
comparar. DI debe contener el offset del string a buscar. Para buscar un valor que sea diferente del
contenido de AL o AX usa REPE. Para buscar un valor igual usa REPNE.
49

Aqu hay algunos ejemplos. El primero ilustra un uso comn de SCASB. El ejemplo busca en un string de
bytes, cada uno guarda un carcter. La instruccin busca el primer carcter diferente a un blanco. Si se
encuentra se copia a BL sino BL queda con un blanco.
; busca en un string de bytes (adelante) el primer carcter diferente de blanco
MOV
AL,
LEA
DI,STRING
MOV
CX,LENGTH STRING
CLD
REPE
SCASB
; si no esta el blanco
; sino
JE
DEC
MOV
JMP
L1:
MOV
L2:

BL <--- carcter
BL <--- blanco
L1
DI
BL,STRING[DI]
L2
BL,

El siguiente ejemplo busca un string hacia atrs, buscando el primer blanco, si est su offset se copia a
BX, sino BX se pone a 0.
; busca un string de bytes (atrs) para un blanco
MOV
AL,
LEA
DI,STRING + SIZE STRING - TYPE STRING
MOV
CX,LENGTH STRING
STD
REPNE SCASB
; if esta el blanco
; sino
JNE
INC
MOV
JMP
L1:
MOV
L2:

BX <--- offset del carcter


BX <--- 0
L1
DI
BX,DI
L2
BX,0

El ltimo ejemplo busca la primer palabra que contenga FFFFH en un string de palabras hacia atrs. Si la
palabra es encontrada, la bandera de acarreo CF se pone a 0 sino se pone a 1.
; busca el valor FFFFH en un string (atrs)
MOV
AX,0FFFFH
LEA
DI,STRING
MOV
CX,LENGTH STRING
CLD
REPNE SCASW
; if FFFFH esta

CF <--- 0
50

; sino

L1:
L2:

JE
STC
JMP
CLC

CF <--- 1
L1
L2

15.11 Llenar un string con un valor especifico: STOSB y STOSW.


Las instrucciones STOSB y STOSW se usan para llenar un string con un valor especifico. Los
registros AL o AX contiene el valor. El registro DI contiene el offset del string. Para llenar el string, pon
DI al offset del string y usa la instruccin REP.
Aqu hay un ejemplo que llena un string de bytes con blancos.

REP

MOV
LEA
MOV
CLD
STOSB

AL,
DI,STRING
CX,LENGTH STRING

Aqu hay un ejemplo que llena un string de palabras con ceros

REP

MOV
LEA
MOV
CLD
STOSW

AX,0
DI,STRING
CX,LENGTH STRING

Como puedes ver ambos ejemplos procesan el string hacia adelante. Cuando llenas un string no puedes
llenarlo hacia atrs.

15.12 Llenar un string con un patrn especifico: MOVSB y MOVSW.


Algunas veces necesitas llenar un string con un patrn especifico, por ejemplo lo caracteres *---*
una y otra vez. Para hacer esto, puedes usar la instrucciones MOVSB y MOVSW. Como mencione
anteriormente estas instrucciones pueden sobreescribir el string fuente si sobrepasa al string destino y si
el offset de fuente es menor que el destino, cuando llenas un string con un patrn, puedes procesarlo hacia
adelante.
Aqu hay un ejemplo que llena un string de bytes con el patrn *---*. Primero, copia el patrn al inicio
del string, y entonces propaga el patrn usando MOVSB con una sobreescritura de fuente y destino.
; llenar el string de bytes con un patrn *---*
; --- ajustar el patrn
MOV
STRING,*
MOV
STRING+1,-
MOV
STRING+2,-
51

MOV
STRING+3,-
MOV
STRING+4,*
; llenar el string
LEA
SI,STRING
LEA
DI,STRING+5
MOV
CX,LENGTH STRING
CLD
REP
MOVSB

15.13 Crear operaciones personalizadas con strings.


Las instrucciones LODSB, LODSW, STOSB y STOSW copian un byte o una palabra entre los
registros AL o AX y las locaciones de memoria. Usando las instrucciones en la figura 15-3, puedes copiar
un string de una locacin de memoria a otra de modo que cada byte o palabra pase a travs de AL o AX.
Si as es, puedes procesar el valor en el registro. Esto te permite disear operaciones con strings
personalizadas.
Tabla 15-3 Fuentes y destinos de LODSB, LODSW, STOSB y STOSW
Instruccin
Copia qu?
De donde?
A donde?
LODSB
byte
offset SI ---> AL
LODSW
palabra
offset SI ---> AX
STOSB
byte
AL
---> offset DI
STOSW
palabra
AX
---> offset DI
El esquema es el siguiente
1.- Copia el offset del string fuente a SI.
2.- Copia el offset del string destino a DI.
3.- Copia la longitud del string a CX.
4.- Pon o limpia la bandera de direccin DF.
5.- Para cada byte (palabra) en la fuente,
Copia el byte (palabra) de la fuente a AL (AX).
Procesa el valor en AL (AX).
Copia el nuevo valor de AL (AX) al destino.
Aqu hay un ejemplo que copia u string de palabras de una locacin a otra. Cada palabra contiene un
nmero con signo. El ejemplo examina cada palabra y si es negativa, la reemplaza con 0.
; copia una string de palabras de nmeros con signo a otra.
; convirtiendo los nmeros negativos a ceros.
LEA
SI,STRING1
LEA
DI,STRING2
MOV
CX,LENGTH STRING1
CLD
L1:
LODSW
; -- procesar cada numero --CMP
AX,0
JNL
L2
MOV
AX,0
52

L2:
STOSW
LOOP L1
Algunas veces quieres trabajar con solo un string no con dos. Todo lo que tiene que hacer es copiar el
mismo offset a SI y DI. El siguiente ejemplo procesa un string de palabras que contiene nmeros con
signo. El ejemplo reemplaza los nmeros negativos con 0. La diferencia es que SI y DI son idnticos.
; copia una string de palabras de nmeros con signo a otra.
; convirtiendo los nmeros negativos a ceros.
LEA
SI,STRING
LEA
DI,STRING
MOV
CX,LENGTH STRING
CLD
L1:
LODSW
; -- procesar cada numero --CMP
AX,0
JNL
L2
MOV
AX,0
L2:
STOSW
LOOP L1
Un uso final es examinar los byte o palabras en un string sin cambiarlos. Simplemente quitando las
instrucciones STOSB y STOSW. El siguiente ejemplo cuneta el nmero de blancos en un string de bytes.
; copia una string de palabras de nmeros con signo a otra.
; convirtiendo los nmeros negativos a ceros.
LEA
SI,STRING
LEA
DI,STRING
MOV
CX,LENGTH STRING
CLD
MOV
BX,0
L1:
LODSB
; -- procesar cada carcter--CMP
AL,
JNE
L2
INC
BX
L2:
LOOP L1
15.14 Trasladar desde una tabla: XLAT.
La instruccin XLAT usa el valor de un byte para extraer un segundo valor de una tabla. El segundo
valor es entonces copiado al byte original. XLAT significa trasladar.
XLAT asume que AL contiene el valor para la traslacin y que el registro BX contiene el offset de la
tabla. XLAT usa el valor en AL como ndice en la tabla. Aqu hay un ejemplo simple, TABLA es una
secuencia de bytes que contiene diez valores hex del 30H al 39H. TABLA est definida como sigue:
53

TABLA DB

30H,31H,32H,33H,34H,35H,36H,37H,38H,39H

Considere las siguientes instrucciones:


MOV
AL,5
LEA
BX,TABLA
XLAT
XLAT examina el valor en AL, en este caso 5, entonces XLAT copia el valor del offset TABLA+5 a AL.
En este caso copia 35H a AL. La tabla usada por XLAT es conocida como tabla de traslacin. Una tabla
de traslacin debe contener bytes. XLAT puede trasladar hasta 256 valores diferentes.
XLAT es usado especialmente cuando necesitas trasladar un string de bytes. Para hacer esto usa un ciclo
con las instrucciones LODSB y STOSB. Aqu hay un ejemplo comn que usa XLAT para trasladar un
string de dgitos decimales a sus cdigos ASCII. El ejemplo usa una tabla de traslacin definido como
sigue:
D_TABLA

DB

30H,31H,32H,33H,34H,35H,36H,37H,38H,39H

; trasladar un string de dgitos decimales a ASCII


LEA
SI,STRING
LEA
DI,STRING
MOV
CX,LENGTH, STRING
CLD
LEA
BX,D_TABLA
L1:
LODSB
XLAT
STOSB
LOOP
L1
Las instrucciones LODSB y STOSB trabajan con el LOOP para procesar cada byte en turno del string.
Cada byte es copiado a AL, trasladado por XLAT y entonces copiado de nuevo al string. Puedes usar este
ejemplo para trasladar un numero decimal sin empacar a ASCII. Simplemente copia el offset del numero
SI y DI. El ciclo procesa el numero, un dgito a la vez.
Aqu hay otro ejemplo. Este traslada un string de dgitos hex a ASCII. La figura 15-5 muestra los 16
dgitos hex y sus cdigos ASCII.
Figura 15-5
Los 16 dgitos hex
0 1 2 3 4 5 6 7 8 9 A B C D E F
30H 31H 32H 33H 34H 35H 36H 37H 38H 39H 41H 42H 43H 44H 45H 46H
Todo lo que tienes que hacer es usar la tabla de traslacin con los valores de los 6 dgitos extra:
H_TABLA
DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H
DB 41H,42H,43H,44H,45H,46H
Aqu esta una instruccin que hace el trabajo:
; traducir un string de seis dgitos a ASCII
LEA
SI,STRING
54

LEA
MOV
CLD
LEA

DI,STRING
CX,LENGTH STRING
BX,H_TABLA

L1:
LODSB
XLAT
STOSB
LOOP

L1

En ambos ejemplos, la traslacin tiene valores desde 0. Sin embargo, digamos que quieres trasladar un
string de caracteres ASCII a dgitos decimales, en este caso el rango de valores ser de 30H a 39H.
EL modo de hacer esto es definir una tabla que vaya desde 0H a 3AH. Los bytes de 31H a 3AH sern
llenados con los valores decimales 0 al 9. Los bytes anteriores, de 0H al 30H, pueden ser llenadas con lo
que sea :
A_TABLA

DB

30H DUP(0),0,1,2,3,4,5,6,7,8,9

Las siguientes instrucciones usan una tabla para trasladar un string de caracteres ASCII a dgitos
decimales. Esencialmente, este ejemplo traslada caracteres ASCII a decimales sin empacar.
; trasladar un string de ASCII a dgitos decimales
LEA
SI,STRING
LEA
DI,STRING
MOV
CX,LENGTH STRING
CLD
LEA
BX_TABLA
L1:
LODSB
XLAT
STOSB
LOOP
L1
Para usar XLAT debes entender dos cosas. Primero, debes usar el mismo tipo de estructura de control con
las diferentes tablas. Segundo, debes asegurarte que XLAT no haga referencia a valores que no existen en
la tabla de traslacin.

15.15 Alternar nombres de las instrucciones string: MOVS, CMPS, SCAS, LODS y STOS.
Cada par de instrucciones tiene nombres alternos. Estos nombres estn en la tabla 15-3.
Tabla 15-3 Nombres alternos de las instrucciones string
Par de instrucciones
Nombre alterno
MOVSB
MOVS
MOVSW
CMPSB
CMPS
CMPSW
SCASB
SCAS
SCASW
55

LODSB
LODSW
STOSB
STOSW

LODS
STOS

Si utilizas nombres alternos debes especificar sobre que campos dato van a interactuar ya sean bytes o
palabras.
Por ejemplo, las siguientes conjuntos de instrucciones son equivalentes:
; copia un string de bytes (adelante) usando MOVSB
LEA
SI,STRING1
LEA
DI,STRING2
MOV
CX,LENGTH STRING1
CLD
REP
MOVSB
; copia un string de bytes (adelante) usando MOVS
LEA
SI,STRING1
LEA
DI,STRING2
MOV
CX,LENGTH STRING1
CLD
REP
MOVSB STRING1,STRING2
Note que cuando especificas los operandos explcitamente, debes poner a SI y DI; el ensamblador no lo
hace por ti. Cuando usas los nombres alternos, el ensamblador checa los tipos y la accesibilidad de los
operandos.
Por ejemplo, digamos que necesitas copiar STRING1 a STRING2, y ambos strings estn en el segmento
extra, puedes usar:
; copia un string de bytes (adelante) usando MOVS
LEA
SI,ES:STRING1
LEA
DI,ES:STRING2
MOV
CX,LENGTH STRING1
CLD
REP
MOVS
ES:STRING1,STRING2
{_____________o___________}

56

CAPITULO 16

TRABAJAR CON BITS

Hay dos razones por las cuales debes aprender a trabajar con bits. Primero puedes usar los bits para
representar banderas. La segunda razn es para tener un control mas exquisito sobre los datos. En este
captulo aprenders a usar los tipos de operaciones bsicas.
Para cambiar y probar los valores bits dentro de un byte o palabra (AND, OR, XOR, NOT, TEST)
Para cambiar las posiciones de los bits en un byte o palabra (SHL, SHR, SAL, SAR, ROL, RCL, RCR)
Nuevos Trminos
Mascara de bits. Una secuencia de bits que junto con la operacin AND, OR, o XOR, indica cual bits
deben ser cambiados y cuales ignorar.

16.1 Las cuatro operaciones fundamentales de Bits.


En orden de usar bits o banderas, hay cuatro operaciones fundamentales que debes ejecutar en byte o
palabras.

poner un bit a 0.
poner un bit a 1
complementar ciertos bits (0 a 1 y 1 a 0)
complementar todos los bits

Estas operaciones son hechas por las instrucciones AND, OR, XOR, y NOT respectivamente. Aqu estn
los formatos:
AND
OR
XOR
NOT

operando1,operando2
operando1,operando2
operando1,operando2
operando

Cada operando puede ser un byte o una palabra. En las instrucciones con dos operandos estos deben ser
del mismo tamao. El primer operando puede ser un registro o un campo dato; el segundo operando pude
ser un registro, campo dato o valor inmediato.
estas instrucciones modifican los bits dentro del primer operando. El segundo permanece sin cambio.
Aqu hay algunos ejemplos:
AND
OR
XOR

AX,BX
AL,VALOR
VALOR,DH
57

AND
OR
XOR

DATA,0001100111110110B
AX,3H
DL,a

16.2 Mascaras de Bits.


La instrucciones AND, OR, y XOR modifican los bits del primer operando. Los bits son
seleccionados por el valor del segundo operando, el cuales llamado la mascara de bits. EL segundo
operando permanece sin cambios.
Una mascara de bits cubre ciertos bits del byte o palabra. Solo los bits expuestos pueden ser encendidos o
apagados o complementados. El modo en que opera la mascara es completamente diferente en cada
instruccin. LA idea general es que construyas la mascara usando 0s y 1s conociendo tus
especificaciones.
Por ejemplo, la siguiente instruccin AND tiene una mascara de 0000111100001111B
AND

AX,0000111100001111B

La mascara tambin puede ser especificada con valores en hexadecimal


AND

AX,0F0FH

Otra tcnica til es usar un igual para asignar un valor a la mascara. As se puede usar un nombre en lugar
de un numero especifico.
MASCARA

EQU

0000111100001111B

La instruccin AND puede quedar como:


AND

AX,MASCARA

16.3 Apagar bits particulares: AND.


AND apaga bits particulares en el primer operando, el segundo que acta como la mascara
permanece sin cambios. En la mascara un 0 significa que el bit correspondiente se apagar; un 1 indica
que el bit permanecer sin cambios
Aqu hay un ejemplo, digamos que AL contiene 10010110B. Consideremos la instruccin:
AND

AL,11110000B

En este caso, la mascara es 11110000B. La mascara indica que ignorara los cuatro bits de mas a la
izquierda del contenido de AL y tratara de apagar los otros cuatro de mas a la derecha. As el resultado de
la instruccin es que AL tiene un valor de 10010000B.
Si la mascara es de puros 0s, AND apaga todos los bits en el primer operando. Por ejemplo:
AND

BX,0000000000000000B
58

Pone todos los bits de BX a 0.


Si la mascara es de puros 1s ninguno de los bits del primer operando se vera afectado. Por ejemplo la
siguiente instruccin deja sin cambios al contenido del byte VALOR.
AND

VALOR,11111111B

Uno de los usos ms tiles del AND es poder apagar un bit especifico en un byte o una palabra. Todo lo
que tienes que hacer es usar la mascara para que todos excepto un bit (el que quieres cambiar) no sean
afectados. Por ejemplo, para apagar el bit de mas a la derecha de CX, usa la instruccin:
AND

CX,1111111111111110B

La definicin formal de un AND es como sigue: Compara dos operandos, bit por bit, si los dos bits son 1,
deja un uno en el primer operando, sino deja un cero en ese operando. Las posibilidades son:
0
0
1
1

AND
AND
AND
AND

0
1
0
1

--->
--->
--->
--->

0
0
0
1

Otro ejemplo til del uso del AND es convertir caracteres numricos a decimales sin empacar. Si
examinas la figura 16-1, la cual muestra los caracteres ASCII del 0 al 9 en hex y sus correspondientes
decimales sin empacar, para convertir un numero ASCII a un decimal sin empacar todo lo que tienes que
hacer es cambiar los primeros cuatro bits a 0s. Por ejemplo, para convertir el carcter a 9 en decimal
sin empacar, debes cambiar 39H a 09H.
Figura 16-1 Cdigo ASCII y decimal sin empacar del 0 al 9
ASCII
30H 31H 32H 33H 34H 35H 36H 37H 38H 39H
decimal sin e. 00H 01H 02H 03H 04H 05H 06H 07H 08H 09H
Esto puedes hacerlo usando una mascara que cambie los 4 bits de mas a la izquierda a 0000B. La mascara
es 00001111B, el siguiente ejemplo convierte el carcter en AL a un decimal sin empacar:
AND

AL,00001111B

Si AX contiene dos caracteres numricos, uno en cada byte, la siguiente instruccin convierte ambos
caracteres a decimales sin empacar:
AND

AX,0000111100001111B

Algunas persona prefieren ponerlo en hexadecimal.


AND

AX,0F0FH

O usa un igual
CONVERT_ASCII EQU
AND

0F0FH
AX,CONVERT_ASCII

59

16.4 Encender Bits particulares: OR.


OR enciende bits particulares en el primer operando, el segundo que acta como la mascara
permanece sin cambios. En la mascara un 1 significa que el bit correspondiente se encender; un 0 indica
que el bit permanecer sin cambios
Aqu hay un ejemplo, digamos que AL contiene 10010110B. Consideremos la instruccin:
OR

AL,11110000B

En este caso, la mascara es 11110000B. La mascara indica que ignorara los cuatro bits de mas a la
derecha del contenido de AL y tratara de encender los otros cuatro de mas a la izquierda. As el resultado
de la instruccin es que AL tiene un valor de 11110110B.
Si la mascara es de puros 1s, OR enciende todos los bits en el primer operando. Por ejemplo:
OR

BX,1111111111111111B

Pone todos los bits de BX a 1.


Si la mascara es de puros 0s ninguno de los bits del primer operando se vera afectado. Por ejemplo la
siguiente instruccin deja sin cambios al contenido del byte VALOR.
OR

VALOR,00000000B

Uno de los usos ms tiles del OR es poder encender un bit especifico en un byte o una palabra. Todo lo
que tienes que hacer es usar la mascara para que todos excepto un bit (el que quieres cambiar) no sean
afectados. Por ejemplo, para encender el bit de mas a la derecha de CX, usa la instruccin:
OR

CX,0000000000000001B

La definicin formal de un OR es como sigue: Compara dos operandos, bit por bit, si los dos bits son 0,
deja un 0 en el primer operando, sino deja un 1 en ese operando. Las posibilidades son:
0
0
1
1

OR
OR
OR
OR

0
1
0
1

--->
--->
--->
--->

0
1
1
1

Otro ejemplo til del uso del OR es convertir decimales sin empacar a ASCII. Si examinas la figura 16-1,
la cual muestra los caracteres ASCII del 0 al 9 en hex y sus correspondientes decimales sin empacar, para
convertir un numero decimal sin empacar a ASCII todo lo que tienes que hacer es cambiar los primeros
cuatro bits a 3H. Por ejemplo, para convertir el decimal sin empacar 09H a ASCII, debes cambiar 09H a
39H.
Esto puedes hacerlo usando una mascara que cambie los 4 bits de mas a la izquierda a 0011B. La mascara
es 00110000B, el siguiente ejemplo convierte el decimal sin empacar al caracter ASCII:
60

OR

AL,00110000B

Si AX contiene dos decimales sin empacar, uno en cada byte, la siguiente instruccin convierte ambos
decimales sin empacar a caracteres ASCII:
OR

AX,0011000000110000B

Algunas persona prefieren ponerlo en hexadecimal.


OR

AX,3030H

O usa un igual
CONVERT_DEC
OR

EQU

3030H

AX,CONVERT_DEC

.
16.5 Complementar Bits particulares: XOR.
XOR complementa bits particulares en el primer operando, el segundo que acta como la mascara
permanece sin cambios. En la mascara un 0 significa que el bit correspondiente permanece sin cambios;
un 1 indica que el bit se complementara.
Aqu hay un ejemplo, digamos que AL contiene 00111100B. Consideremos la instruccin:
XOR

AL,11110000B

En este caso, la mascara es 11110000B. La mascara indica que ignorara los cuatro bits de mas a la
derecha del contenido de AL y tratara de complementar los otros cuatro de mas a la izquierda. As el
resultado de la instruccin es que AL tiene un valor de 11001100B.
Si la mascara es de puros 1s, XOR complementa todos los bits en el primer operando. Por ejemplo:
XOR

BX,1111111111111111B

Pone todos los bits de BX a su complemento.


Si la mascara es de puros 0s ninguno de los bits del primer operando se vera afectado. Por ejemplo la
siguiente instruccin deja sin cambios al contenido del byte VALOR.
AND

VALOR,00000000B

Uno de los usos ms tiles del XOR es poder complementar un bit especifico en un byte o una palabra.
Todo lo que tienes que hacer es usar la mascara para que todos excepto un bit (el que quieres cambiar) no
sean afectados. Por ejemplo, para complementar el bit de mas a la derecha de CX, usa la instruccin:
XOR

CX,0000000000000001B

61

La definicin formal de un XOR es como sigue: Compara dos operandos, bit por bit, si los dos bits son 1
o 0, pone el bit del primer operando a 0, sino deja un 1 en ese operando. Las posibilidades son:
0
0
1
1

XOR
XOR
XOR
XOR

0
1
0
1

--->
--->
--->
--->

0
1
1
0

16.6 Complementar un byte o un palabra completa: NOT.


NOT toma solo un operando y complementa todos los bits en ese operando. Cada 0 se cambia a 1 y
cada 1 cambia a 0: Aqu hay un par de ejemplos:
Si AX contiene 0011001100110011B, la instruccin
NOT

AX

Cambia AX a 1100110011001100B.
Si VALOR es un byte que contiene 11110000B, la instruccin:
NOT

VALOR

Cambia VALOR a 00001111B.


NOT es equivalente a un XOR con una mascaras de 1s. Las siguientes instrucciones equivalentes con
XOR:
XOR
XOR

AX,1111111111111111B
VALOR,11111111B

16.7 Probar Bits particulares: TEST.


EL formato de TEST es el siguiente:
TEST

operando1,operando2

TEST examina en primer operando para ver si un bit particular est encendido. Como con AND, OR y
XOR, el primer operando puede ser un registro o un campo dato. El segundo registro puede ser un
registro, campo dato o valor inmediato.
El segundo operando acta como mascara que especifica cuales bits del primer operando sean probados.
En la mascara un 0 indica que el bit correspondiente ser ignorado; un 1 indica que el bit correspondiente
ser examinado.
Aqu hay un ejemplo. Considere la instruccin:
TEST

AL,11110000B
62

En este caso, la mascar es 11110000B. La mascara le dice a TEST que ignore los 4 bits de mas a la
derecha de AL y que examine los 4 bits de mas a la izquierda.
TEST no cambia ninguno de los operandos. En su lugar TEST examina los operandos y entonces
actualiza la bandera de cero (ZF) para reflejar el resultado de la prueba. Si cualquiera de los bits
especificados est encendido, TEST pone ZF a 0; Si ninguno de los bits especificados est encendido,
TEST pone ZF a 1.
Esto significa que cuando el flujo de control de un programa depende de un valor de un bit especifico,
puedes usar JNZ para saltar si cualquiera de los bits especificados esta encendido. Puedes usar JNZ para
saltar si ninguno de los bits especificados est encendido.
Por ejemplo, la siguiente instruccin salta a L1 si cualquiera de los 4 bits de mas a la izquierda estn
encendidos:
TEST
JNZ

AL,11110000B
L1

Un uso ms comn de TEST es crear un ciclo que contine hasta que un bit particular se encienda o
apague. El siguiente ejemplo llama a un procedimiento, GET_INPUT, el cual cambia el valor de AL. EL
ciclo debe llamar GET_INPUT repetidamente hasta el bit 3 ( el cuarto bit de la derecha) en AL es
encendida.
; repite hasta (bit 3 de AL est encendido)
; llama a GET_INPUT
L1:
CALL
TEST
JZ

GET_INPUT
AL,00001000B
L1

El siguiente ejemplo llama a GET_INPUT repetidamente hasta que el bit 3 de AL est apagado:
; repite hasta (bit 3 de AL est apagado)
; llama a GET_INPUT
L1:
CALL
TEST
JNZ

GET_INPUT
AL,00001000B
L1

La definicin formal de TEST es para ejecutar una operacin AND sin cambiar ningn operando. ZF se
pone a 1 o a 0 dependiendo del resultado del AND.

16.8 Cambiar la posicin de los bits en un byte o palabra.


La instruccin descrita en la siguiente seccin cambia la posicin de un bit en un byte o en una
palabra. La lista de estas instrucciones est en la tabla 16-1. Puedes usar el mismo formato para todas las
instrucciones:
opcode

operando,contador
63

Por ejemplo:
SHL

VALOR,4

El primer operando puede ser un registro o un campo dato. Este operando debe ser un byte o palabra.
Cada una de estas instrucciones cambia los bits en el primer operando de izquierda a derecha. El numero
de posiciones es indicada por el valor del segundo operando (el contador)
Tabla 16-1 Instrucciones para cambiar las posiciones de los bits.
Nombre
Significado
SHL
Cambiar a la izquierda
SAL
Cambiar aritmticamente a la izquierda
SHR
Cambiar a la derecha
SAR
Cambiar aritmticamente a la derecha
ROL
Rotar a la izquierda
ROR
Rotar a la derecha
RCL
Rotar con acarreo a la izquierda
RCR
Rotar con acarreo a la derecha
Puedes especificar el contador de dos maneras, con un valor inmediato en el rango de 0 a 31. Por ejemplo
para cambiar los bits de AX cinco posiciones a la derecha, usas la instruccin:
SHL

AX,5

Tambin puedes usar a CL como el contador asegurndote que tenga un valor entre 0 y 31. El siguiente
ejemplo usa a CL como el contador para la misma operacin anterior.
MOV
SHL

CL,5
AX,CL

16.9 Las instrucciones bsicas de movimiento: SHL y SHR.


Las instrucciones SHL y SHR cambian bits a la izquierda o derecha respectivamente. Los bits que
son cambiados afuera se pierden. Por ejemplo si cambias el registro DL tres posiciones ala derecha:
SHR

DL,3

los tres bits originales de mas a la derecha se pierden. Sin embargo el ltimo bit que fue cambiado afuera
siempre queda en la bandera de acarreo CF. Esto es cierto para todas las instrucciones de cambio.
Por ejemplo si DL contiene

y cambias los bits tres posiciones a la derecha, los tres bits de ms a la derecha -100- se perdern. Si
embargo CF tendr el valor del ultimo bit perdido.

64

Sin embargo un byte o una palabra no solo pierde bits, tambin hay nuevos espacios generados por el
corrimiento que deben ser llenados. Con SHL y SHR, estos espacios son llenados con 0s. Por ejemplo si
DL contiene

y mueves los bits a tres posiciones a la derecha, las posiciones dems a la izquierda son llenadas con 0s,
lo cual produce lo siguiente:

Con un movimiento a la izquierda, los bits de mas a la derecha son llenados con 0s. Por ejemplo, si DL
tuviera 11001100 y movieras los bits tres posiciones a la izquierda:
SHL

DL,3

El valor final es

CF contiene el ultimo bit que fue sacado del registro (0).

16.10 Los usos del SHL y SHR.


SHL y SHR tienen dos usos importantes. Primero, puedes usarla para aislar parte de un byte o una
palabra.
Aqu hay un ejemplo. Digamos que quieres aislar los bits 3,4 y 5 en AL y moverlos a la parte mas a la
derecha el registro. Esto es, quieres cambiar

Primero cambia todos los bits a 0. Entonces cambia AL tres posiciones a la derecha:
AND
SHL

AL,00111000B
AL,3

Alternativamente podemos mover primero AL dos posiciones a la izquierda y luego cinco a la derecha:
SHL

AL,2
65

SHL

AL,5

El segundo uso importante de SHL y SHR es multiplicar y dividir en potencias de dos. Cuando usas
nmeros sin signo los movimientos a la izquierda multiplican por dos y los movimientos a la derecha
dividen entre 2.
Por ejemplo, digamos que AL contiene 00001010B (5). Moviendo bits a la izquierda dos posiciones
tenemos
00000101B (5) --------> 00010100B (20)
As como movimos en dos posiciones el contenido multiplicamos por 4.
Aqu hay algunos ejemplos. El primero multiplica BX por 16; el segundo divide VALOR entre 4:
SHL
SHR

BX,4
VALOR,2

Estas multiplicaciones son mas rpidas que las hechas por las operaciones DIV Y IDIV.
Figura 16-2 Numero de posiciones a mover para multiplicar y dividir
Para multiplicar o dividir por
mueve el numero de lugares
2
1
4
2
8
3
16
4
32
5
64
6
128
7
256
8
512
9
1024
10

16.11 Multiplicar y dividir nmeros con signo por movimiento de bits: SAL y SAR.
Las instrucciones SAL y SAR trabajan bien cuando quieres multiplicar o dividir nmeros con signo.
Sin embargo, necesitas instrucciones especiales cuando mueves nmeros con signo. Estas instrucciones
son SAL (mover aritmticamente a la izquierda) y SAR (mover aritmticamente a la derecha).
Aqu est la razn de estas instrucciones: Considere que pasa cuando mueves un numero con signo a la
derecha (dividir). Si el numero es negativo, el resultado debes ser negativo. Sin embargo, si usas SHR, los
espacios de ms a la izquierda sern llenados con 0s. Esto da un resultado completamente errneo. No
sol un valor errneo, sino con un signo positivo.
La solucin es como sigue: Cuando mueves nmeros con signo a la derecha, se llenan los espacios de
mas a la izquierda con 0s si el numero es positivo y con 1s si el numero es negativo
Aqu hay dos ejemplos. Digamos que AL contiene 00001111B(!%). aqu est lo que pasa cuando usas la
instruccin SAR para dividir entre 4:
66

El resultado es 00000011B (3): Esto es correcto debido a que 15/4 es tres con un residuo de 3. (recuerda
que cuando divides con movimiento de bits el residuo se pierde.)
En el segundo ejemplo, BL contiene 11110001B (-15). Aqu est lo que pasa cuando usas SAR para
dividir entre 4:

El resultado es 11111100B (-4). Esto es correcto debido a que en aritmtica con signo, -15/4 es -4 y sobra
-1.
Cuando multiplicas nmeros con signo no hay problema ya que siempre se llenan los espacios con ceros
As las instrucciones SAL y SHL son las mismas.

16.12 Las instrucciones de Rotacin: ROL, ROR, RCL y RCR.


Las instrucciones de rotacin son variaciones de las instrucciones de movimientos. La diferencia
lgica es como sigue: Con las instrucciones de movimiento los bits que son cambiados fuera se pierden y
los lugares vacos son reemplazados por ceros (o algunas veces 1s). Con las instrucciones de rotacin,
los bits forman un ciclo continuo de manera que los bits que salen fuera entra por el lado contrario. As
ningn bit se pierde.
ROR mueve bits a la derecha; ROL mueve bits a la izquierda.
Aqu hay dos ejemplos. Digamos que AL contiene 00001111B. Aqu est lo que pasa cuando usas ROR
para rotar AL a la derecha una posicin:

El bit de ms a la derecha es movido fuera y entra por el otro lado en el espacio libre, CF tiene el valor
del ultimo bit que sali en este caso 1.
En el segundo ejemplo, AL contiene 00001111B y ROL rota los bits cinco posiciones a la izquierda:

Uno por uno, los 5 bis son sacados fuera por la izquierda y entran en el orden en que salen por la derecha.
CF est puesta al ultimo valor que sali, en este caso 1.
Est instruccin es til cuando quieres cambiar el orden de los bits sin perderlos.
La RCR y RCL son similares a ROR y ROL. La nica diferencia es que CF es considerada como un bit
extra que participa completamente en la rotacin.
67

Con RCR, puedes pensar que CF es un bit extra que est pegado a la derecha del byte o palabra. Con
RCL, CF est pegada a la izquierda del byte o palabra.
Por ejemplo, digamos que AL contiene 00111100B y CF contiene 1, la instruccin:
RCR

AL,1

Considera AL y CF para formar una entidad de 9 bits. La rotacin tiene el siguiente efecto:

Los bits dems a la derecha de AL son movidos junto con CF; al mismo tiempo, CF es movida al bit de
mas a la izquierda de AL para llenar el espacio.
Aqu hay un ejemplo que usa RCL. Digamos que CF contiene un 0 y AL contiene 00111100B, la
instruccin
RCL

AL,3

Considere CF y AL para formar una sola entidad de 9 bits de longitud. La rotacin tiene el efecto:

La figura 16-3 ilustra las diferentes variedades de instrucciones de movimiento y rotacin


Figura 16-3 Resumen de las instrucciones de movimiento y rotacin

68

CAPITULO 17

COMO PROVEE SERVICIOS DOS: INTERRUPCIONES

Muchos de los eventos de la computadora son impredecibles, por ejemplo la presin de una de las
teclas del teclado, el procesador necesita estar al cuidado de responder a ciertos eventos y manejarlos
apropiadamente. El sistema por el cual el procesador maneja eventos impredecibles es uno de los tpicos
discutidos en este captulo. El segundo tpico es como este sistema pude ser extendido para propsitos
diferentes.
Nuevos Trminos
Interrupcin. Una sea de que un evento necesita atencin inmediata.
Servicio. El manejo de una interrupcin.
Manejador de interrupcin. Un procedimiento que se ejecuta cuando una interrupcin ocurre.
Vector de interrupciones. Un nmero que identifica una interrupcin especifica.
Tabla descriptiva de interrupciones. Una tabla con direcciones completas, donde cada una apunta a un
manejador de interrupcin.
Interrupcin de Hardware. Un interrupcin generada desde un dispositivo de hardware. Tambin
llamada interrupcin externa.
Interrupcin de Software. Una interrupcin que se origina desde un programa en ejecucin. Tambin
llamada interrupcin interna.
BIOS (Basic Input/Output System). Una serie de programas complejos, almacenados en la memoria
ROM, que provee servicios esenciales de bajo nivel.
Dispositivo Driver. Una interfase estndar a un dispositivo hardware.
Llamada a una funcin. Un servicio ofrecido por DOS bajo los auspicios de la interrupcin 21H.
Numero de llamada. Un numero que identifica una llamada a una funcin especifica.
Prefijo de Segmento de programa (PSP). Un arrea de memoria de 256 bytes que contiene un conjunto
de informacin usada por dos para ejecutar un programa.

69

Programa residente en memoria. Un programa que permanece en la memoria permanentemente


mientras la computadora esta encendida.
Interrupcin no enmascarable (NMI). Una interrupcin tan importante que no puede ser ignorada bajo
ninguna circunstancia.

17.1 Interrupciones.
El procesador debe tener la capacidad de ver algunos eventos, muchos de los cuales ocurren en
tiempos impredecibles. Muchos de estos eventos se originan en el hardware, Veamos algunos de ellos.
La seal del teclado por la presin en alguna tecla..
La impresora que no tiene papel.
Una seal de un dispositivo de disco que ha terminado de transferir datos.
Un chip de memoria defectuoso es detectado.
Ocasionalmente un evento impredecible puede ocurrir en el software
Un programa ha tratado de dividir por cero.
Generalmente hablando, hay dos maneras de manejar una interrupcin. La primera es ignorar los eventos
externos que ocurren haciendo pausas a intervalos regulares para ver si algo necesita atencin. La
segunda es manejar los eventos tal como ocurren. Sin embargo con este mtodo debes marcar lo que
estabas haciendo para procesar el evento y despus regresar a donde estabas.
El procesador fue diseado usando el segundo sistema. La computadora siempre est preparada para
reconocer una seal que indique que un evento ha ocurrido y requiere atencin inmediata. Tal seal es
llamada una interrupcin. Cuando la interrupcin ocurre, el procesador aparta al programa actual, maneja
la interrupcin, y entonces regresa al programa en donde se quedo. Nosotros decimos que el procesador
sirve la interrupcin.
17.2 Como son servidas las interrupciones.
Despus de detectar una interrupcin, el procesador ejecuta un procedimiento especial llamado una
manejador de interrupcin. Cada tipo de interrupcin requiere su propio manejador de interrupcin. El
propsito de que el manejador atienda a la interrupcin de manera adecuada. Una vez que termina, el
procesador continua con el programa n progreso.
Desde el punto de vista del procesador, iniciar un manejador de interrupcin es muy parecido a iniciar la
llamada a un procedimiento. La diferencia principal es que antes de saltar al principio del manejador, el
procesador debe salvar la suficiente informacin para reiniciar el programa actual. En particular, el
procesador debe salvar las banderas y la direccin completa de la siguiente instruccin en el programa
actual.
Aqu estn los pasos que el procesador sigue cuando tiene que tratar con una interrupcin:
1. Termina la instruccin que este ejecutando actualmente.
2. Empuja las banderas a la pila.
3. Empuja el segmento de direccin de la siguiente instruccin en la pila.
70

4. Empuja el offset de la siguiente instruccin a la pila.


5. Determina la direccin del manejador de interrupcin apropiada.
6. Llama al manejador de interrupcin.
Cuando la interrupcin termina, el procesador restaura la banderas e reinicia el programa que fue
interrumpido.

17.3 La tabla descriptiva de interrupciones.


Cada interrupcin es servida por su propio manejador de interrupcin. Cuando la interrupcin
ocurre, el procesador debe identificar el tipo de interrupcin y determina la direccin del manejador
apropiado.
El sistema est diseado para que cada interrupcin diferente este definida por un numero llamado el
vector de interrupciones.
DOS mantiene una tabla de direcciones completas, cada una apuntando a un manejador diferente. Est
tabla es llamada tabla descriptiva de interrupciones. La tabla descriptiva es almacenada en las locaciones
de memoria mas bajas de 0000H a 03FFH (1024 bytes). Cada vector requiere 4 bytes para su
identificacin (direccin de segmento y offset), la tabla puede mantener hasta 256 direcciones completas.
Esto significa que DOS puede proveer hasta 256 interrupciones diferentes, pero algunas de estas no tiene
uso.
Las 256 posibles interrupciones estn numeradas desde 0H a FFH. Las direcciones para las interrupciones
son almacenadas en el mismo orden en la tabla descriptiva. As la direccin completa para el manejador
de interrupcin 0 esta almacenada en los cuatro bytes empezando en la locacin 0000H. La direccin del
manejador 1 est e la locacin 0004H. La direccin del 2 esta en la locacin 0008H. En general, la
direccin de la n interrupcin esta en la locacin 4 x n.
As cuando una interrupcin ocurre el procesador calcula el numero de servicio por 4 para obtener la
direccin del manejador para esa interrupcin, por ejemplo para la interrupcin 20H, el procesador
ejecuta el manejador cuya direccin est en la locacin 0080H.
La tabla es ajustada automticamente cuando inicia DOS, sin embargo en principio, estas direcciones
pueden ser cambiadas por manejadores de interrupcin nuevos o modificaciones a interrupciones que ya
tengan uso.

17.4 Las interrupciones que son usadas por el programador: INT.


Las interrupciones tiene dos propsitos: Primero, permiten que la computadora responda
inmediatamente a eventos que pasan inpredeciblemente. Segundo, es posible que un programa mande una
seal de interrupcin. Sin embargo como es posible que un programa llame a tal procedimiento? La
respuesta est en el sistema operativo (DOS) y el software interconstruido (el BIOS) que ofrecen muchos
servicios a los programas. En orden de tomar ventaja de estos servicios, un programa debe ser capaz de
llamar al procedimiento adecuado. Sin embargo no hay un modo fcil par que el programa sepa las
locaciones de estos procedimientos.
71

La solucin es asignar a cada servicio un numero que corresponda a un vector de interrupcin. Un


programa puede requerir un servicio que corresponda al vector de interrupcin. De hecho la instruccin
INT tiene este propsito, este es su formato:
INT

vector-interrupcin

Por ejemplo, un programa puede sealar a la interrupcin 21H ejecutando lo siguiente:


INT

21H

Las interrupciones tiene dos propsitos:


*
Permiten al procesador atender las necesidades del hardware
*
Permiten a un programa requerir servicios del sistema operativo y del software interconstruido.
Una interrupcin que se origina por una seal de hardware es conocida como interrupcin externa, por el
contrario una interrupcin generada por el software es llamada interrupcin interna.

17.5 El BIOS.
El BIOS provee tres funciones importantes:
Primera, el BIOS contiene la prueba para encendido (POST), la cual se ejecuta automticamente cada vez
que enciendes la computadora. El POST checa varias partes de la computadora incluyendo la memoria,
para encontrar problemas de hardware antes de usar la mquina.
Segundo, el BIOS contiene programas especiales, llamados dispositivos manejadores (device drivers),
que proveen un conjunto de interfaces estndar para los dispositivos hardware. Un device driver opera al
nivel del hardware, mandando y recibiendo seales byte por byte. Sin dispositivos manejadores tendras
muchos problemas para usar una parte de hardware. En general los drivers protegen a los programadores
de tener que comprender las caractersticas de los varios dispositivos hardware.
Adems de los drivers interconstruidos, DOS tambin permite instalar manejadores de dispositivos
cuando enciendes la mquina. Esto permite mejorar e innovar el manejo del hardware. Los dispositivos
drivers se especifican usando el comando DEVICE en el archivo CONFIG:SYS.
Tercero, algunos de los servicios del BIOS pueden ser utilizados por los programas, con la requisicin de
interrupciones. Sin embargo, hay un par de excepciones que no pueden ser usadas directamente, y que
son usadas solo por el sistema operativo.
17.6 El sistema operativo: DOS.
El programador puede considerar al sistema operativo como un proveedor de servicios. Para requerir
un servicio (con DOS) puedes usar la instruccin INT para marcar la seal de un interrupcin. DOS est
diseado para ejecutar muchas de las tareas ms complejas e importantes que tus programas requieren. Lo
bueno de tener las tareas del DOS es que programador puede despreocuparse de como ejecutar esas
tareas. Por ejemplo para leer un archivo se necesitan cientos de instrucciones de lenguaje de bajo nivel.
Con el Dos y el BIOS podemos hacer casi todo automticamente.

72

17.7 Las llamadas de funcin DOS.


DOS provee mas de 130 servicios tiles en los programas. Cada servicio tiene su propio vector de
interrupcin (nmeros). Los servicios de DOS ofrece bajo el auspicio de la interrupcin 21H es llamada
llamada a funcin.
Cada llamada a funcin est identificada por un numero llamado numero de llamada. Para usar esta
funcin, ponemos en el registro AH el numero de llamada, y entonces sealamos la interrupcin 21H. Por
ejemplo la siguiente llamada a funcin 19H determina la unidad actual de disco por default. Las
siguientes instrucciones ejecutan la llamada a funcin:
; determina la unidad actual por omisin
MOV
AH,19H
INT
21H
Ya que todas las llamadas a funcin son ejecutadas por la misma interrupcin, esto provee un modo
estandarizado para ofrecer servicios para programar.
Los siguientes dos resmenes contienen las llamadas de funcin de DOS en categoras, ordenadas por el
numero de llamada. Estas listas estn actualizadas hasta la versin 6.2.
Resumen de llamadas a funciones de DOS por categoras.
Input/Output para archivos
2EH
3CH
3DH
3EH
3FH
40H
42H
45H
46H
54H
5AH
5BH
67H
68H
6CH
4402H
4403H
4404H
4405H
4406H
4407H

Modificar los campos del switch de verificacin


Abrir un archivo para salida
Abrir un archivo existente
Cerrar un archivo
Leer de un archivo o dispositivo
Escribir a un archivo o dispositivo
Mover un apuntador Lectura/Escritura
Crear un manejador de archivo duplicado
Hacer un manejador de archivo existente igual a otro
Obtener los campos del switch de verificacin
Crear un archivo con un nombre nico
Crear un archivo nuevo
Ajustar el numero mximo de manejadores de archivos
Desalojar los buffers de archivos a disco
Crear, abrir o remplazar un archivo (combinaciones de 3CH, 3DH, 5BH)
Leer de un dispositivo de carcter
Escribir a un dispositivo de carcter
Leer de un dispositivo de carcter
Escribir a un dispositivo de carcter
Determinar si un dispositivo est listo para entrada
Determinar si un dispositivo est listo para salida

Entrada/Salida de caracteres
01H

Leer de la entrada estndar (teclado): sin esperar, con eco


73

02H
Escribir a la salida estndar (pantalla)
03H
Leer del dispositivo auxiliar estndar; esperar
04H
Escribir al dispositivo auxiliar estndar
05H
Escribir al dispositivo estndar de impresin
06H
Leer de la entrada estndar (teclado), esperar, con eco
07H
Leer de la entrada estndar (teclado), esperar, sin eco
08H
Leer de la entrada estndar (teclado), esperar, con eco, ?break
09H
Escribir un string a la impresora estndar
0AH
Leer de la entrada estndar (teclado)
0BH
Checar si la entrada estndar (teclado) tiene carcter disponible
0CH
Teclado: limpiar el buffer y entonces invocar la llamada a funcin
Entrada/Salida de archivos del viejo DOS 2.00 (No use nunca las llamadas a funcin I/O)
0DH
0FH
10H
11H
12H
13H
14H
15H
16H
17H
1AH
21H
22H
23H
24H
27H
28H
29H
2FH

Desalojar todos los buffers de archivos


Abrir un archivo
Cerrar un archivo
Encontrar el primer nombre de archivo igual a la especificacin
Encontrar el siguiente nombre de archivo igual a la especificacin
Borrar un archivo
Lectura secuencial de un archivo
Escritura secuencial de un archivo
Crear un archivo
Renombrar un archivo
Ajustar la direccin de transferencia a disco
Lectura aleatoria de un archivo
Escritura aleatoria de un archivo
Obtener el tamao de un archivo en registros
ajustar aleatoriamente el campo de un registro
Lectura aleatoria de un bloque de un archivo
Escritura aleatoria de un bloque de un archivo
Parsear un nombre de archivo
Obtener la direccin de transferencia de disco

Manejo de archivos
43H
4EH
4FH
56H
57H

Cambiar el modo de un archivo (Atributos)


Encontrar el primer nombre de archivo igual a la especificacin
Encontrar el siguiente nombre de archivo igual a la especificacin
Renombrar o mover un archivo
Obtener o modificar la fecha o la hora

Manejo de directorios
39H
3AH
3BH
41H
47H

Crear un subdirectorio
Remover un subdirectorio
Ajustar al directorio actual
Borrar un archivo de un directorio
Obtener el nombre del directorio actual

74

Manejo de dispositivos
0EH
19H
1BH
1CH
1FH
32H
3305H
36H
4400H
4401H
4408H
440CH
440DH
440EH
440FH
4410H
4411H

Seleccionar la unidad de disco por omisin


Determinar la unidad de disco por default
Obtener la direccin de la locacin de la tabla acerca de la unidad de default
Obtener la direccin de la locacin de la tabla acerca de dispositivo especificado
Obtener el bloque de parametro de unidad para la unidad de default
Obtener el bloque de parametro de la unidad (viejo: use 1FH o 36H)
Obtener el cdigo del boot de la unidad
Obtener la informacin del espacio del disco
Obtener la informacin del dispositivo
Ajustar la informacin del dispositivo
Determinar si el bloque de dispositivo soporta medios removibles
Permitir que el driver de dispositivo soporte el intercambio de paginas de cdigo
IOCTL uniforme para soportar dispositivos de bloque
Determinar si le bloque de dispositivo tiene unidades lgicas de letras mayores que 1
Asignar una letra de unidad lgica a un bloque de dispositivo
Determinar si un dispositivo soporta servicios IOCTL
Determinar si una unidad soporta servicios IOCTL

Manejo de programas
00H
25H
26H
30H
31H
3300H
3301H
3306H
34H
35H
48H
49H
4AH
4B00H
4B03H
4B05H
4CH
4DH
50H
51H
5D0AH
5800H
5801H
5802H
5803H
59H
62H

Terminar un programa: sin cdigo de retorno (viejo: usa 31H o 4CH)


Modificar la entrada de la tabla descriptora de interrupciones
Crear un nuevo segmento de programa (viejo: usa 4BH)
Obtener la versin del DOS
Terminar un proceso y dejarlo residente: ajustar el cdigo de retorno
Obtener la bandera Ctrl-Break
Ajustar la bandera Ctrl-Break
Obtener la versin del DOS (ms sofisticado que 30H)
Obtener la bandera InDOS
Obtener la entrada de la tabla descriptora de interrupciones
Colocar memoria
Liberar memoria colocada
Modificar memoria colocada
Cargar y ejecutar un programa
Cargar y superponer
Preparar a DOS para transferir control a un nuevo programa
Terminar un proceso: ajustar el cdigo de regreso
Obtener el cdigo de retorno de otro proceso
Definir la direccin de un nuevo prefijo de segmento de programa (PSP)
Obtener la direccin del prefijo de segmento de programa (PSP) actual
Ajustar la informacin de error extendida
Determinar que estrategia que colocacin de memoria esta usando DOS
Ajustar la estrategia de colocacin de memoria que DOS puede usar
Determina si el rea de memoria alta (HMA) esta disponible
Decirle a DOS que el rea de memoria (HMA) alta est disponible
Obtener informacin de error extendida
Obtener la direccin del segmento de prefijo de programa (PSP)

75

Redes
4409H
440AH
440BH
5CH
5E00H
5E02H
5E03H
5F02H
5F03H
5F04H

Determina si un dispositivo lgico es local o remoto


Determinar si el manejador de archivo es local o remoto
Especifica el numero de intento a acceso a archivo y el retraso del reintento
Bloque o desbloquea parte de un archivo
Obtener el nombre de la mquina
Especificar la actualizacin de la impresora
Obtener la actualizacin de la impresora
Obtener los asignamientos de redes no locales
Hacer la conexin redirector/servidor
Cancelar la redireccin previa

Fecha y hora
2AH
2BH
2CH
2DH

Obtener la fecha
Ajustar la fecha
Obtener la hora
Ajustar la hora

Servicios especficos del pas


38H
66H
6501H
6502H
6504H
6505H
6506H
6507H
6520H
6521H
6522H

Obtener o ajustar la informacin dependiente del pas


Obtener o ajustar el cdigo de pagina global para la seleccin del pas actual
Obtener informacin extendida del pas
Obtener la direccin para la tabla de mapa: caracteres mayores de ASCII 127
Obtener la direccin para la tabla de mapa: nombre del archivo de caracteres > ASCII 127
Obtener la direccin para la tabla de caracteres invlidos: nombres de archivos
Obtener la direccin para la tabla en secuencia ordenada
Obtener la direccin del ajuste de tabla para caracteres de doble byte
Convertir un carcter simple usando tabla mapa
Convertir cadena de caracteres usando la tabla mapa
Convertir una cadena de caracteres ASCIIZ usando la tabla mapa

Resumen de llamada de funciones por orden de numero de llamada de funcin


00H
01H
02H
03H
04H
05H
06H
07H
08H
09H
0AH
0BH
0CH

Terminar un programa: sin cdigo de retorno (viejo: usa 31H o 4CH)


Leer de la entrada estndar (teclado): sin esperar, con eco
Escribir a la salida estndar (pantalla)
Leer del dispositivo auxiliar estndar; esperar
Escribir al dispositivo auxiliar estndar
Escribir al dispositivo estndar de impresin
Leer de la entrada estndar (teclado), esperar, con eco
Leer de la entrada estndar (teclado), esperar, sin eco
Leer de la entrada estndar (teclado), esperar, con eco, ?break
Escribir un string a la impresora estndar
Leer de la entrada estndar (teclado)
Checar si la entrada estndar (teclado) tiene carcter disponible
Teclado: limpiar el buffer y entonces invocar la llamada a funcin
76

0DH
0FH
10H
11H
12H
13H
14H
15H
16H
17H
19H
1AH
1BH
1CH
1FH

Desalojar todos los buffers de archivos


Abrir un archivo
Cerrar un archivo
Encontrar el primer nombre de archivo igual a la especificacin
Encontrar el siguiente nombre de archivo igual a la especificacin
Borrar un archivo
Lectura secuencial de un archivo
Escritura secuencial de un archivo
Crear un archivo
Renombrar un archivo
Determinar la unidad de disco por omisin
Ajustar la direccin de transferencia a disco
Obtener la informacin de la tabla de colocacin acerca del la unidad por default
Obtener la informacin de la tabla de colocacin acerca del la unidad especificada
Obtener el bloque de parmetros para la unidad por default

21H
22H
23H
24H
25H
26H
27H
28H
29H
2AH
2BH
2CH
2DH
2EH
2FH

Lectura aleatoria de un archivo


Escritura aleatoria de un archivo
Obtener el tamao de un archivo en registros
ajustar aleatoriamente el campo de un registro
Modificar la entrada en la tabla descriptora de interrupciones
Crear un nuevo segmento de programa (viejo: usa 4BH)
Lectura aleatoria de un bloque de un archivo
Escritura aleatoria de un bloque de un archivo
Parsear un nombre de archivo
Obtener la fecha
Ajustar la fecha
Obtener la hora
Ajustar la hora
Modificar campos del switch de verificacin
Obtener la direccin de transferencia de disco

30H
31H
32H
3300H
3301H
3306H
34H
35H
36H
38H
39H
3AH
3BH
3CH
3DH
3EH
3FH
40H
41H
42H

Obtener la versin del DOS


Terminar un proceso y dejarlo residente: ajustar el cdigo de retorno
Obtener el bloque de parmetros de la unidad
Obtener la bandera Ctrl-Break
Ajustar la bandera Ctrl-Break
Obtener la versin del DOS (ms sofisticado que 30H)
Obtener la bandera InDOS
Obtener la entrada de la tabla descriptora de interrupciones
Obtener informacin del espacio en disco
Obtener o poner la informacin dependiente del pas
Crear un subdirectorio
Remover un subdirectorio
Poner el directorio actual
Abrir un archivo para salida
Abrir un archivo existente
Cerrar un archivo
Leer de un archivo o dispositivo
Escribir a un archivo o dispositivo
Borrar un archivo de un subdirectorio
Mover un apuntador Lectura/Escritura
77

43H
4400H
4401H
4402H
4403H
4405H
4406H
4407H
4408H
4409H
440AH
440BH
440CH
440DH
440EH
440FH
4410H
4411H
45H
46H
47H
48H
49H
4AH
4B00H
4B03H
4B05H
4CH
4DH
4EH
4FH

Cambiar el modo de un archivo (atributos)


Obtener la informacin de un dispositivo
Ajustar la informacin de un dispositivo
Leer de un dispositivo de caracteres
Leer de un dispositivo de caracteres
Escribir a un dispositivo de caracteres
Determinar si un dispositivo est listo para entrada
Determinar si un dispositivo est listo para salida
Determinar si el bloque de dispositivo soporta medios removibles
Determina si un dispositivo lgico es local o remoto
Determinar si el manejador de archivo es local o remoto
Especifica el numero de intento a acceso a archivo y el retraso del reintento
Permitir que el driver de dispositivo soporte el intercambio de paginas de cdigo
IOCTL uniforme para soportar dispositivos de bloque
Determinar si le bloque de dispositivo tiene unidades lgicas de letras mayores que 1
Asignar una letra de unidad lgica a un bloque de dispositivo
Determinar si un dispositivo soporta servicios IOCTL
Determinar si una unidad soporta servicios IOCTL
Crear un manejador de archivo duplicado
Hacer un manejador de archivo existente igual a otro
Obtener el nombre del directorio actual
Colocar memoria
Liberar memoria colocada
Modificar memoria colocada
Cargar y ejecutar un programa
Cargar y sobreponer
Preparar a DOS para transferir el control a un nuevo programa
Terminar un proceso: ajustar el cdigo de retorno
Obtener el cdigo de retorno de otro proceso
Encontrar el primer nombre de archivo igual a la especificacin
Encontrar el siguiente nombre de archivo igual a la especificacin

50H
51H
54H
56H
5800H
5801H
5802H
5803H
59H
5AH
5BH
5CH
5D0AH
5E00H
5E02H
5E03H
5F02H
5F03H
5F04H

Definir la direccin de un nuevo prefijo de segmento de programa (PSP)


Obtener la direccin del prefijo de segmento de programa (PSP) actual
Obtener los campos del switch de verificacin
Renombrar o mover un archivo
Determinar que estrategia que colocacin de memoria esta usando DOS
Ajustar la estrategia de colocacin de memoria que DOS puede usar
Determina si el rea de memoria alta (HMA) esta disponible
Decirle a DOS que el rea de memoria (HMA) alta est disponible
Obtener informacin de error extendida
Crear un archivo con un nombre nico
Crear un archivo nuevo
Bloque o desbloquea parte de un archivo
Ajustar la informacin de error extendida
Obtener el nombre de la mquina
Especificar la actualizacin de la impresora
Obtener la actualizacin de la impresora
Obtener los asignamientos de redes no locales
Hacer la conexin redirector/servidor
Cancelar la redireccin previa
78

62H
6501H
6502H
6504H
6505H
6506H
6507H
6520H
6521H
6522H
66H
67H
68H
6CH

Obtener la direccin del segmento de prefijo de programa (PSP)


Obtener informacin extendida del pas
Obtener la direccin para la tabla de mapa: caracteres mayores de ASCII 127
Obtener la direccin para la tabla de mapa: nombre del archivo de caracteres > ASCII 127
Obtener la direccin para la tabla de caracteres invlidos: nombres de archivos
Obtener la direccin para la tabla en secuencia ordenada
Obtener la direccin del ajuste de tabla para caracteres de doble byte
Convertir un carcter simple usando tabla mapa
Convertir cadena de caracteres usando la tabla mapa
Convertir una cadena de caracteres ASCIIZ usando la tabla mapa
Obtener o ajustar el cdigo de pagina global para la seleccin del pas actual
Ajustar el numero mximo de manejadores de archivos
Desalojar los buffers de archivos a disco
Crear, abrir o remplazar un archivo (combinaciones de 3CH, 3DH, 5BH)

17.8 Guas para usar las llamadas a funcin de DOS.


Muchas llamadas a funciones requieren entrada y generan salida. Sin embargo las llamadas de
funcin no accesan al rea de datos del programa, toda la informacin debe ser pasada y regresada a
travs de los registros.
Antes de una llamada a funcin, tenemos que saber exactamente que valores necesitan ser puestos en los
registros y que contendrn cuando la llamada a funcin regrese. Para la entrada, la llamada a funcin
requiere que el numero de la funcin este en AH. Como regla general, DL es usado para mantener un
valor de entrada, y DX es usado para mantener el offset de un string de entrada en el segmento de datos.
Para salida, los valores son regresados en AX, AL o DL. Sin embargo hay excepciones a estas reglas.
Una caracterstica especial es que la llamada de funcin regresa un 0 en CF si todo paso
satisfactoriamente, si un error ocurre CF es puesta a 1. As podemos usar un salto condicional (JC o JNC)
despus de la interrupcin para cerciorarnos de que todo sali bien. La interrupcin 21H como todo
procedimiento bien construido no cambia los valores de los registros o de las banderas excepto los
registros que son utilizados para regresar resultados de salida.
Una vez que DOS toma el control, este usa su propia pila interna. Sin embargo, el mecanismo de
interrupcin usa la misma pila que el programa que llama. En orden de asegurarte de que la pila sea
suficientemente grande, deja un espacio de 200 H extra aparte de las necesidades de tu programa.

17.9 Ejemplos de llamadas a funcin DOS.


El primer ejemplo usa la llamada a funcin 30H para obtener el nmero de versin de DOS. Para
preparar esta funcin, ajusta AH al numero de llamada 30H. La salida esta en dos partes: El numero
mayor de la versin esta en el registro AL, y el menor en AH. Por ejemplo si la versin del sistema
operativo es DOS 5.0, AL contiene un % y AH contiene un 0.
; obtener el numero de versin
; AL <--- numero mayor de la versin
; AH <--- numero menor de la versin
MOV
AH,30H
79

INT

21H

El segundo y tercer ejemplo usa la llamadas a 2AH y 2BH para obtener y ajustar la fecha. Para obtener la
fecha, usa la llamada a funcin 2AH. Primero ajusta AH al numero de llamada 2AH. Esta es la salida:
AL <--- Dia de la semana (0 para Domingo, 1 para Lunes...)
CX <--- Ao (de 1980 al 2099)
DH <--- Mes (1 para Enero, 2 para Febrero...)
DL <--- Dia (1 al 31)
Por ejemplo, digamos que es Lunes, 21 de Diciembre de 1992, puedes ejecutar la siguiente instruccin:
; obtener la fecha
MOV
INT

AH,2AH
21H

Como salida, DOS ajusta los registros de la siguiente manera:


AL = 1;

CX= 1992 (07C8H);

DH = 12; DL = 21

Para ajustar la fecha, usamos la funcin 2BH. Como entrada, colocamos el ao, mes y da en CX, DH y
DL.
Por ejemplo para poner la fecha Diciembre 21 de 1992 usamos las instrucciones
; ajustar la fecha a Diciembre 21 de 1992
MOV
CX,1992
MOV
DH,12
MOV
DL,21
MOV
AH,28H
INT
21H
Aqu hay un ejemplo que usa estas dos funciones para calcular el da de la semana de una fecha
especifica. La idea es que si ajustas la fecha a una fecha especifica, puedas hacer que DOS calcule el da
de la semana para ti. La lgica es como sigue:
Salvar la fecha actual
Usar la funcin 2AH para ajustar a una fecha especifica
Usar la funcin 2BH para obtener la fecha
Salvar el da de la semana
Restaurar la fecha actual
En este ejemplo, la fecha la fecha de la cual queremos el da de la semana est almacenada en tres campos
dato YEAR, MONTH y DAY. Una vez que el da es calculado este es copiado al campo dato
WEEKDAY. Estos datos estn declarados en el segmento de datos. Si la fecha especificada fuera
Diciembre 21 del 2002 estas seran las declaraciones:
YEAR
DW
MONTH DB
12
DAY
DB
WEEKDAY DB

2002
21
?

Aqu estn las instrucciones que calculan el da de la semana:


80

; calcular el da de la semana de una fecha especifica


; WEEKDAY <--- resultado (0-6)
; salvar la direccin actual
MOV
AH,2AH
INT
21H
PUSHA
; -- ajustar a la fecha especifica
MOV
CX,YEAR
MOV
DH,MONTH
MOV
DL,DAY
MOV
AH,2BH
INT
21H
; obtener el dato especifico
MOV
AH,2AH
INT
21H
; copiar el da al campo WEEKDAY
MOV
WEEKDAY,AL
; restaurar la fecha anterior
POPA
MOV
AH,2BH
INT
21H
El resultado es que WEEKDAY tiene un valor de 6 que significa que el da 21 de Diciembre del 2002 es
sbado.

17.10 Manejo de Errores.


Muchas llamadas a funciones indican un error poniendo la bandera de acarreo a 1. En tales casos,
necesitas encontrar la naturaleza del error. La llamada a funcin 59H provee este servicio.
La llamada de funcin 59H requiere los siguientes parmetros de entrada:
AH <--- numero de llamada (59H)
AL <--- 0
Despus usa la llamada a funcin que seala un error, el programa puede probar a CF. Si CF ests puesta
a 1, el programa puede ejecutar la llamada 59H para obtener ms informacin. Algunas de las llamadas a
funcin regresan el cdigo de error en AX y CF. Sin embargo, estos son cdigos de error viejos, es ms
seguro usar los resultados de la funcin 59H.
Aqu est un ejemplo que usa la funcin 40H para escribir en un archivo.. El salvar y restaurar el registro
DS en el segundo conjuntos de instrucciones ser explicada mas adelante.
; escribir al archivo
MOV
BX,FILE_HANDLE
LEA
DX,BUFFER
MOV
CX,COUNT
MOV
AH,40H
INT
21H
81

; Si hay un error , obtener la informacin del error y entonces llamar


; al procedimiento de error
JNC
L1
PUSH
DS
MOV
BX,0
MOV
AH,59H
INT
21H
POP
DS
CALL
ERROR
L1:
La llamada de funcin 59H regresa los siguientes parmetros de salida:
AX
BH
BL
CH

<--<--<--<---

El cdigo de error
La clase de error
La accin recomendada
El lugar

El lugar se refiere a la parte de la computadora donde ocurri el error.


Adems de los parmetros de salida, debes tener cuidado con esta funcin ya que no salva los valores de
los registros CL, DX, SI, DI, DS y ES. As antes de hacer la llamada a esa funcin, debes salvar a DS y a
otros registros importantes

17.11 Ejemplo del uso de Interrupciones.


En algunas ocasiones puedes invocar a las interrupciones directamente. En est seccin te mostrare
tres ejemplos de interrupciones interesantes todas del BIOS. Las interrupciones de esta seccin son
simples en el sentido de que no necesitan entrada o salida. Sin embargo, muchas de las interrupciones del
DOS y de BIOS necesitan parmetros.
La primer interrupcin interesante es la 05H. Esta interrupcin copia el contenido de la pantalla a la
impresora, cuando presionas el Imptr Pant. Puedes usar esta interrupcin para imprimir la pantalla dentro
de un programa. Antes de hacer esto asegrate que la impresora est lista. La salida est direccionada al
puerto LPT1.
; imprimir la pantalla
INT
05H
La segunda interrupcin es la 18H. La interrupcin detiene a DOS y ejecuta la versin rudimentaria de
BASIC que est almacenada en el ROM. (este es el casete bsico que inicia si enciendes la computadora
y el BIOS no puede encontrar la forma de arrancar el DOS).
Este servicio solo puede ser una curiosidad interesante; sin embargo puedes usar la imaginacin para
encontrar un uso para esto. Asegrate de hacer dos cosas: primero, si usas esta versin de BASIC, no
podrs salvar los programas a disco. Segundo, el nico modo de regresar a DOS es reiniciar la
computadora.
; cambiar al casete BASIC
82

INT

18H

La tercera interrupcin es la 19H. Esta interrupcin reinicia la computadora. Esta es til si quieres
reiniciar la mquina desde un programa. Este reinicio es abreviada y omite los siguientes pasos:
El sistema automaticamente ejecuta un chequeo cuando inicias la mquina (un reseteo en fro)
Las operaciones de reset que son ejecutadas con Ctrl-Alt-Del (reseteo en caliente).
As la interupcin 19H puede ser considerado como un reseteo en caliente.
Esto es bueno y malo, es bueno porque el reseteo en caliente es mas rapido, debido a que no ejcuta el
chequeo y las operaciones de reseteo, sin embargo este reseteo no funciona bajo algunas circunstancias,
como por ejemplo si algunos programas residentes estan cargados en memoria.
; ejecuta un reseteo en caliente
INT
19H

17.12 Terminar un programa.


Cuando un programa termina, regresa al DOS ejecutando la instruccin RET, la cual saca la
direccin de regreso de la pila, y salta a esa direccin. Ya que todos los programas son de tipo FAR, la
direccin de regreso debe consistir de la direccin del segmento y el offset.
La direccin de regreso debe ser empujada a la pila al principio del programa. Este trabajo es manejado
por las siguientes instrucciones:
; salvar la direccin del DOS
PUSH
DS
PUSH
0
El primer PUSH almacena la direccin del segmento; el segundo PUSH almacana el desplazamiento.
Cada vez que el programa se ejecuta, DOS coloca un rea de 256 bytes llamado el prefijo del segmento
del programa (PSP). El PSP es cargado en memoria y alineado al limite de un parrafo (16 bytes) en el
frente de tu programa, de ah el termino prefijo.
El PSP contiene una combinacin de informacin que DOS usa para ejecutar el programa. A menos que
necesites accesar los parametros de la linea de comandos o el ambiente de Dos puedes ignorar el PSP.
Despues de que el programa es cargado en memoria, DOS pone los registros DS y ES a la direccin del
prefijo de segmento. Esto significa que cada programa inicia con DS y ES apuntando al PSP. Las
primeras dos instrucciones del programa meten el valor de DS y 0 en la pila antes de modificar a DS. Esto
significa que el RET final regresa al inicio del PSP. El inicio del PSP contiene una instruccin de dos
bytes:
INT

20H

La interrupcin 20H ejecuta las tareas necesarias para terminar el programa y le da el control de nuevio a
DOS.
83

As, colocandose en el inicio del PSP que contiene la interrupcin 20H, DOS permite terminar el
programa con un simple RET. Este metodo de terminacin fue diseado para ser simple, y muchas de las
veces es suficiente. Sin embargo, hay dos situaciones no usuales en las cuales podemos terminar el
programa de manera diferente. Primero, podemos mandar un codigo de retorno al programa que llamo,
usando la llamada a funcin 4CH. Segundo puedes dejar un programa en memoria despues de que
termine. En este caso, usamos la llamada a funcin 31H.

17.13 Disear tu propio manejador de Interrupcin: IRET.


Usualmente, una interrupcin es servida por un manejador de interrupcin que es parte del DOS o
del BIOS. Sin embargo, puedes modificar la tabla descriptiva de interrupcin para que apunte a tu propio
manejador de interrupcin. Esto da un mayor control sobre la interrupcin a ser servida.
Normalmente, no se debe hacer esto; de hecho muchos manejadores de interrupciones tratan con tareas
complejas y raramente necesitas cambiarlas. Sin embargo, puedes querer escribir tu propia rutina de
manejador, esta seccin y la siguiente explican esta tecnica.
Basicamene, un manejador de interrupcin actua como un procedimiento de tipo FAR, cuando la
interrupcin es sealada, el procesador detiene el programa actual, salva las banderas y la direccin de la
siguiente instruccin en su propia pila, e invoca al manejador de interrupcin.
Un manejador de interrupcin actua como un procedimiento FAR. Sin embargo un manejador de
interrupcion usando la instruccin IRET (regreso de interrupcin) en lugar de la RET. Como sabes, la
instruccin RET regresa la direccin de retorno que fue enpujada a la pila por la instruccin CALL. La
instruccin IRET restaura tambien el registro de banderas que fue empujado a la pila adelante de la
direccin de regreso. As, las funciones de la IRET son las siguientes:
Sacar la direccin de regreso (offset y direccin de segmento) fuera de la pila
Saca y restaura el registro de banderas de la pila
Salata a la direccin de regreso.
Ademas de uasr la instruccin IRET en lugar de la RET, hay otras diferencias entre el manejador y un
procedimiento regular.
Un manejador de interrupcin
No puede ser invocada por otras interrupciones (usando INT)
Debe preservar los valores de todos los registros excepto de aquellos que usa para pasar
parametros (como en tod procedimiento)
En resumen, debes escribir un manejador de interrupcin de manera que pueda ser invocada cuando sea
causando errores o efectos laterales.
17.14 Modificar la tabla descriptiva de Interrupciones.

84

En orden de usa tu propio manwejador de interrupcin, debes reemplazar la entrada apropiada en la


tabla descriptiva de interrupciones. En principio puedes hacer esto directamente (ya que la tabla inicia en
la locacin 0000H y cada entrada es de 4 bytes de longitud). Sin embargo, esta es una idea pobre que un
programa dependa de direcciones absolutas. (Esto es debido a que la tabla esta en una locacin diferente
cuando el procesador corre en modo protegido.)
En su lugar, DOS permite hacer este remplazo por ti. La llamada a fucnin 25H provee este serviicio.
Estos son los paametros:
AL
DX
DS
AH

<--<--<--<---

numero de vector o entrada a ser examinada


offset del manejador de interrupcin
segmento de direccin del manejador de interrupcin
25H (el numero de llamada)

No hay parametros de salida.


Aqu hay un ejemplo que ilustra estas tecnicas. El ejmplo remplaza el manejador de interrupcion 5
(imprimir la pantalla) con un procedimiento que emite un beep.
Primero, aqu esta el procedimiento que emite un sonido. Los detalles sern explicados en el siguiente
capitulo. Sin embargo note que cada procedimiento salva y regresa los registros usando IRET.
; interrupcion que emite un sonido
BEEP
PROC
PUSHA
MOV
AL,0B6H
OUT
43H,AL
MOV
AX,3025
OUT
42H,AL
JMP
SHORT $+2
MOV
AL,AH
OUT
42H,AL
IN
AL,61H
MOV
AH,AL
OR
AL,03
OUT
61H,AL
MOV
CX,0FFFFH
L1:
LOOP
L1
MOV
AL,AH
OUT
61H,AL
POPA
IRET
BEEP
ENDP
Para usar este procedimiento como un manejador de interrupcin 5H, necesitas invocar la funcin 25H
con la salida de parametros descrita a continuacin.
Un punto importante es que DS debe apuntar al segmento de direccin del procedimiento. Una vez que
BEEP esta en el segmento de codigo, DS debe ponerse al valor del registro CS. Sin embargo no puedes
hacer esto directamente. Debes empujar el valor a la pila y despues sacar el valor a DS. Por supuesto,
debes salvar el valor original y restaurarlo despues de la llamada a funcin
85

Aqu estan las instrucciones:


; modifica el vector 5 para apuntar al procedimiento BEEP
; AL <-- 05H (el vector de interrupcion a ser manejado
; DX <-- offset del procedimiento BEEP
; DS <-- direccion de segmento del procedimiento BEEP
; AH <-- 25H (numero de llamada a funcin)
PUSH
DS
MOV
AL,05H
LEA
DX,BEEP
PUSH
CS
POP
DS
MOV
AH,25H
INT
21H
POP
DS
Una vez que estas instrucciones son ejecutadas, el manejador de interrupcin 5 ser el procedimiento
BEEP. Desde ahora, cada vez que ejecutes:
INT

5H

La computadora emitira un sonido en lugar de imprimir la pantalla.


Por supuesto, el nuevo manejador de interrupcion funcionara solo mientras el programa esta enejecucin.
Una vez que el programa termina, este manejador desaparece.
teiens dos opciones:
1. Si quieres que el manejador de interrupcion tiene un efecto permanente, puedes terminar el programa
de tal manera que quedde residenbte en memoria. Esto es discutido en la siguiente seccin.
2. Si quieres que el nuevo manejador tenga un efecto solo durante el programa, debes salvar y restaurar la
la entrada original en la tabla descriptora de interrupciones.
Para hacer el manejador efectivo solo durente el programa, recuerde que cada entrada contiene la
direccin de segmento y un offset. Antes de poner el nuevo manejador, salva el segmento y offset
originales en dos campos dato (ORIGINAL_OFFSET y ORIGINAL_SEGADDR). Entonces al final del
programa, restaura la entrada con sus valores originales.
Para salvar los valores originales, usa la funcin 35H. Esta funcin examina la tabla descrptiva de
interrupciones y regresa el segmento de direccin y el offset que estan almacenados en una entrada
particular. Estos son los parametros de entrada:
AL <-- numero de entrada de vector a ser examinado
AH <--- 25H el numero de llamada.
Los parametros de salida son:
BX <-- offset del manejador de interrupcin
ES <-- segmento de direccin del manejador de interrupcin
86

Aqu estan los estatutos que hacen el trabajo. Primero, en el segmento de datos, define los campos dato
que deben guardar la direccin de segmento y el offset:
ORIGINAL_OFFSET
DW ?
ORIGINAL_SEGADDR DW ?
Segundo, dentro del segmento de codigo, salva los valores originales y entonces modifica la tabla. Note
que estas instrucciones preservan los valores de Es y DS cuando es necesario.
; salva el contenido de la entrada en la tabla descriptiva de int. para la INT 5
; ORIGINAL_OFFSET <-- BX <-- offset
; ORIGIANL_SEGADDR <-- ES <-- direccin de segmento
PUSH
ES
MOV
AL,05H
MOV
AH,35H
INT
21H
MOV
ORIGINAL_OFFSET,BX
MOV
ORIGINAL_SEGADDR,ES
POP
ES
; modificar el vector INT 5 para apuntar al procedimiento BEEP
;
AL <--- 05H (vector de int a ser usada
;
DX <--- offset del procedimiento BEEP
;
DS <--- direccin de segmento del procedimiento BEEP
;
AH <--- 25H (numero de llamada a funcin)
PUSH
DS
MOV
AL,05H
LEA
DX,BEEP
PUSH
CS
POP
DS
MOV
AH,25H
INT
21H
POP
DS
Al final del programa, use la siguientes instrucciones para restaurar la entrada original en la tabla:
; modifica INT 5 para apuntar al manjeador original
;
AL <--- 05H (vector a ser restaurado)
;
DX <--- offset original
;
DS <--- direccion de segmento original
;
AH <--- 25H (numero de llamada a funcin
PUSH
DS
MOV
AL,05H
MOV
DX,ORIGINAL_OFFSET
MOV
DS,ORIGINAL_SEGADDR
MOV
AH,25H
INT
21H
POP
DS
17.15 Crear Software residente en memoria.
87

DOS provee un mecanismo para terminar un programa y dejarlo en memoria. El programa es


entonces considerado como una extensin permanente del DOS hasta que reinicias la computadora. Tal
programa es llamdo residente en memoria. El uso ms comn para los programas residentes en memoria
es tener un manejador de interrupcion permanente.
Para terminar un programa y hacerlo residente, usa la funcin de DOS 31H. Los parametros de entrada
son como sigue:
AL <--- codigo de retorno
DX <--- tamao del programa residente
AH <--- 31H (numro de llamada)
No hay parametros de salida.
El codigo de regreso es un valor que puede ser usado para pasar informacin al programa que llamo.
Usualmente el coigo de retorno es puesto a cero para indicar que no hay errores y 1 para indicar algun
error.
El valor de DX indica cuanto del programa quedara residente. Ponga a DX al desplazamiento del primer
byte despues del fin del area del residente. n otras palabras, DX debe apuntar al lugar en el cual DOS
puede cargar un programa.
La figura 17-1 muestra un programa que usa la llamada a funcion 35H. El ejemplo instala el
procedimiento BEEP como un manejador permanente a la interrupcion 5. Una vez que BEEP esta
instalado en memoria como un programa residente, puedes hacer que suene cada vez que presionas Impr
Pant. Si quieres hacer este cambio permanente, puedes ejecutar el programa de instalacin en el archivo
AUTOEXEC.BAT

17.16 Sobreflujo en artimetica: INTO.


Hay dos tipos de interrupciones que son usadas para manejar las ocndiciones de sobreflujo: las
interrupciones 0 y 4. La interrupcion 0 es invocada automaticamente cuando una operacin de division
producida por un sobreflujo. Esto puede ocurrir si el cociente es demasiado largo o el divisor es cero. La
interrupcion 0 despliega el mensaje
Divide overflow
y entonces termina el programa.
La interrucpcion 4 es usado para manejar otras condiciones aritmeticas de sobreflujo. Aqu hay una
instruccin especial, INTO para ejecutar esta interrupcion su formato es:
INTO
INTO examina la bandera de sobreflujo (OF): Si OF est puesta a 1, INTO invoca a la interrupcin 4; si
OF esta limpia a 0, INTO no hace nada. En otras palabras, INTO ejecuta la misma fucin que las
siguientes instrucciones:
; si la bandera de overflow esta puesta a 1 invocar a la interrupcion 4
JNO
L1
88

INT

L1:
Cuando reinicais la computadora, el manejador de la interrupcion 4 es una instruccin IRET. Esto la
interrupcion no hace nada. La intencion es que si es necesario, tu puedes escribir tu propio manejador de
condiciones de sobreflujo. Esto es un ejemplo de una instruccion INTO despues de un calculo aritmetico.
ADD
INTO

AX,BX

Otra alternativa es escribir un procedimiento de errror que se llama si CF esta puesta a 1, por ejemplo:
ADD
JNO
CALL

AX,BX
L1
ERROR_PROC

L1:
La ventaja de usar INTO es que provee un metodo simple para probar el sobreflujo despues de cada
calculo. La desventaja es que tu tienes que disear y programar tu propio manejador de interucion. Otra
desventaja es que INTO es util solo si trabajas con numeros con signo. Si estas usando numeros sin
signo, puedes detectar el sobreflujo con las instrucciones JC y JNC.
Figura 17-1 Programa para instalar un manejador residente.
PAGE
58,132
;------------------------------------------------------------------------------;
PONER LA INTERRUPCION 5
;
;
Proposito:
;
para instalar un manejador de int. residente en memoria
;
para la interrupcion 5
;------------------------------------------------------------------------------; ajustar el titulo y el conjunto de instruccion
TITLE
Set interrupt 5 -- poner la 5 a Beep
.286
;---------------------------------------------------------- segmento de PILA
SSEG
SEGMENT
STACK
DB 32 DUP(STACK---)
SSEG
ENDS
;------------------------------------------------------- segmento de DATOS
DSEG
SEGMENT
MESSAGE
DB Interrupcion 5 instalada y lista,0DH,0AH,$
DSEG
ENDS
;------------------------------------------------------ segmento de CODIGO
CSEG
SEGMENT
ASSUME CS:CSEG, SS:SSEG, DS:DSEG
PAGE
89

;-------------------------------------------------------------------------------;
MAIN
;
;
Proposito:
;
instalar la interrupcion 5 con el procedimiento BEEP
;
Entrada:
;
-ninguna;
Salida:
;
-un mensaje a pantalla
;
Procedimientos:
;
BEEP
;--------------------------------------------------------------------------------; procedimiento MAIN
MAIN
PROC

FAR

; salvar la direccin de regreso a DOS


PUSH
DS
PUSH
0
; actualizar el segmento de datos
MOV
AX,DSEG
MOV
DS,AX
; modificar el vector INT 5 para que apunte a BEEP
PUSH
DS
MOV
AL,05H
LEA
DX,BEEP
PUSH
CS
POP
DS
MOV
AH,25H
INT
21H
POP
DS
; despliega el mensaje para indicar que ya se modifico el vector
LEA
DX,MESSAGE
MOV
AH,09H
INT
21H
; regresa a DOS y queda residente
MOV
AL,0
LEA
DX,END_OF_PROGRAM
MOV
AH,31H
INT
27H
; fin del procedimiento MAIN
MAIN
ENDP
PAGE
;--------------------------------------------------------------------------------;
BEEP
;
90

;
Proposito:
;
un manejador de interrupcion que emite un beep
;
Entrada,salida y procedimientos:
;
-ninguno;--------------------------------------------------------------------------------; procedimiento BEEP
BEEP
PROC
; salvar los registros
PUSHA
; hacer el beep
MOV
OUT
MOV
OUT
JMP
MOV
OUT
IN
MOV
OR
OUT
MOV
L1:
LOOP
MOV
OUT

AL,0B6H
43H,AL
AX,3025
42H,AL
SHORT $+2
AL,AH
42H,AL
AL,61H
AH,AL
AL,03
61H,AL
CX,0FFFFH
L1
AL,AH
61H,AL

; restaurar los registros


POPA
; regresar de la interrupcion
IRET
;fin de BEEP
BEEP
ENDP
; locacin despues del area residente
END_OF_PROGRAM:
; fin del segmento de codigo
CSEG
ENDS
;-----------------------------------------------------------------fin de programa
END
MAIN
17.17 Inhibir interrupciones: CLI y STI

91

En raras ocasiones, puedes inhibir al procesador para que no responda a las insterrupciones. Por
ejemplo, digamos que una secuencia de instrucciones depende de un timing exacto. Si una interrupcion
ocurre mientras la instruccione se est ejecutando, el timing puede romperse.
Para controlar la respuesta del procesador las insterrupciones, puedes limpiar o poner la bandera de
interrupcion (IF): La instruccin CLI pona la bandera a 0; la instruccion STI pone la bandera a 1. El
formato es simple:
CLI
STI
Cuando la bandera de interrupcion esta puesta a 1, el procesador sirve las interrupciones. Este es el curso
normal de evntos. Cuando la bandera de interrupcion esta puesta a 0, el procesador ignora todas las
interrupciones excepto las no enmascarables o NMI.
El proposito de las NMI es sealar una interrupcion tan importante que no puede ser ignorada bajo
ninguna circunstancia, por ejemplo un error de hardware.
Si inhibes las interrupciones debes asegurarte de activarlas antes de salir del programa en ensamblador o
en caso contrario dejaras inhabilitadas las interrupciones para el sistema y otros programas.
{_____________o___________}
CAPITULO 16

TRABAJAR CON BITS

Hay dos razones por las cuales debes aprender a trabajar con bits. Primero puedes usar los bits para
representar banderas. La segunda razn es para tener un control mas exquisito sobre los datos. En este
captulo aprenders a usar los tipos de operaciones bsicas.
Para cambiar y probar los valores bits dentro de un byte o palabra (AND, OR, XOR, NOT, TEST)
Para cambiar las posiciones de los bits en un byte o palabra (SHL, SHR, SAL, SAR, ROL, RCL, RCR)
Nuevos Trminos
Mascara de bits. Una secuencia de bits que junto con la operacin AND, OR, o XOR, indica cual bits
deben ser cambiados y cuales ignorar.

16.1 Las cuatro operaciones fundamentales de Bits.


En orden de usar bits o banderas, hay cuatro operaciones fundamentales que debes ejecutar en byte o
palabras.

poner un bit a 0.
poner un bit a 1
complementar ciertos bits (0 a 1 y 1 a 0)
complementar todos los bits
92

Estas operaciones son hechas por las instrucciones AND, OR, XOR, y NOT respectivamente. Aqu estn
los formatos:
AND
OR
XOR
NOT

operando1,operando2
operando1,operando2
operando1,operando2
operando

Cada operando puede ser un byte o una palabra. En las instrucciones con dos operandos estos deben ser
del mismo tamao. El primer operando puede ser un registro o un campo dato; el segundo operando pude
ser un registro, campo dato o valor inmediato.
estas instrucciones modifican los bits dentro del primer operando. El segundo permanece sin cambio.
Aqu hay algunos ejemplos:
AND
OR
XOR
AND
OR
XOR

AX,BX
AL,VALOR
VALOR,DH
DATA,0001100111110110B
AX,3H
DL,a

16.2 Mascaras de Bits.


La instrucciones AND, OR, y XOR modifican los bits del primer operando. Los bits son
seleccionados por el valor del segundo operando, el cuales llamado la mascara de bits. EL segundo
operando permanece sin cambios.
Una mascara de bits cubre ciertos bits del byte o palabra. Solo los bits expuestos pueden ser encendidos o
apagados o complementados. El modo en que opera la mascara es completamente diferente en cada
instruccin. LA idea general es que construyas la mascara usando 0s y 1s conociendo tus
especificaciones.
Por ejemplo, la siguiente instruccin AND tiene una mascara de 0000111100001111B
AND

AX,0000111100001111B

La mascara tambin puede ser especificada con valores en hexadecimal


AND

AX,0F0FH

Otra tcnica til es usar un igual para asignar un valor a la mascara. As se puede usar un nombre en lugar
de un numero especifico.
MASCARA

EQU

0000111100001111B

La instruccin AND puede quedar como:


93

AND

AX,MASCARA

16.3 Apagar bits particulares: AND.


AND apaga bits particulares en el primer operando, el segundo que acta como la mascara
permanece sin cambios. En la mascara un 0 significa que el bit correspondiente se apagar; un 1 indica
que el bit permanecer sin cambios
Aqu hay un ejemplo, digamos que AL contiene 10010110B. Consideremos la instruccin:
AND

AL,11110000B

En este caso, la mascara es 11110000B. La mascara indica que ignorara los cuatro bits de mas a la
izquierda del contenido de AL y tratara de apagar los otros cuatro de mas a la derecha. As el resultado de
la instruccin es que AL tiene un valor de 10010000B.
Si la mascara es de puros 0s, AND apaga todos los bits en el primer operando. Por ejemplo:
AND

BX,0000000000000000B

Pone todos los bits de BX a 0.


Si la mascara es de puros 1s ninguno de los bits del primer operando se vera afectado. Por ejemplo la
siguiente instruccin deja sin cambios al contenido del byte VALOR.
AND
VALOR,11111111B
Uno de los usos ms tiles del AND es poder apagar un bit especifico en un byte o una palabra. Todo lo
que tienes que hacer es usar la mascara para que todos excepto un bit (el que quieres cambiar) no sean
afectados. Por ejemplo, para apagar el bit de mas a la derecha de CX, usa la instruccin:
AND

CX,1111111111111110B

La definicin formal de un AND es como sigue: Compara dos operandos, bit por bit, si los dos bits son 1,
deja un uno en el primer operando, sino deja un cero en ese operando. Las posibilidades son:
0
0
1
1

AND
AND
AND
AND

0
1
0
1

--->
--->
--->
--->

0
0
0
1

Otro ejemplo til del uso del AND es convertir caracteres numricos a decimales sin empacar. Si
examinas la figura 16-1, la cual muestra los caracteres ASCII del 0 al 9 en hex y sus correspondientes
decimales sin empacar, para convertir un numero ASCII a un decimal sin empacar todo lo que tienes que
hacer es cambiar los primeros cuatro bits a 0s. Por ejemplo, para convertir el carcter a 9 en decimal
sin empacar, debes cambiar 39H a 09H.
Figura 16-1 Cdigo ASCII y decimal sin empacar del 0 al 9
ASCII
30H 31H 32H 33H 34H 35H 36H 37H 38H 39H
decimal sin e. 00H 01H 02H 03H 04H 05H 06H 07H 08H 09H
94

Esto puedes hacerlo usando una mascara que cambie los 4 bits de mas a la izquierda a 0000B. La mascara
es 00001111B, el siguiente ejemplo convierte el carcter en AL a un decimal sin empacar:
AND

AL,00001111B

Si AX contiene dos caracteres numricos, uno en cada byte, la siguiente instruccin convierte ambos
caracteres a decimales sin empacar:
AND

AX,0000111100001111B

Algunas persona prefieren ponerlo en hexadecimal.


AND

AX,0F0FH

O usa un igual
CONVERT_ASCII EQU
AND

0F0FH
AX,CONVERT_ASCII

16.4 Encender bits particulares: OR.


OR enciende bits particulares en el primer operando, el segundo que acta como la mascara
permanece sin cambios. En la mascara un 1 significa que el bit correspondiente se encender; un 0 indica
que el bit permanecer sin cambios
Aqu hay un ejemplo, digamos que AL contiene 10010110B. Consideremos la instruccin:
OR

AL,11110000B

En este caso, la mascara es 11110000B. La mascara indica que ignorara los cuatro bits de mas a la
derecha del contenido de AL y tratara de encender los otros cuatro de mas a la izquierda. As el resultado
de la instruccin es que AL tiene un valor de 11110110B.
Si la mascara es de puros 1s, OR enciende todos los bits en el primer operando. Por ejemplo:
OR

BX,1111111111111111B

Pone todos los bits de BX a 1.


Si la mascara es de puros 0s ninguno de los bits del primer operando se vera afectado. Por ejemplo la
siguiente instruccin deja sin cambios al contenido del byte VALOR.
OR

VALOR,00000000B

Uno de los usos ms tiles del OR es poder encender un bit especifico en un byte o una palabra. Todo lo
que tienes que hacer es usar la mascara para que todos excepto un bit (el que quieres cambiar) no sean
afectados. Por ejemplo, para encender el bit de mas a la derecha de CX, usa la instruccin:
OR

CX,0000000000000001B
95

La definicin formal de un OR es como sigue: Compara dos operandos, bit por bit, si los dos bits son 0,
deja un 0 en el primer operando, sino deja un 1 en ese operando. Las posibilidades son:
0
0
1
1

OR
OR
OR
OR

0
1
0
1

--->
--->
--->
--->

0
1
1
1

Otro ejemplo til del uso del OR es convertir decimales sin empacar a ASCII. Si examinas la figura 16-1,
la cual muestra los caracteres ASCII del 0 al 9 en hex y sus correspondientes decimales sin empacar, para
convertir un numero decimal sin empacar a ASCII todo lo que tienes que hacer es cambiar los primeros
cuatro bits a 3H. Por ejemplo, para convertir el decimal sin empacar 09H a ASCII, debes cambiar 09H a
39H.
Esto puedes hacerlo usando una mascara que cambie los 4 bits de mas a la izquierda a 0011B. La mascara
es 00110000B, el siguiente ejemplo convierte el decimal sin empacar al carcter ASCII:
OR

AL,00110000B

Si AX contiene dos decimales sin empacar, uno en cada byte, la siguiente instruccin convierte ambos
decimales sin empacar a caracteres ASCII:
OR

AX,0011000000110000B

Algunas persona prefieren ponerlo en hexadecimal.


OR

AX,3030H

O usa un igual
CONVERT_DEC
OR

EQU

3030H

AX,CONVERT_DEC

.
16.5 Complementar bits particulares: XOR.
XOR complementa bits particulares en el primer operando, el segundo que acta como la mascara
permanece sin cambios. En la mascara un 0 significa que el bit correspondiente permanece sin cambios;
un 1 indica que el bit se complementara.
Aqu hay un ejemplo, digamos que AL contiene 00111100B. Consideremos la instruccin:
XOR

AL,11110000B

En este caso, la mascara es 11110000B. La mascara indica que ignorara los cuatro bits de mas a la
derecha del contenido de AL y tratara de complementar los otros cuatro de mas a la izquierda. As el
resultado de la instruccin es que AL tiene un valor de 11001100B.
Si la mascara es de puros 1s, XOR complementa todos los bits en el primer operando. Por ejemplo:
96

XOR

BX,1111111111111111B

Pone todos los bits de BX a su complemento.


Si la mascara es de puros 0s ninguno de los bits del primer operando se vera afectado. Por ejemplo la
siguiente instruccin deja sin cambios al contenido del byte VALOR.
AND

VALOR,00000000B

Uno de los usos ms tiles del XOR es poder complementar un bit especifico en un byte o una palabra.
Todo lo que tienes que hacer es usar la mascara para que todos excepto un bit (el que quieres cambiar) no
sean afectados. Por ejemplo, para complementar el bit de mas a la derecha de CX, usa la instruccin:
XOR

CX,0000000000000001B

La definicin formal de un XOR es como sigue: Compara dos operandos, bit por bit, si los dos bits son 1
o 0, pone el bit del primer operando a 0, sino deja un 1 en ese operando. Las posibilidades son:
0
0
1
1

XOR
XOR
XOR
XOR

0
1
0
1

--->
--->
--->
--->

0
1
1
0

16.6 Complementar un byte o un palabra completa: NOT.


NOT toma solo un operando y complementa todos los bits en ese operando. Cada 0 se cambia a 1 y
cada 1 cambia a 0: Aqu hay un par de ejemplos:
Si AX contiene 0011001100110011B, la instruccin
NOT

AX

Cambia AX a 1100110011001100B.
Si VALOR es un byte que contiene 11110000B, la instruccin:
NOT

VALOR

Cambia VALOR a 00001111B.


NOT es equivalente a un XOR con una mascaras de 1s. Las siguientes instrucciones equivalentes con
XOR:
XOR
XOR

AX,1111111111111111B
VALOR,11111111B

16.7 Probar Bits particulares: TEST.


97

EL formato de TEST es el siguiente:


TEST

operando1,operando2

TEST examina en primer operando para ver si un bit particular est encendido. Como con AND, OR y
XOR, el primer operando puede ser un registro o un campo dato. El segundo registro puede ser un
registro, campo dato o valor inmediato.
El segundo operando acta como mascara que especifica cuales bits del primer operando sean probados.
En la mascara un 0 indica que el bit correspondiente ser ignorado; un 1 indica que el bit correspondiente
ser examinado.
Aqu hay un ejemplo. Considere la instruccin:
TEST

AL,11110000B

En este caso, la mascar es 11110000B. La mascara le dice a TEST que ignore los 4 bits de mas a la
derecha de AL y que examine los 4 bits de mas a la izquierda.
TEST no cambia ninguno de los operandos. En su lugar TEST examina los operandos y entonces
actualiza la bandera de cero (ZF) para reflejar el resultado de la prueba. Si cualquiera de los bits
especificados est encendido, TEST pone ZF a 0; Si ninguno de los bits especificados est encendido,
TEST pone ZF a 1.
Esto significa que cuando el flujo de control de un programa depende de un valor de un bit especifico,
puedes usar JNZ para saltar si cualquiera de los bits especificados esta encendido. Puedes usar JNZ para
saltar si ninguno de los bits especificados est encendido.
Por ejemplo, la siguiente instruccin salta a L1 si cualquiera de los 4 bits de mas a la izquierda estn
encendidos:
TEST
JNZ

AL,11110000B
L1

Un uso ms comn de TEST es crear un ciclo que contine hasta que un bit particular se encienda o
apague. El siguiente ejemplo llama a un procedimiento, GET_INPUT, el cual cambia el valor de AL. EL
ciclo debe llamar GET_INPUT repetidamente hasta el bit 3 ( el cuarto bit de la derecha) en AL es
encendida.
; repite hasta (bit 3 de AL est encendido)
; llama a GET_INPUT
L1:
CALL
TEST
JZ

GET_INPUT
AL,00001000B
L1

El siguiente ejemplo llama a GET_INPUT repetidamente hasta que el bit 3 de AL est apagado:
; repite hasta (bit 3 de AL est apagado)
; llama a GET_INPUT
L1:
98

CALL
TEST
JNZ

GET_INPUT
AL,00001000B
L1

La definicin formal de TEST es para ejecutar una operacin AND sin cambiar ningn operando. ZF se
pone a 1 o a 0 dependiendo del resultado del AND.

16.8 Cambiar la posicin de los bits en un byte o palabra.


La instruccin descrita en la siguiente seccin cambia la posicin de un bit en un byte o en una
palabra. La lista de estas instrucciones est en la tabla 16-1. Puedes usar el mismo formato para todas las
instrucciones:
opcode

operando,contador

Por ejemplo:
SHL

VALOR,4

El primer operando puede ser un registro o un campo dato. Este operando debe ser un byte o palabra.
Cada una de estas instrucciones cambia los bits en el primer operando de izquierda a derecha. El numero
de posiciones es indicada por el valor del segundo operando (el contador)
Tabla 16-1 Instrucciones para cambiar las posiciones de los bits.
Nombre
Significado
SHL
Cambiar a la izquierda
SAL
Cambiar aritmticamente a la izquierda
SHR
Cambiar a la derecha
SAR
Cambiar aritmticamente a la derecha
ROL
Rotar a la izquierda
ROR
Rotar a la derecha
RCL
Rotar con acarreo a la izquierda
RCR
Rotar con acarreo a la derecha
Puedes especificar el contador de dos maneras, con un valor inmediato en el rango de 0 a 31. Por ejemplo
para cambiar los bits de AX cinco posiciones a la derecha, usas la instruccin:
SHL

AX,5

Tambin puedes usar a CL como el contador asegurndote que tenga un valor entre 0 y 31. El siguiente
ejemplo usa a CL como el contador para la misma operacin anterior.
MOV
SHL

CL,5
AX,CL

16.9 Las instrucciones bsicas de movimiento: SHL y SHR.


Las instrucciones SHL y SHR cambian bits a la izquierda o derecha respectivamente. Los bits que
son cambiados afuera se pierden. Por ejemplo si cambias el registro DL tres posiciones ala derecha:
99

SHR

DL,3

los tres bits originales de mas a la derecha se pierden. Sin embargo el ltimo bit que fue cambiado afuera
siempre queda en la bandera de acarreo CF. Esto es cierto para todas las instrucciones de cambio.
Por ejemplo si DL contiene

y cambias los bits tres posiciones a la derecha, los tres bits de ms a la derecha -100- se perdern. Si
embargo CF tendr el valor del ultimo bit perdido.
Sin embargo un byte o una palabra no solo pierde bits, tambin hay nuevos espacios generados por el
corrimiento que deben ser llenados. Con SHL y SHR, estos espacios son llenados con 0s. Por ejemplo si
DL contiene

y mueves los bits a tres posiciones a la derecha, las posiciones dems a la izquierda son llenadas con 0s,
lo cual produce lo siguiente:

Con un movimiento a la izquierda, los bits de mas a la derecha son llenados con 0s. Por ejemplo, si DL
tuviera 11001100 y movieras los bits tres posiciones a la izquierda:
SHL

DL,3

El valor final es

CF contiene el ultimo bit que fue sacado del registro (0).

16.10 Los usos del SHL y SHR.


SHL y SHR tienen dos usos importantes. Primero, puedes usarla para aislar parte de un byte o una
palabra.

100

Aqu hay un ejemplo. Digamos que quieres aislar los bits 3,4 y 5 en AL y moverlos a la parte mas a la
derecha el registro. Esto es, quieres cambiar

Primero cambia todos los bits a 0. Entonces cambia AL tres posiciones a la derecha:
AND
SHL

AL,00111000B
AL,3

Alternativamente podemos mover primero AL dos posiciones a la izquierda y luego cinco a la derecha:
SHL
SHL

AL,2
AL,5

El segundo uso importante de SHL y SHR es multiplicar y dividir en potencias de dos. Cuando usas
nmeros sin signo los movimientos a la izquierda multiplican por dos y los movimientos a la derecha
dividen entre 2.
Por ejemplo, digamos que AL contiene 00001010B (5). Moviendo bits a la izquierda dos posiciones
tenemos
00000101B (5) --------> 00010100B (20)
As como movimos en dos posiciones el contenido multiplicamos por 4.
Aqu hay algunos ejemplos. El primero multiplica BX por 16; el segundo divide VALOR entre 4:
SHL
SHR

BX,4
VALOR,2

Estas multiplicaciones son mas rpidas que las hechas por las operaciones DIV Y IDIV.
Figura 16-2 Numero de posiciones a mover para multiplicar y dividir
Para multiplicar o dividir por
mueve el numero de lugares
2
1
4
2
8
3
16
4
32
5
64
6
128
7
256
8
512
9
101

1024

10

16.11 Multiplicar y dividir nmeros con signo por movimiento de bits: SAL y SAR.
Las instrucciones SAL y SAR trabajan bien cuando quieres multiplicar o dividir nmeros con signo.
Sin embargo, necesitas instrucciones especiales cuando mueves nmeros con signo. Estas instrucciones
son SAL (mover aritmticamente a la izquierda) y SAR (mover aritmticamente a la derecha).
Aqu est la razn de estas instrucciones: Considere que pasa cuando mueves un numero con signo a la
derecha (dividir). Si el numero es negativo, el resultado debes ser negativo. Sin embargo, si usas SHR, los
espacios de ms a la izquierda sern llenados con 0s. Esto da un resultado completamente errneo. No
sol un valor errneo, sino con un signo positivo.
La solucin es como sigue: Cuando mueves nmeros con signo a la derecha, se llenan los espacios de
mas a la izquierda con 0s si el numero es positivo y con 1s si el numero es negativo
Aqu hay dos ejemplos. Digamos que AL contiene 00001111B(!%). aqu est lo que pasa cuando usas la
instruccin SAR para dividir entre 4:

El resultado es 00000011B (3): Esto es correcto debido a que 15/4 es tres con un residuo de 3. (recuerda
que cuando divides con movimiento de bits el residuo se pierde.)
En el segundo ejemplo, BL contiene 11110001B (-15). Aqu est lo que pasa cuando usas SAR para
dividir entre 4:

El resultado es 11111100B (-4). Esto es correcto debido a que en aritmtica con signo, -15/4 es -4 y sobra
-1.
Cuando multiplicas nmeros con signo no hay problema ya que siempre se llenan los espacios con ceros
As las instrucciones SAL y SHL son las mismas.
16.12 Las instrucciones de rotacin: ROL, ROR, RCL y RCR.
Las instrucciones de rotacin son variaciones de las instrucciones de movimientos. La diferencia
lgica es como sigue: Con las instrucciones de movimiento los bits que son cambiados fuera se pierden y
los lugares vacos son reemplazados por ceros (o algunas veces 1s). Con las instrucciones de rotacin,
los bits forman un ciclo continuo de manera que los bits que salen fuera entra por el lado contrario. As
ningn bit se pierde.
ROR mueve bits a la derecha; ROL mueve bits a la izquierda.
102

Aqu hay dos ejemplos. Digamos que AL contiene 00001111B. Aqu est lo que pasa cuando usas ROR
para rotar AL a la derecha una posicin:

El bit de ms a la derecha es movido fuera y entra por el otro lado en el espacio libre, CF tiene el valor
del ultimo bit que sali en este caso 1.
En el segundo ejemplo, AL contiene 00001111B y ROL rota los bits cinco posiciones a la izquierda:

Uno por uno, los 5 bis son sacados fuera por la izquierda y entran en el orden en que salen por la derecha.
CF est puesta al ultimo valor que sali, en este caso 1.
Est instruccin es til cuando quieres cambiar el orden de los bits sin perderlos.
La RCR y RCL son similares a ROR y ROL. La nica diferencia es que CF es considerada como un bit
extra que participa completamente en la rotacin.
Con RCR, puedes pensar que CF es un bit extra que est pegado a la derecha del byte o palabra. Con
RCL, CF est pegada a la izquierda del byte o palabra.
Por ejemplo, digamos que AL contiene 00111100B y CF contiene 1, la instruccin:
RCR

AL,1

Considera AL y CF para formar una entidad de 9 bits. La rotacin tiene el siguiente efecto:

Los bits dems a la derecha de AL son movidos junto con CF; al mismo tiempo, CF es movida al bit de
mas a la izquierda de AL para llenar el espacio.
Aqu hay un ejemplo que usa RCL. Digamos que CF contiene un 0 y AL contiene 00111100B, la
instruccin
RCL

AL,3

Considere CF y AL para formar una sola entidad de 9 bits de longitud. La rotacin tiene el efecto:

La figura 16-3 ilustra las diferentes variedades de instrucciones de movimiento y rotacin


103

Figura 16-3 Resumen de las instrucciones de movimiento y rotacin

CAPITULO 17

COMO PROVEE SERVICIOS DOS: INTERRUPCIONES

Muchos de los eventos de la computadora son impredecibles, por ejemplo la presin de una de las
teclas del teclado, el procesador necesita estar al cuidado de responder a ciertos eventos y manejarlos
apropiadamente. El sistema por el cual el procesador maneja eventos impredecibles es uno de los tpicos
104

discutidos en este captulo. El segundo tpico es como este sistema pude ser extendido para propsitos
diferentes.
Nuevos Trminos
Interrupcin. Una sea de que un evento necesita atencin inmediata.
Servicio. El manejo de una interrupcin.
Manejador de interrupcin. Un procedimiento que se ejecuta cuando una interrupcin ocurre.
Vector de interrupciones. Un nmero que identifica una interrupcin especifica.
Tabla descriptiva de interrupciones. Una tabla con direcciones completas, donde cada una apunta a un
manejador de interrupcin.
Interrupcin de Hardware. Un interrupcin generada desde un dispositivo de hardware. Tambin
llamada interrupcin externa.
Interrupcin de Software. Una interrupcin que se origina desde un programa en ejecucin. Tambin
llamada interrupcin interna.
BIOS (Basic Input/Output System). Una serie de programas complejos, almacenados en la memoria
ROM, que provee servicios esenciales de bajo nivel.
Dispositivo Driver. Una interfase estndar a un dispositivo hardware.
Llamada a una funcin. Un servicio ofrecido por DOS bajo los auspicios de la interrupcin 21H.
Numero de llamada. Un numero que identifica una llamada a una funcin especifica.
Prefijo de Segmento de programa (PSP). Un arrea de memoria de 256 bytes que contiene un conjunto
de informacin usada por dos para ejecutar un programa.
Programa residente en memoria. Un programa que permanece en la memoria permanentemente
mientras la computadora esta encendida.
Interrupcin no enmascarable (NMI). Una interrupcin tan importante que no puede ser ignorada bajo
ninguna circunstancia.

17.1 Interrupciones.
El procesador debe tener la capacidad de ver algunos eventos, muchos de los cuales ocurren en
tiempos impredecibles. Muchos de estos eventos se originan en el hardware, Veamos algunos de ellos.
La seal del teclado por la presin en alguna tecla..
La impresora que no tiene papel.
Una seal de un dispositivo de disco que ha terminado de transferir datos.
Un chip de memoria defectuoso es detectado.
105

Ocasionalmente un evento impredecible puede ocurrir en el software


Un programa ha tratado de dividir por cero.
Generalmente hablando, hay dos maneras de manejar una interrupcin. La primera es ignorar los eventos
externos que ocurren haciendo pausas a intervalos regulares para ver si algo necesita atencin. La
segunda es manejar los eventos tal como ocurren. Sin embargo con este mtodo debes marcar lo que
estabas haciendo para procesar el evento y despus regresar a donde estabas.
El procesador fue diseado usando el segundo sistema. La computadora siempre est preparada para
reconocer una seal que indique que un evento ha ocurrido y requiere atencin inmediata. Tal seal es
llamada una interrupcin. Cuando la interrupcin ocurre, el procesador aparta al programa actual, maneja
la interrupcin, y entonces regresa al programa en donde se quedo. Nosotros decimos que el procesador
sirve la interrupcin.

17.2 Como son servidas las interrupciones.


Despus de detectar una interrupcin, el procesador ejecuta un procedimiento especial llamado una
manejador de interrupcin. Cada tipo de interrupcin requiere su propio manejador de interrupcin. El
propsito de que el manejador atienda a la interrupcin de manera adecuada. Una vez que termina, el
procesador continua con el programa n progreso.
Desde el punto de vista del procesador, iniciar un manejador de interrupcin es muy parecido a iniciar la
llamada a un procedimiento. La diferencia principal es que antes de saltar al principio del manejador, el
procesador debe salvar la suficiente informacin para reiniciar el programa actual. En particular, el
procesador debe salvar las banderas y la direccin completa de la siguiente instruccin en el programa
actual.
Aqu estn los pasos que el procesador sigue cuando tiene que tratar con una interrupcin:
1. Termina la instruccin que este ejecutando actualmente.
2. Empuja las banderas a la pila.
3. Empuja el segmento de direccin de la siguiente instruccin en la pila.
4. Empuja el offset de la siguiente instruccin a la pila.
5. Determina la direccin del manejador de interrupcin apropiada.
6. Llama al manejador de interrupcin.
Cuando la interrupcin termina, el procesador restaura la banderas e reinicia el programa que fue
interrumpido.

17.3 La tabla descriptiva de interrupciones.


Cada interrupcin es servida por su propio manejador de interrupcin. Cuando la interrupcin
ocurre, el procesador debe identificar el tipo de interrupcin y determina la direccin del manejador
apropiado.
El sistema est diseado para que cada interrupcin diferente este definida por un numero llamado el
vector de interrupciones.
106

DOS mantiene una tabla de direcciones completas, cada una apuntando a un manejador diferente. Est
tabla es llamada tabla descriptiva de interrupciones. La tabla descriptiva es almacenada en las locaciones
de memoria mas bajas de 0000H a 03FFH (1024 bytes). Cada vector requiere 4 bytes para su
identificacin (direccin de segmento y offset), la tabla puede mantener hasta 256 direcciones completas.
Esto significa que DOS puede proveer hasta 256 interrupciones diferentes, pero algunas de estas no tiene
uso.
Las 256 posibles interrupciones estn numeradas desde 0H a FFH. Las direcciones para las interrupciones
son almacenadas en el mismo orden en la tabla descriptiva. As la direccin completa para el manejador
de interrupcin 0 esta almacenada en los cuatro bytes empezando en la locacin 0000H. La direccin del
manejador 1 est e la locacin 0004H. La direccin del 2 esta en la locacin 0008H. En general, la
direccin de la n interrupcin esta en la locacin 4 x n.
As cuando una interrupcin ocurre el procesador calcula el numero de servicio por 4 para obtener la
direccin del manejador para esa interrupcin, por ejemplo para la interrupcin 20H, el procesador
ejecuta el manejador cuya direccin est en la locacin 0080H.
La tabla es ajustada automticamente cuando inicia DOS, sin embargo en principio, estas direcciones
pueden ser cambiadas por manejadores de interrupcin nuevos o modificaciones a interrupciones que ya
tengan uso.

17.4 Las interrupciones que son usadas por el programador: INT.


Las interrupciones tiene dos propsitos: Primero, permiten que la computadora responda
inmediatamente a eventos que pasan inpredeciblemente. Segundo, es posible que un programa mande una
seal de interrupcin. Sin embargo como es posible que un programa llame a tal procedimiento? La
respuesta est en el sistema operativo (DOS) y el software interconstruido (el BIOS) que ofrecen muchos
servicios a los programas. En orden de tomar ventaja de estos servicios, un programa debe ser capaz de
llamar al procedimiento adecuado. Sin embargo no hay un modo fcil par que el programa sepa las
locaciones de estos procedimientos.
La solucin es asignar a cada servicio un numero que corresponda a un vector de interrupcin. Un
programa puede requerir un servicio que corresponda al vector de interrupcin. De hecho la instruccin
INT tiene este propsito, este es su formato:
INT

vector-interrupcin

Por ejemplo, un programa puede sealar a la interrupcin 21H ejecutando lo siguiente:


INT

21H

Las interrupciones tiene dos propsitos:


*
Permiten al procesador atender las necesidades del hardware
*
Permiten a un programa requerir servicios del sistema operativo y del software interconstruido.
Una interrupcin que se origina por una seal de hardware es conocida como interrupcin externa, por el
contrario una interrupcin generada por el software es llamada interrupcin interna.

107

17.5 El BIOS.
El BIOS provee tres funciones importantes:
Primera, el BIOS contiene la prueba para encendido (POST), la cual se ejecuta automticamente cada vez
que enciendes la computadora. El POST checa varias partes de la computadora incluyendo la memoria,
para encontrar problemas de hardware antes de usar la mquina.
Segundo, el BIOS contiene programas especiales, llamados dispositivos manejadores (device drivers),
que proveen un conjunto de interfaces estndar para los dispositivos hardware. Un device driver opera al
nivel del hardware, mandando y recibiendo seales byte por byte. Sin dispositivos manejadores tendras
muchos problemas para usar una parte de hardware. En general los drivers protegen a los programadores
de tener que comprender las caractersticas de los varios dispositivos hardware.
Adems de los drivers interconstruidos, DOS tambin permite instalar manejadores de dispositivos
cuando enciendes la mquina. Esto permite mejorar e innovar el manejo del hardware. Los dispositivos
drivers se especifican usando el comando DEVICE en el archivo CONFIG:SYS.
Tercero, algunos de los servicios del BIOS pueden ser utilizados por los programas, con la requisicin de
interrupciones. Sin embargo, hay un par de excepciones que no pueden ser usadas directamente, y que
son usadas solo por el sistema operativo.
17.6 El sistema operativo: DOS.
El programador puede considerar al sistema operativo como un proveedor de servicios. Para requerir
un servicio (con DOS) puedes usar la instruccin INT para marcar la seal de un interrupcin. DOS est
diseado para ejecutar muchas de las tareas ms complejas e importantes que tus programas requieren. Lo
bueno de tener las tareas del DOS es que programador puede despreocuparse de como ejecutar esas
tareas. Por ejemplo para leer un archivo se necesitan cientos de instrucciones de lenguaje de bajo nivel.
Con el DOS y el BIOS podemos hacer casi todo automticamente.

17.7 Las llamadas de funcin DOS.


DOS provee mas de 130 servicios tiles en los programas. Cada servicio tiene su propio vector de
interrupcin (nmeros). Los servicios de DOS ofrece bajo el auspicio de la interrupcin 21H es llamada
llamada a funcin.
Cada llamada a funcin est identificada por un numero llamado numero de llamada. Para usar esta
funcin, ponemos en el registro AH el numero de llamada, y entonces sealamos la interrupcin 21H. Por
ejemplo la siguiente llamada a funcin 19H determina la unidad actual de disco por default. Las
siguientes instrucciones ejecutan la llamada a funcin:
; determina la unidad actual por omisin
MOV
AH,19H
INT
21H
Ya que todas las llamadas a funcin son ejecutadas por la misma interrupcin, esto provee un modo
estndarizado para ofrecer servicios para programar.
108

Los siguientes dos resmenes contienen las llamadas de funcin de DOS en categoras, ordenadas por el
numero de llamada. Estas listas estn actualizadas hasta la versin 6.2.
Resumen de llamadas a funciones de DOS por categoras.
Input/Output para archivos
2EH
3CH
3DH
3EH
3FH
40H
42H
45H
46H
54H
5AH
5BH
67H
68H
6CH
4402H
4403H
4404H
4405H
4406H
4407H

Modificar los campos del switch de verificacin


Abrir un archivo para salida
Abrir un archivo existente
Cerrar un archivo
Leer de un archivo o dispositivo
Escribir a un archivo o dispositivo
Mover un apuntador Lectura/Escritura
Crear un manejador de archivo duplicado
Hacer un manejador de archivo existente igual a otro
Obtener los campos del switch de verificacin
Crear un archivo con un nombre nico
Crear un archivo nuevo
Ajustar el numero mximo de manejadores de archivos
Desalojar los buffers de archivos a disco
Crear, abrir o remplazar un archivo (combinaciones de 3CH, 3DH, 5BH)
Leer de un dispositivo de carcter
Escribir a un dispositivo de carcter
Leer de un dispositivo de carcter
Escribir a un dispositivo de carcter
Determinar si un dispositivo est listo para entrada
Determinar si un dispositivo est listo para salida

Entrada/Salida de caracteres
01H
02H
03H
04H
05H
06H
07H
08H
09H
0AH
0BH
0CH

Leer de la entrada estndar (teclado): sin esperar, con eco


Escribir a la salida estndar (pantalla)
Leer del dispositivo auxiliar estndar; esperar
Escribir al dispositivo auxiliar estndar
Escribir al dispositivo estndar de impresin
Leer de la entrada estndar (teclado), esperar, con eco
Leer de la entrada estndar (teclado), esperar, sin eco
Leer de la entrada estndar (teclado), esperar, con eco, ?break
Escribir un string a la impresora estndar
Leer de la entrada estndar (teclado)
Checar si la entrada estndar (teclado) tiene carcter disponible
Teclado: limpiar el buffer y entonces invocar la llamada a funcin

Entrada/Salida de archivos del viejo DOS 2.00 (No use nunca las llamadas a funcin I/O)
0DH
0FH
10H
11H
12H
13H
14H

Desalojar todos los buffers de archivos


Abrir un archivo
Cerrar un archivo
Encontrar el primer nombre de archivo igual a la especificacin
Encontrar el siguiente nombre de archivo igual a la especificacin
Borrar un archivo
Lectura secuencial de un archivo
109

15H
16H
17H
1AH
21H
22H
23H
24H
27H
28H
29H
2FH

Escritura secuencial de un archivo


Crear un archivo
Renombrar un archivo
Ajustar la direccin de transferencia a disco
Lectura aleatoria de un archivo
Escritura aleatoria de un archivo
Obtener el tamao de un archivo en registros
ajustar aleatoriamente el campo de un registro
Lectura aleatoria de un bloque de un archivo
Escritura aleatoria de un bloque de un archivo
Parsear un nombre de archivo
Obtener la direccin de transferencia de disco

Manejo de archivos
43H
4EH
4FH
56H
57H

Cambiar el modo de un archivo (Atributos)


Encontrar el primer nombre de archivo igual a la especificacin
Encontrar el siguiente nombre de archivo igual a la especificacin
Renombrar o mover un archivo
Obtener o modificar la fecha o la hora

Manejo de directorios
39H
3AH
3BH
41H
47H

Crear un subdirectorio
Remover un subdirectorio
Ajustar al directorio actual
Borrar un archivo de un directorio
Obtener el nombre del directorio actual

Manejo de dispositivos
0EH
19H
1BH
1CH
1FH
32H
3305H
36H
4400H
4401H
4408H
440CH
440DH
440EH
440FH
4410H
4411H

Seleccionar la unidad de disco por omisin


Determinar la unidad de disco por default
Obtener la direccin de la locacin de la tabla acerca de la unidad de default
Obtener la direccin de la locacin de la tabla acerca de dispositivo especificado
Obtener el bloque de parmetro de unidad para la unidad de default
Obtener el bloque de parmetro de la unidad (viejo: use 1FH o 36H)
Obtener el cdigo del boot de la unidad
Obtener la informacin del espacio del disco
Obtener la informacin del dispositivo
Ajustar la informacin del dispositivo
Determinar si el bloque de dispositivo soporta medios removibles
Permitir que el driver de dispositivo soporte el intercambio de paginas de cdigo
IOCTL uniforme para soportar dispositivos de bloque
Determinar si le bloque de dispositivo tiene unidades lgicas de letras mayores que 1
Asignar una letra de unidad lgica a un bloque de dispositivo
Determinar si un dispositivo soporta servicios IOCTL
Determinar si una unidad soporta servicios IOCTL

Manejo de programas
00H

Terminar un programa: sin cdigo de retorno (viejo: usa 31H o 4CH)


110

25H
26H
30H
31H
3300H
3301H
3306H
34H
35H
48H
49H
4AH
4B00H
4B03H
4B05H
4CH
4DH
50H
51H
5D0AH
5800H
5801H
5802H
5803H
59H
62H

Modificar la entrada de la tabla descriptora de interrupciones


Crear un nuevo segmento de programa (viejo: usa 4BH)
Obtener la versin del DOS
Terminar un proceso y dejarlo residente: ajustar el cdigo de retorno
Obtener la bandera Ctrl-Break
Ajustar la bandera Ctrl-Break
Obtener la versin del DOS (ms sofisticado que 30H)
Obtener la bandera InDOS
Obtener la entrada de la tabla descriptora de interrupciones
Colocar memoria
Liberar memoria colocada
Modificar memoria colocada
Cargar y ejecutar un programa
Cargar y superponer
Preparar a DOS para transferir control a un nuevo programa
Terminar un proceso: ajustar el cdigo de regreso
Obtener el cdigo de retorno de otro proceso
Definir la direccin de un nuevo prefijo de segmento de programa (PSP)
Obtener la direccin del prefijo de segmento de programa (PSP) actual
Ajustar la informacin de error extendida
Determinar que estrategia que colocacin de memoria esta usando DOS
Ajustar la estrategia de colocacin de memoria que DOS puede usar
Determina si el rea de memoria alta (HMA) esta disponible
Decirle a DOS que el rea de memoria (HMA) alta est disponible
Obtener informacin de error extendida
Obtener la direccin del segmento de prefijo de programa (PSP)

Redes
4409H
440AH
440BH
5CH
5E00H
5E02H
5E03H
5F02H
5F03H
5F04H

Determina si un dispositivo lgico es local o remoto


Determinar si el manejador de archivo es local o remoto
Especifica el numero de intento a acceso a archivo y el retraso del reintento
Bloque o desbloquea parte de un archivo
Obtener el nombre de la mquina
Especificar la actualizacin de la impresora
Obtener la actualizacin de la impresora
Obtener los asignamientos de redes no locales
Hacer la conexin redirector/servidor
Cancelar la redireccin previa

Fecha y hora
2AH
2BH
2CH
2DH

Obtener la fecha
Ajustar la fecha
Obtener la hora
Ajustar la hora

Servicios especficos del pas


38H
66H
6501H

Obtener o ajustar la informacin dependiente del pas


Obtener o ajustar el cdigo de pagina global para la seleccin del pas actual
Obtener informacin extendida del pas
111

6502H
6504H
6505H
6506H
6507H
6520H
6521H
6522H

Obtener la direccin para la tabla de mapa: caracteres mayores de ASCII 127


Obtener la direccin para la tabla de mapa: nombre del archivo de caracteres > ASCII 127
Obtener la direccin para la tabla de caracteres invlidos: nombres de archivos
Obtener la direccin para la tabla en secuencia ordenada
Obtener la direccin del ajuste de tabla para caracteres de doble byte
Convertir un carcter simple usando tabla mapa
Convertir cadena de caracteres usando la tabla mapa
Convertir una cadena de caracteres ASCIIZ usando la tabla mapa

Resumen de llamada de funciones por orden de numero de llamada de funcin


00H
01H
02H
03H
04H
05H
06H
07H
08H
09H
0AH
0BH
0CH
0DH
0FH
10H
11H
12H
13H
14H
15H
16H
17H
19H
1AH
1BH
1CH
1FH
21H
22H
23H
24H
25H
26H
27H
28H
29H
2AH
2BH
2CH
2DH

Terminar un programa: sin cdigo de retorno (viejo: usa 31H o 4CH)


Leer de la entrada estndar (teclado): sin esperar, con eco
Escribir a la salida estndar (pantalla)
Leer del dispositivo auxiliar estndar; esperar
Escribir al dispositivo auxiliar estndar
Escribir al dispositivo estndar de impresin
Leer de la entrada estndar (teclado), esperar, con eco
Leer de la entrada estndar (teclado), esperar, sin eco
Leer de la entrada estndar (teclado), esperar, con eco, ?break
Escribir un string a la impresora estndar
Leer de la entrada estndar (teclado)
Checar si la entrada estndar (teclado) tiene carcter disponible
Teclado: limpiar el buffer y entonces invocar la llamada a funcin
Desalojar todos los buffers de archivos
Abrir un archivo
Cerrar un archivo
Encontrar el primer nombre de archivo igual a la especificacin
Encontrar el siguiente nombre de archivo igual a la especificacin
Borrar un archivo
Lectura secuencial de un archivo
Escritura secuencial de un archivo
Crear un archivo
Renombrar un archivo
Determinar la unidad de disco por omisin
Ajustar la direccin de transferencia a disco
Obtener la informacin de la tabla de colocacin acerca del la unidad por default
Obtener la informacin de la tabla de colocacin acerca del la unidad especificada
Obtener el bloque de parmetros para la unidad por default
Lectura aleatoria de un archivo
Escritura aleatoria de un archivo
Obtener el tamao de un archivo en registros
ajustar aleatoriamente el campo de un registro
Modificar la entrada en la tabla descriptora de interrupciones
Crear un nuevo segmento de programa (viejo: usa 4BH)
Lectura aleatoria de un bloque de un archivo
Escritura aleatoria de un bloque de un archivo
Parsear un nombre de archivo
Obtener la fecha
Ajustar la fecha
Obtener la hora
Ajustar la hora
112

2EH
2FH
30H
31H
32H
3300H
3301H
3306H
34H
35H
36H
38H
39H
3AH
3BH
3CH
3DH
3EH
3FH
40H
41H
42H
43H
4400H
4401H
4402H
4403H
4405H
4406H
4407H
4408H
4409H
440AH
440BH
440CH
440DH
440EH
440FH
4410H
4411H
45H
46H
47H
48H
49H
4AH
4B00H
4B03H
4B05H
4CH
4DH
4EH

Modificar campos del switch de verificacin


Obtener la direccin de transferencia de disco
Obtener la versin del DOS
Terminar un proceso y dejarlo residente: ajustar el cdigo de retorno
Obtener el bloque de parmetros de la unidad
Obtener la bandera Ctrl-Break
Ajustar la bandera Ctrl-Break
Obtener la versin del DOS (ms sofisticado que 30H)
Obtener la bandera InDOS
Obtener la entrada de la tabla descriptora de interrupciones
Obtener informacin del espacio en disco
Obtener o poner la informacin dependiente del pas
Crear un subdirectorio
Remover un subdirectorio
Poner el directorio actual
Abrir un archivo para salida
Abrir un archivo existente
Cerrar un archivo
Leer de un archivo o dispositivo
Escribir a un archivo o dispositivo
Borrar un archivo de un subdirectorio
Mover un apuntador Lectura/Escritura
Cambiar el modo de un archivo (atributos)
Obtener la informacin de un dispositivo
Ajustar la informacin de un dispositivo
Leer de un dispositivo de caracteres
Leer de un dispositivo de caracteres
Escribir a un dispositivo de caracteres
Determinar si un dispositivo est listo para entrada
Determinar si un dispositivo est listo para salida
Determinar si el bloque de dispositivo soporta medios removibles
Determina si un dispositivo lgico es local o remoto
Determinar si el manejador de archivo es local o remoto
Especifica el numero de intento a acceso a archivo y el retraso del reintento
Permitir que el driver de dispositivo soporte el intercambio de pginas de cdigo
IOCTL uniforme para soportar dispositivos de bloque
Determinar si le bloque de dispositivo tiene unidades lgicas de letras mayores que 1
Asignar una letra de unidad lgica a un bloque de dispositivo
Determinar si un dispositivo soporta servicios IOCTL
Determinar si una unidad soporta servicios IOCTL
Crear un manejador de archivo duplicado
Hacer un manejador de archivo existente igual a otro
Obtener el nombre del directorio actual
Colocar memoria
Liberar memoria colocada
Modificar memoria colocada
Cargar y ejecutar un programa
Cargar y sobreponer
Preparar a DOS para transferir el control a un nuevo programa
Terminar un proceso: ajustar el cdigo de retorno
Obtener el cdigo de retorno de otro proceso
Encontrar el primer nombre de archivo igual a la especificacin
113

4FH
50H
51H
54H
56H
5800H
5801H
5802H
5803H
59H
5AH
5BH
5CH
5D0AH
5E00H
5E02H
5E03H
5F02H
5F03H
5F04H
62H
6501H
6502H
6504H
6505H
6506H
6507H
6520H
6521H
6522H
66H
67H
68H
6CH

Encontrar el siguiente nombre de archivo igual a la especificacin


Definir la direccin de un nuevo prefijo de segmento de programa (PSP)
Obtener la direccin del prefijo de segmento de programa (PSP) actual
Obtener los campos del switch de verificacin
Renombrar o mover un archivo
Determinar que estrategia que colocacin de memoria esta usando DOS
Ajustar la estrategia de colocacin de memoria que DOS puede usar
Determina si el rea de memoria alta (HMA) esta disponible
Decirle a DOS que el rea de memoria (HMA) alta est disponible
Obtener informacin de error extendida
Crear un archivo con un nombre nico
Crear un archivo nuevo
Bloque o desbloquea parte de un archivo
Ajustar la informacin de error extendida
Obtener el nombre de la mquina
Especificar la actualizacin de la impresora
Obtener la actualizacin de la impresora
Obtener los asignamientos de redes no locales
Hacer la conexin redirector/servidor
Cancelar la redireccin previa
Obtener la direccin del segmento de prefijo de programa (PSP)
Obtener informacin extendida del pas
Obtener la direccin para la tabla de mapa: caracteres mayores de ASCII 127
Obtener la direccin para la tabla de mapa: nombre del archivo de caracteres > ASCII 127
Obtener la direccin para la tabla de caracteres invlidos: nombres de archivos
Obtener la direccin para la tabla en secuencia ordenada
Obtener la direccin del ajuste de tabla para caracteres de doble byte
Convertir un carcter simple usando tabla mapa
Convertir cadena de caracteres usando la tabla mapa
Convertir una cadena de caracteres ASCIIZ usando la tabla mapa
Obtener o ajustar el cdigo de pagina global para la seleccin del pas actual
Ajustar el numero mximo de manejadores de archivos
Desalojar los buffers de archivos a disco
Crear, abrir o remplazar un archivo (combinaciones de 3CH, 3DH, 5BH)

17.8 Guas para usar las llamadas a funcin de DOS.


Muchas llamadas a funciones requieren entrada y generan salida. Sin embargo las llamadas de
funcin no accesan al rea de datos del programa, toda la informacin debe ser pasada y regresada a
travs de los registros.
Antes de una llamada a funcin, tenemos que saber exactamente que valores necesitan ser puestos en los
registros y que contendrn cuando la llamada a funcin regrese. Para la entrada, la llamada a funcin
requiere que el numero de la funcin este en AH. Como regla general, DL es usado para mantener un
valor de entrada, y DX es usado para mantener el offset de un string de entrada en el segmento de datos.
Para salida, los valores son regresados en AX, AL o DL. Sin embargo hay excepciones a estas reglas.
Una caracterstica especial es que la llamada de funcin regresa un 0 en CF si todo paso
satisfactoriamente, si un error ocurre CF es puesta a 1. As podemos usar un salto condicional (JC o JNC)
despus de la interrupcin para cerciorarnos de que todo sali bien. La interrupcin 21H como todo
114

procedimiento bien construido no cambia los valores de los registros o de las banderas excepto los
registros que son utilizados para regresar resultados de salida.
Una vez que DOS toma el control, este usa su propia pila interna. Sin embargo, el mecanismo de
interrupcin usa la misma pila que el programa que llama. En orden de asegurarte de que la pila sea
suficientemente grande, deja un espacio de 200 H extra aparte de las necesidades de tu programa.
17.9 Ejemplos de llamadas a funcin DOS.
El primer ejemplo usa la llamada a funcin 30H para obtener el nmero de versin de DOS. Para
preparar esta funcin, ajusta AH al numero de llamada 30H. La salida esta en dos partes: El numero
mayor de la versin esta en el registro AL, y el menor en AH. Por ejemplo si la versin del sistema
operativo es DOS 5.0, AL contiene un % y AH contiene un 0.
; obtener el numero de versin
; AL <--- numero mayor de la versin
; AH <--- numero menor de la versin
MOV
AH,30H
INT
21H
El segundo y tercer ejemplo usa la llamadas a 2AH y 2BH para obtener y ajustar la fecha. Para obtener la
fecha, usa la llamada a funcin 2AH. Primero ajusta AH al numero de llamada 2AH. Esta es la salida:
AL <--- Dia de la semana (0 para Domingo, 1 para Lunes...)
CX <--- Ao (de 1980 al 2099)
DH <--- Mes (1 para Enero, 2 para Febrero...)
DL <--- Dia (1 al 31)
Por ejemplo, digamos que es Lunes, 21 de Diciembre de 1992, puedes ejecutar la siguiente instruccin:
; obtener la fecha
MOV
INT

AH,2AH
21H

Como salida, DOS ajusta los registros de la siguiente manera:


AL = 1;

CX= 1992 (07C8H);

DH = 12; DL = 21

Para ajustar la fecha, usamos la funcin 2BH. Como entrada, colocamos el ao, mes y da en CX, DH y
DL.
Por ejemplo para poner la fecha Diciembre 21 de 1992 usamos las instrucciones
; ajustar la fecha a Diciembre 21 de 1992
MOV
CX,1992
MOV
DH,12
MOV
DL,21
MOV
AH,28H
INT
21H

115

Aqu hay un ejemplo que usa estas dos funciones para calcular el da de la semana de una fecha
especifica. La idea es que si ajustas la fecha a una fecha especifica, puedas hacer que DOS calcule el da
de la semana para ti. La lgica es como sigue:
Salvar la fecha actual
Usar la funcin 2AH para ajustar a una fecha especifica
Usar la funcin 2BH para obtener la fecha
Salvar el da de la semana
Restaurar la fecha actual
En este ejemplo, la fecha la fecha de la cual queremos el da de la semana est almacenada en tres campos
dato YEAR, MONTH y DAY. Una vez que el da es calculado este es copiado al campo dato
WEEKDAY. Estos datos estn declarados en el segmento de datos. Si la fecha especificada fuera
Diciembre 21 del 2002 estas seran las declaraciones:
YEAR
DW
MONTH DB
12
DAY
DB
WEEKDAY DB

2002
21
?

Aqu estn las instrucciones que calculan el da de la semana:


; calcular el da de la semana de una fecha especifica
; WEEKDAY <--- resultado (0-6)
; salvar la direccin actual
MOV
AH,2AH
INT
21H
PUSHA
; -- ajustar a la fecha especifica
MOV
CX,YEAR
MOV
DH,MONTH
MOV
DL,DAY
MOV
AH,2BH
INT
21H
; obtener el dato especifico
MOV
AH,2AH
INT
21H
; copiar el da al campo WEEKDAY
MOV
WEEKDAY,AL
; restaurar la fecha anterior
POPA
MOV
AH,2BH
INT
21H
El resultado es que WEEKDAY tiene un valor de 6 que significa que el da 21 de Diciembre del 2002 es
sbado.

17.10 Manejo de errores.

116

Muchas llamadas a funciones indican un error poniendo la bandera de acarreo a 1. En tales casos,
necesitas encontrar la naturaleza del error. La llamada a funcin 59H provee este servicio.
La llamada de funcin 59H requiere los siguientes parmetros de entrada:
AH <--- numero de llamada (59H)
AL <--- 0
Despus usa la llamada a funcin que seala un error, el programa puede probar a CF. Si CF ests puesta
a 1, el programa puede ejecutar la llamada 59H para obtener ms informacin. Algunas de las llamadas a
funcin regresan el cdigo de error en AX y CF. Sin embargo, estos son cdigos de error viejos, es ms
seguro usar los resultados de la funcin 59H.
Aqu est un ejemplo que usa la funcin 40H para escribir en un archivo. El salvar y restaurar el registro
DS en el segundo conjuntos de instrucciones ser explicada mas adelante.
; escribir al archivo
MOV
BX,FILE_HANDLE
LEA
DX,BUFFER
MOV
CX,COUNT
MOV
AH,40H
INT
21H
; Si hay un error , obtener la informacin del error y entonces llamar
; al procedimiento de error
JNC
L1
PUSH
DS
MOV
BX,0
MOV
AH,59H
INT
21H
POP
DS
CALL
ERROR
L1:
La llamada de funcin 59H regresa los siguientes parmetros de salida:
AX
BH
BL
CH

<--<--<--<---

El cdigo de error
La clase de error
La accin recomendada
El lugar

El lugar se refiere a la parte de la computadora donde ocurri el error.


Adems de los parmetros de salida, debes tener cuidado con esta funcin ya que no salva los valores de
los registros CL, DX, SI, DI, DS y ES. As antes de hacer la llamada a esa funcin, debes salvar a DS y a
otros registros importantes

17.11 Ejemplo del uso de interrupciones.

117

En algunas ocasiones puedes invocar a las interrupciones directamente. En est seccin te mostrare
tres ejemplos de interrupciones interesantes todas del BIOS. Las interrupciones de esta seccin son
simples en el sentido de que no necesitan entrada o salida. Sin embargo, muchas de las interrupciones del
DOS y de BIOS necesitan parmetros.
La primer interrupcin interesante es la 05H. Esta interrupcin copia el contenido de la pantalla a la
impresora, cuando presionas el Impr Pant. Puedes usar esta interrupcin para imprimir la pantalla dentro
de un programa. Antes de hacer esto asegrate que la impresora est lista. La salida est direccionada al
puerto LPT1.
; imprimir la pantalla
INT
05H
La segunda interrupcin es la 18H. La interrupcin detiene a DOS y ejecuta la versin rudimentaria de
BASIC que est almacenada en el ROM. (este es el casete bsico que inicia si enciendes la computadora
y el BIOS no puede encontrar la forma de arrancar el DOS).
Este servicio solo puede ser una curiosidad interesante; sin embargo puedes usar la imaginacin para
encontrar un uso para esto. Asegrate de hacer dos cosas: primero, si usas esta versin de BASIC, no
podrs salvar los programas a disco. Segundo, el nico modo de regresar a DOS es reiniciar la
computadora.
; cambiar al casete BASIC
INT
18H
La tercera interrupcin es la 19H. Esta interrupcin reinicia la computadora. Esta es til si quieres
reiniciar la mquina desde un programa. Este reinicio es abreviada y omite los siguientes pasos:
El sistema automticamente ejecuta un chequeo cuando inicias la mquina (un reseteo en fro)
Las operaciones de reset que son ejecutadas con Ctrl-Alt-Del (reseteo en caliente).
As la interrupcin 19H puede ser considerado como un reseteo en caliente.
Esto es bueno y malo, es bueno porque el reseteo en caliente es mas rpido, debido a que no ejecuta el
chequeo y las operaciones de reseteo, sin embargo este reseteo no funciona bajo algunas circunstancias,
como por ejemplo si algunos programas residentes estn cargados en memoria.
; ejecuta un reseteo en caliente
INT
19H

17.12 Terminar un programa.


Cuando un programa termina, regresa al DOS ejecutando la instruccin RET, la cual saca la
direccin de regreso de la pila, y salta a esa direccin. Ya que todos los programas son de tipo FAR, la
direccin de regreso debe consistir de la direccin del segmento y el offset.
La direccin de regreso debe ser empujada a la pila al principio del programa. Este trabajo es manejado
por las siguientes instrucciones:
118

; salvar la direccin del DOS


PUSH
DS
PUSH
0
El primer PUSH almacena la direccin del segmento; el segundo PUSH almacena el desplazamiento.
Cada vez que el programa se ejecuta, DOS coloca un rea de 256 bytes llamado el prefijo del segmento
del programa (PSP). El PSP es cargado en memoria y alineado al limite de un prrafo (16 bytes) en el
frente de tu programa, de ah el termino prefijo.
El PSP contiene una combinacin de informacin que DOS usa para ejecutar el programa. A menos que
necesites accesar los parmetros de la lnea de comandos o el ambiente de Dos puedes ignorar el PSP.
Despus de que el programa es cargado en memoria, DOS pone los registros DS y ES a la direccin del
prefijo de segmento. Esto significa que cada programa inicia con DS y ES apuntando al PSP. Las
primeras dos instrucciones del programa meten el valor de DS y 0 en la pila antes de modificar a DS. Esto
significa que el RET final regresa al inicio del PSP. El inicio del PSP contiene una instruccin de dos
bytes:
INT

20H

La interrupcin 20H ejecuta las tareas necesarias para terminar el programa y le da el control de nuevo a
DOS.
As, colocndose en el inicio del PSP que contiene la interrupcin 20H, DOS permite terminar el
programa con un simple RET. Este mtodo de terminacin fue diseado para ser simple, y muchas de las
veces es suficiente. Sin embargo, hay dos situaciones no usuales en las cuales podemos terminar el
programa de manera diferente. Primero, podemos mandar un cdigo de retorno al programa que llamo,
usando la llamada a funcin 4CH. Segundo puedes dejar un programa en memoria despus de que
termine. En este caso, usamos la llamada a funcin 31H.

17.13 Disear tu propio manejador de interrupcin: IRET.


Usualmente, una interrupcin es servida por un manejador de interrupcin que es parte del DOS o
del BIOS. Sin embargo, puedes modificar la tabla descriptiva de interrupcin para que apunte a tu propio
manejador de interrupcin. Esto da un mayor control sobre la interrupcin a ser servida.
Normalmente, no se debe hacer esto; de hecho muchos manejadores de interrupciones tratan con tareas
complejas y raramente necesitas cambiarlas. Sin embargo, puedes querer escribir tu propia rutina de
manejador, esta seccin y la siguiente explican esta tcnica.
Bsicamente, un manejador de interrupcin acta como un procedimiento de tipo FAR, cuando la
interrupcin es sealada, el procesador detiene el programa actual, salva las banderas y la direccin de la
siguiente instruccin en su propia pila, e invoca al manejador de interrupcin.
Un manejador de interrupcin acta como un procedimiento FAR. Sin embargo un manejador de
interrupcin usando la instruccin IRET (regreso de interrupcin) en lugar de la RET. Como sabes, la
instruccin RET regresa la direccin de retorno que fue empujada a la pila por la instruccin CALL. La
instruccin IRET restaura tambin el registro de banderas que fue empujado a la pila adelante de la
direccin de regreso. As, las funciones de la IRET son las siguientes:
119

Sacar la direccin de regreso (offset y direccin de segmento) fuera de la pila


Saca y restaura el registro de banderas de la pila
Salta a la direccin de regreso.
Adems de usar la instruccin IRET en lugar de la RET, hay otras diferencias entre el manejador y un
procedimiento regular.
Un manejador de interrupcin
No puede ser invocada por otras interrupciones (usando INT)
Debe preservar los valores de todos los registros excepto de aquellos que usa para pasar parmetros
(como en todo procedimiento)
En resumen, debes escribir un manejador de interrupcin de manera que pueda ser invocada cuando sea
causando errores o efectos laterales.
17.14 Modificar la tabla descriptiva de Interrupciones.
En orden de usa tu propio manejador de interrupcin, debes reemplazar la entrada apropiada en la
tabla descriptiva de interrupciones. En principio puedes hacer esto directamente (ya que la tabla inicia en
la locacin 0000H y cada entrada es de 4 bytes de longitud). Sin embargo, esta es una idea pobre que un
programa dependa de direcciones absolutas. (Esto es debido a que la tabla esta en una locacin diferente
cuando el procesador corre en modo protegido.)
En su lugar, DOS permite hacer este remplazo por ti. La llamada a funcin 25H provee este servicio.
Estos son los parmetros:
AL
DX
DS
AH

<--<--<--<---

numero de vector o entrada a ser examinada


offset del manejador de interrupcin
segmento de direccin del manejador de interrupcin
25H (el numero de llamada)

No hay parmetros de salida.


Aqu hay un ejemplo que ilustra estas tcnicas. El ejemplo reemplaza el manejador de interrupcin 5
(imprimir la pantalla) con un procedimiento que emite un beep.
Primero, aqu esta el procedimiento que emite un sonido. Los detalles sern explicados en el siguiente
capitulo. Sin embargo note que cada procedimiento salva y regresa los registros usando IRET.
; interrupcion que emite un sonido
BEEP
PROC
PUSHA
MOV
AL,0B6H
OUT
43H,AL
MOV
AX,3025
OUT
42H,AL
JMP
SHORT $+2
120

MOV
OUT
IN
MOV
OR
OUT
MOV

AL,AH
42H,AL
AL,61H
AH,AL
AL,03
61H,AL
CX,0FFFFH

L1:

BEEP

LOOP
L1
MOV
AL,AH
OUT
61H,AL
POPA
IRET
ENDP

Para usar este procedimiento como un manejador de interrupcin 5H, necesitas invocar la funcin 25H
con la salida de parmetros descrita a continuacin.
Un punto importante es que DS debe apuntar al segmento de direccin del procedimiento. Una vez que
BEEP esta en el segmento de cdigo, DS debe ponerse al valor del registro CS. Sin embargo no puedes
hacer esto directamente. Debes empujar el valor a la pila y despus sacar el valor a DS. Por supuesto,
debes salvar el valor original y restaurarlo despus de la llamada a funcin
Aqu estn las instrucciones:
; modifica el vector 5 para apuntar al procedimiento BEEP
; AL <-- 05H (el vector de interrupcion a ser manejado
; DX <-- offset del procedimiento BEEP
; DS <-- direccion de segmento del procedimiento BEEP
; AH <-- 25H (numero de llamada a funcin)
PUSH
DS
MOV
AL,05H
LEA
DX,BEEP
PUSH
CS
POP
DS
MOV
AH,25H
INT
21H
POP
DS
Una vez que estas instrucciones son ejecutadas, el manejador de interrupcin 5 ser el procedimiento
BEEP. Desde ahora, cada vez que ejecutes:
INT

5H

La computadora emitir un sonido en lugar de imprimir la pantalla.


Por supuesto, el nuevo manejador de interrupcin funcionara solo mientras el programa esta enejecucin.
Una vez que el programa termina, este manejador desaparece.
tienes dos opciones:
1. Si quieres que el manejador de interrupcin tiene un efecto permanente, puedes terminar el programa
121

de tal manera que quede residente en memoria. Esto es discutido en la siguiente seccin.
2. Si quieres que el nuevo manejador tenga un efecto solo durante el programa, debes salvar y restaurar la
la entrada original en la tabla descriptora de interrupciones.
Para hacer el manejador efectivo solo durante el programa, recuerde que cada entrada contiene la
direccin de segmento y un offset. Antes de poner el nuevo manejador, salva el segmento y offset
originales en dos campos dato (ORIGINAL_OFFSET y ORIGINAL_SEGADDR). Entonces al final del
programa, restaura la entrada con sus valores originales.
Para salvar los valores originales, usa la funcin 35H. Esta funcin examina la tabla descriptiva de
interrupciones y regresa el segmento de direccin y el offset que estn almacenados en una entrada
particular. Estos son los parmetros de entrada:
AL <-- numero de entrada de vector a ser examinado
AH <--- 25H el numero de llamada.
Los parmetros de salida son:
BX <-- offset del manejador de interrupcin
ES <-- segmento de direccin del manejador de interrupcin
Aqu estn los estatutos que hacen el trabajo. Primero, en el segmento de datos, define los campos dato
que deben guardar la direccin de segmento y el offset:
ORIGINAL_OFFSET
DW ?
ORIGINAL_SEGADDR DW ?
Segundo, dentro del segmento de cdigo, salva los valores originales y entonces modifica la tabla. Note
que estas instrucciones preservan los valores de Es y DS cuando es necesario.
; salva el contenido de la entrada en la tabla descriptiva de int. para la INT 5
; ORIGINAL_OFFSET <-- BX <-- offset
; ORIGIANL_SEGADDR <-- ES <-- direccin de segmento
PUSH
ES
MOV
AL,05H
MOV
AH,35H
INT
21H
MOV
ORIGINAL_OFFSET,BX
MOV
ORIGINAL_SEGADDR,ES
POP
ES
; modificar el vector INT 5 para apuntar al procedimiento BEEP
;
AL <--- 05H (vector de int a ser usada
;
DX <--- offset del procedimiento BEEP
;
DS <--- direccin de segmento del procedimiento BEEP
;
AH <--- 25H (numero de llamada a funcin)
PUSH
DS
MOV
AL,05H
LEA
DX,BEEP
PUSH
CS
POP
DS
122

MOV
INT
POP

AH,25H
21H
DS

Al final del programa, use la siguientes instrucciones para restaurar la entrada original en la tabla:
; modifica INT 5 para apuntar al manejador original
;
AL <--- 05H (vector a ser restaurado)
;
DX <--- offset original
;
DS <--- direccion de segmento original
;
AH <--- 25H (numero de llamada a funcin
PUSH
DS
MOV
AL,05H
MOV
DX,ORIGINAL_OFFSET
MOV
DS,ORIGINAL_SEGADDR
MOV
AH,25H
INT
21H
POP
DS
17.15 Crear software residente en memoria.
DOS provee un mecanismo para terminar un programa y dejarlo en memoria. El programa es
entonces considerado como una extensin permanente del DOS hasta que reinicias la computadora. Tal
programa es llamado residente en memoria. El uso ms comn para los programas residentes en memoria
es tener un manejador de interrupcin permanente.
Para terminar un programa y hacerlo residente, usa la funcin de DOS 31H. Los parmetros de entrada
son como sigue:
AL <--- codigo de retorno
DX <--- tamao del programa residente
AH <--- 31H (numero de llamada)
No hay parmetros de salida.
El cdigo de regreso es un valor que puede ser usado para pasar informacin al programa que llamo.
Usualmente el cdigo de retorno es puesto a cero para indicar que no hay errores y 1 para indicar algn
error.
El valor de DX indica cuanto del programa quedara residente. Ponga a DX al desplazamiento del primer
byte despus del fin del rea del residente. n otras palabras, DX debe apuntar al lugar en el cual DOS
puede cargar un programa.
La figura 17-1 muestra un programa que usa la llamada a funcin 35H. El ejemplo instala el
procedimiento BEEP como un manejador permanente a la interrupcin 5. Una vez que BEEP esta
instalado en memoria como un programa residente, puedes hacer que suene cada vez que presionas Impr
Pant. Si quieres hacer este cambio permanente, puedes ejecutar el programa de instalacin en el archivo
AUTOEXEC.BAT

17.16 Sobreflujo en aritmtica: INTO.


123

Hay dos tipos de interrupciones que son usadas para manejar las condiciones de sobreflujo: las
interrupciones 0 y 4. La interrupcin 0 es invocada automticamente cuando una operacin de divisin
producida por un sobreflujo. Esto puede ocurrir si el cociente es demasiado largo o el divisor es cero. La
interrupcin 0 despliega el mensaje
Divide overflow
y entonces termina el programa.
La interrupcin 4 es usado para manejar otras condiciones aritmticas de sobreflujo. Aqu hay una
instruccin especial, INTO para ejecutar esta interrupcin su formato es:
INTO
INTO examina la bandera de sobreflujo (OF): Si OF est puesta a 1, INTO invoca a la interrupcin 4; si
OF esta limpia a 0, INTO no hace nada. En otras palabras, INTO ejecuta la misma funcin que las
siguientes instrucciones:
; si la bandera de overflow esta puesta a 1 invocar a la interrupcion 4
JNO
L1
INT
4
L1:
Cuando reinicias la computadora, el manejador de la interrupcin 4 es una instruccin IRET. Esto la
interrupcin no hace nada. La intencin es que si es necesario, tu puedes escribir tu propio manejador de
condiciones de sobreflujo. Esto es un ejemplo de una instruccin INTO despus de un calculo aritmtico.
ADD
INTO

AX,BX

Otra alternativa es escribir un procedimiento de error que se llama si CF esta puesta a 1, por ejemplo:
ADD
JNO
CALL

AX,BX
L1
ERROR_PROC

L1:
La ventaja de usar INTO es que provee un mtodo simple para probar el sobreflujo despus de cada
calculo. La desventaja es que tu tienes que disear y programar tu propio manejador de interrupcin. Otra
desventaja es que INTO es til solo si trabajas con nmeros con signo. Si estas usando nmeros sin
signo, puedes detectar el sobreflujo con las instrucciones JC y JNC.
Figura 17-1 Programa para instalar un manejador residente.
PAGE
58,132
;------------------------------------------------------------------------------;
PONER LA INTERRUPCION 5
;
;
Proposito:
;
para instalar un manejador de int. residente en memoria
;
para la interrupcion 5
124

;------------------------------------------------------------------------------; ajustar el titulo y el conjunto de instruccion


TITLE
Set interrupt 5 -- poner la 5 a Beep
.286
;---------------------------------------------------------- segmento de PILA
SSEG
SEGMENT
STACK
DB 32 DUP(STACK---)
SSEG
ENDS
;------------------------------------------------------- segmento de DATOS
DSEG
SEGMENT
MESSAGE
DB Interrupcion 5 instalada y lista,0DH,0AH,$
DSEG
ENDS
;------------------------------------------------------ segmento de CODIGO
CSEG
SEGMENT
ASSUME CS:CSEG, SS:SSEG, DS:DSEG
PAGE
;-------------------------------------------------------------------------------;
MAIN
;
;
Proposito:
;
instalar la interrupcion 5 con el procedimiento BEEP
;
Entrada:
;
-ninguna;
Salida:
;
-un mensaje a pantalla
;
Procedimientos:
;
BEEP
;--------------------------------------------------------------------------------; procedimiento MAIN
MAIN
PROC

FAR

; salvar la direccin de regreso a DOS


PUSH
DS
PUSH
0
; actualizar el segmento de datos
MOV
AX,DSEG
MOV
DS,AX
; modificar el vector INT 5 para que apunte a BEEP
PUSH
DS
MOV
AL,05H
LEA
DX,BEEP
PUSH
CS
POP
DS
MOV
AH,25H
INT
21H
125

POP

DS

; despliega el mensaje para indicar que ya se modifico el vector


LEA
DX,MESSAGE
MOV
AH,09H
INT
21H
; regresa a DOS y queda residente
MOV
AL,0
LEA
DX,END_OF_PROGRAM
MOV
AH,31H
INT
27H
; fin del procedimiento MAIN
MAIN
ENDP
PAGE
;--------------------------------------------------------------------------------;
BEEP
;
;
Proposito:
;
un manejador de interrupcion que emite un beep
;
Entrada,salida y procedimientos:
;
-ninguno;--------------------------------------------------------------------------------; procedimiento BEEP
BEEP
PROC
; salvar los registros
PUSHA
; hacer el beep
MOV
OUT
MOV
OUT
JMP
MOV
OUT
IN
MOV
OR
OUT
MOV
L1:
LOOP
MOV
OUT

AL,0B6H
43H,AL
AX,3025
42H,AL
SHORT $+2
AL,AH
42H,AL
AL,61H
AH,AL
AL,03
61H,AL
CX,0FFFFH
L1
AL,AH
61H,AL

; restaurar los registros


POPA
126

; regresar de la interrupcion
IRET
;fin de BEEP
BEEP
ENDP
; locacin despues del area residente
END_OF_PROGRAM:
; fin del segmento de codigo
CSEG
ENDS
;-----------------------------------------------------------------fin de programa
END
MAIN

17.17 Inhibir interrupciones: CLI y STI


En raras ocasiones, puedes inhibir al procesador para que no responda a las interrupciones. Por
ejemplo, digamos que una secuencia de instrucciones depende de un timing exacto. Si una interrupcin
ocurre mientras la instrucciones se est ejecutando, el timing puede romperse.
Para controlar la respuesta del procesador las interrupciones, puedes limpiar o poner la bandera de
interrupcin (IF): La instruccin CLI pone la bandera a 0; la instruccin STI pone la bandera a 1. El
formato es simple:
CLI
STI
Cuando la bandera de interrupcin esta puesta a 1, el procesador sirve las interrupciones. Este es el curso
normal de eventos. Cuando la bandera de interrupcin esta puesta a 0, el procesador ignora todas las
interrupciones excepto las no enmascarables o NMI.
El propsito de las NMI es sealar una interrupcin tan importante que no puede ser ignorada bajo
ninguna circunstancia, por ejemplo un error de hardware.
Si inhibes las interrupciones debes asegurarte de activarlas antes de salir del programa en ensamblador o
en caso contrario dejaras inhabilitadas las interrupciones para el sistema y otros programas.
{_____________o___________}
CAPITULO 18 ENTRADA/SALIDA
La entrada/Salida o I/O, se refiere a mover datos de y desde los archivos y dispositivos. Muchas de las
veces, la entrada viene desde el teclado o un archivo de disco, y sale a la pantalla, la impresora o a otro archivo.
I/O es usualmente, la parte ms compleja de cualquier sistemas de computadora, debido a que actualmente los
programas que leen y escriben deben mantener un control exquisito sobre los dispositivos, y cada dispositivo tiene
sus propias peculiaridades que deben ser respetadas.

127

Afortunadamente, los servicios de llamada a funcin de DOS hacen casi todo el trabajo por ti. En este captulo, te
presentar las formas ms importantes de ejecutar I/O. Estas descripciones y ejemplos te mostrarn como hacer el
I/O de la mayora de tus programas.
Nuevos Trminos
Input/Output. Mover datos entre archivos y dispositivos ; tambin llamado I/O.
Abrir un archivo. Una instruccin de DOS para preparar un archivo para su uso.
Cerrar un archivo. Una seal de DOS que indica que un programa a dejado de usar un archivo.
Manejador (Handle). Un nmero de 16-bits que identifica un archivo abierto.
Buffer. Un rea usada para mantener que han sido ledos o que van a escribirse.
Cadena ASCIIZ. Una secuencia de caracteres seguido por un byte con el valor 00H.
Apuntador a un archivo. En un archivo abierto, la localizacin del siguiente byte a ser procesado.
Atributo. Una caracterstica de un archivo que describe cuando es o no un archivo de solo lectura, oculto, sistema,
o archivo.
Archivo de solo lectura. Un archivo que puede ser ledo pero no modificado.
Archivo oculto. Un archivo que no es desplegado durante una bsqueda normal en directorio.
Archivo de sistema. Un trmino anacrnico, ya no se usa.
Archivo de archivo. Un archivo que ha sido respaldado por los comandos de DOS BACKUP o XCOPY.
ANSI.SYS Un manejador de dispositivo que te permite un control sobre las operaciones del teclado y la pantalla.
Puerto. Una conexin a travs de la cual pasan datos de o hacia un dispositivo.

18.1 Los niveles de I/O


Para comprender el I/O, es til pensar que la computadora opera a niveles diferentes de abstraccin. En el nivel ms
bajo, un programa se comunica directamente con un dispositivo. En este nivel, el programa puede mandar y recibir
informacin byte por byte. Tal programa es invariablemente complicado debido a todos los detalles de
almacenamiento del I/O. En particular el programa debe comprender las peculiaridades del dispositivo.
Em el nivel medio, un programa usa el BIOS para manejar los detalles de bajo nivel. Como explique en el captulo
17, el BIOS contiene manejadores de dispositivos cuyo trabajo es proveer una interfase estndar para los diferentes
dispositivos. Esto remueve un poco de trabajo de tus programas porque ya no hay que tratar con los detalles de
cada uno de los dispositivos. Sin embargo, tus programas deben mantener la organizacin lgica de tus datos.
En el nivel ms alto, un programa usa las llamadas a funcin de DOS. Estos servicios proveen una interfase
sofisticada para I/O, similar a lo que ofrecen los lenguajes de alto nivel. En este nivel, DOS permite tratar con
archivos o dispositivos llamados entidades que pueden ser manipulados de manera estndar. De hecho, puedes
tratar a un dispositivo como si fuera un tipo de archivo especial.
Obviamente, la manera ms fcil de programar I/O es usar las llamadas a funciones. De hecho, esto es un intento de
IBM y Microsoft de que uses las funciones la mayora de las veces. Si lo haces as, est garantizado que tus
128

programas sigan funcionando bajo futuras versiones de DOS. Si no, IBM o Microsoft no asegura que los detalles de
medio o bajo nivel de I/O sigan sin cambios.
Ms an, si quieres que tus programas funcionen con otro software, el mejor modo son las llamadas a funcin. Por
ejemplo, los programas que dan salida en bajo nivel no pueden tomar ventaja de las facilidades ofrecidas por
Microsoft Windows.
As, puedes usar la siguiente gua : Usa llamadas a funcin para ejecutar I/O excepto cuando las llamadas sean
inadecuadas. El ejemplo ms comn para no usar llamadas a funciones es que necesites un programa que escriba a
la pantalla rpidamente. Es tal caso la llamada a funcin puede ser demasiado lenta para tu programa.

18.2 Conceptos bsicos


Existen varios conceptos bsicos que son comunes en las llamadas a funcin de I/O. Primero, antes de trabajar con
un archivo, debes abrirlo. Cuando terminas de usarlo debes cerrarlo.
Cuando abres un archivo, debes especificar el path y el nombre del archivo. Dos regresa un nmero de 16-bits
llamado manejador de archivo o manejador. Una vez que haces esto, puedes referirte al archivo solo por su
manejador y DOS se encarga de todos los detalles. (Este sistema fue copiado del sistema operativo UNIX y del
lenguaje de programacin C).
Cerrar un archivo seala a DOS que el archivo ya no va a ser usado. Esto permite a DOS encargarse de cualquier
requerimiento de control interno. Por esto es esencial que cierres cada archivo que abras ; o de otra manera corres el
riego de perder datos.
Cundo lees o escribes datos, debes tener un rea para mantenerlos. Esta rea es llamada buffer. Con una operacin
de lectura DOS pone datos en el buffer. Con una operacin de escritura DOS obtiene los datos del buffer.
Para definir un buffer, apartamos espacio en el segmento de datos, por ejemplo :
BUFFE

DB

256 DUP( ?)

Para cualquiera de las llamadas a funcin, necesitas especificar un string que mantenga informacin. El string debe
tener un formato llamado ASCIIZ.
Un string ASCIIZ consiste de una secuencia de caracteres seguidos por un byte con el valor 00H. (ASCIIZ
significa caracteres seguidos de un cero). Aqu hay dos ejemplos de estatutos que definen una cadena ASCIIZ :
INFILE
DB
C :\WORK\INPUT.TXT,00H
NUMBER DB
5,00H
Cuando metes comandos de Dos desde el teclado, debes usar el carcter \ para separar las partes del path. Sin
embargo, cuando usas un ASCIIZ para un path, puedes usar los caracteres \ o /. Por ejemplo, el path en el siguiente
estatuto puede funcionar tambin como sigue :
INFILE

DB

C :/WORK/INPUT.TXT,00H

18.3 Los manejadores estndar


Cuando las llamadas a funcin para hacer I/O, DOS te permite usar a los archivos o dispositivos de manera
similar. Todo lo que tienes que hacer es especificar el manejador y Dos se encarga de los detalles. As, usas la
misma funcin para escribir a la pantalla o para escribir a un archivo de disco.

129

Para muchos archivos, DOS usa el manejador cuando abres al archivo. Como conveniencia, Dos asigna 5
manejadores estndar que puedes usar para leer o escribir a los dispositivos usados comnmente. Estos
manejadores se muestran en la tabla 18-1. DOS abre o cierra estos manejadores automticamente, as que siempre
estn disponibles.
Los primeros tres manejadores se refieren al teclado y a la pantalla. Para ller del teclado, usa la entrada estndar
(handle 0000H). Para escribir a la pantalla, usa la salida estndar (handle 0001H) o el error estndar (00002H). La
entrada y salida estndar pueden ser redirigidas a otro archivo o dispositivo. El error estndar no puede ser
redirigido.
Tabla 18-1 Manejador Uso
Dispositivo por omisin
0000H
Entrada estndar CON :
0001H
Salida estndar CON :
0002H
Error estndar
CON :
0003H
Auxiliar estndar AUX :
0004H
Impresora estndar
PRN :
Generalmente, puedes escribir usando la salida estndar. Sin embargo, en ciertas ocasiones necesitas escribir datos
que deben desplegarse ; esto es, se tendrs que redirigirlos ; los mensajes de error o preguntas importantes son dos
ejemplos. En tales casos, escribe los datos al error estndar.
El Auxiliar estndar se refiere al primer dispositivo serial ; la impresora estndar se refiere al primer dispositivo en
paralelo. Puedes imprimir datos mandndolos a la impresora estndar (handle 0004H).
Un modo conveniente de trabajar con estos manejadores es usar iguales para definir nombres.
; manejadores de archivos estndar
KEYBOARD EQU 0000H
DISPLAY EQU 0001H
ST_ERROR
EQU 0002H
AUX
EQU 0003H
PRINTER EQU 0004H
Ahora puedes referirte al manejador por su nombre, haciendo tus programas fciles de comprender, por ejemplo :
MOV

BL,DISPLAY

18.4 Abrir un archivo


Para abrir un archivo, usa la funcin DH. Aqu estn los parmetros de entrada :
AL
DS :DX
AH

tipo de acceso
direccin del ASCIIZ que contiene el path y el nombre del
archivo a abrir
3DH

El valor de AL especifica como ser el acceso al archivo. Usa los siguientes valores :
Solo lectura
00H
Solo escritura
01H
Lectura/escritura 02H
Estos valores pueden ser diferentes si se usa subprocesamiento o una red.
Los parmetros de salida son los siguientes :
130

AX
CF

Manejador
0 (no hay error) 1 (error)

Si la bandera de acarreo est puesta a 1, usa la funcin 59H para obtener informacin acerca del tipo de error.
Aqu hay un ejemplo que abre el archivo C :\WORK\FILE :TXT para lectura y escritura. El ejemplo usa los
siguientes campos de datos :
NAME
Path y nombre del archivo a ser abierto
HANDLE Nombre del manejador cuando el archivo est abierto
En el segmento de datos define
FILE
DB
HANDLE DW

C :\WORK\FILE.TXT,00H
?

Estas son las instrucciones para abrir el archivo :


; abrir el archivo para lectura/escritura
MOV
AL,02H
LEA
DX,FILE
MOV
AH,3DH
INT
21H
; si hubo una falla : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
L1 :
; copiar el manejador a HANDLE
MOV
HANDLE,AX
Un programa puede tener un mximo de 20 archivos abiertos a la vez. Debido aque hay 3 manejadores predefinidos
(CON :, AUX :, y PRN:), esto deja a 17 para tus propsitos. Sin embargo, por omisin DOS permite solo 8
archivos abiertos. Si necesitas ms, usa el comando FILES en el CONFIG.SYS para especificar un nmero mayor.

18.5 Cerrar un archivo


Para cerrar un archivo, usa la funcin 3H. Los parmetros de entrada son
BX
AH

Manejador
3EH

El parmetro de salida es
CF

0 (no hay error) 1 (error)

Si CF est puesta a 1, usa la funcin 59H para obtener informacin acerca del tipo de error.
Aqu hay un ejemplo que cierra un archivo. El campo HANDLE contiene al manejador.
;cerrar un archivo
MOV
MOV
INT

BX,HANDLE
AH,3EH
21H
131

; si no hay xito : llamar a ERROR


JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1 :

18.6 Leer de un archivo o dispositivo


Para leer un archivo, usa la funcin 3FH. Los parmetros de entrada son
BX
CX
DS :DX
AH

Manejador
Nmero de bytes a leer
Direccin del buffer de entrada
3F

Los parmetros de salida son


AX
CF

Nmero de bytes que fueron ledos


0 (no hay error) 1 (error)

Si CF est puesta a 1, usa la funcin 59H para obtener informacin acerca del tipo de error.
Tambin pudes especificar como sern ledos algunos bytes, aqu no hay garanta de que DOS satisfaga tu
peticin.De hecho puede ser que algunos bytes queden dentro de un archivo. Tambin cuando lees del teclado
(handle 0000H), DOS podr leer solo una lnea a la vez
As, despues de la llamada a funcin, puedes comparar Ax contra CX para ver si los bytes suficientes fueron ledos.
Si un programa trata de empezar la lectura al final del archivo de disco, DOS regresar un valor de 0 en AX.
Veamos estos dos ejemplos. El primer ejemplo lee una cadena del teclado. Cuando un programa lee desde el
teclado, DOS intenta leer tantos caracteres como pide el programa. Sin embargo Dos no puede leer pasado en fin de
lnea. Cuando el usuario hace una entrada, marca el fin de lnea presionando ENTER, el cual es trasladado como
dos bytes
0DH, 0AH
Existen dos cdigos ASCII para el retorno de carro y la lnea de alimentacin, respectivamente. As, si el usuario
teclea 12345 y entonces presiona ENTER, se leern siete bytes de datos.
Aqu hay un ejemplo que lee 30 bytes de datos desde el teclado. Elejemplo usa los siguiente campos dato :
KEYBUFF
KEYBOARD
L_KEYBUFF

Buffer de entrada
Manejador para la pantalla
Longitud del buffer de entrada

En la seccin de iguales, define


KEYBOARD

EQU 0001H

En el segmento de datos, define


KEYBUFF DB 30 DUP( ?)
L_KEYBUFF EQU $-KEYBUFF
132

Aqu estn las istrucciones


; leer un string del teclado
MOV
BX,KEYBOARD
MOV
CX,L_KEYBUFF
LEA
DX,KEYBUFF
MOV
AH,3FH
INT
21H
El segundo ejemplo lee de un archivo de disco. El ejemplo usa los siguientes campos dato :
HANDLE El manejador del archivo
COUNT El nmero de bytes a leer
INBUFF El buffer de entrada
Si DOS no lee el nmero de bytes solicitados, el ejmplo salta a la etiqueta END_OF_FILE.
; leer de un archivo
MOV
BX,HANDLE
MOV
CX,COUNT
LEA
DX,INBUFF
MOV
AH,3FH
INT
21H
; si no hubo xito : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1 :
; si es fin de archivo : salta a END_OF_FILE
CMP
AX,CX
JB
END_OF_FILE

18.7 Escribir a un archivo o dispositivo


Para escribir a un archivo, usa la llamada a funcin 40H. Los parmetros de entrada son
BX
CX
DS :DX
AH

Manejador
Nmero de bytes a ser escritos
Direccin del buffer de salida
40H

Los parmetros son


AX
CF

Nmero de bytes que son escritos


0 (no hay error) 1 (error)

Si CF est puesta a 1, usa la funcin 59H para obteber informacin acerca del tipo de error.
Despus de la llamada a funcin, puedes comparar AX con CX para asegurarte que todos los bytes han sido
escritos. Si AX no es igual a CX, ocurri un error. Usualmente esto significa que el programa est escribiendo un
archivo a un disco lleno.

133

Aqu hay dos ejemplos. El primero escribe un mensaje a la pantalla, puedes mover el cursor al principio de la
siguiente lnea escribiendo los bytes
0DH, 0AH
Estos son los cdigos del retorno de carro y de alimentacin de lnea, respectivamente.
El primer ejemplo usa los siguiente campos de datos :
CR
LF
DISPLAY
MESSAGE
L_MESSAGE

Cdigo del retorno de carro


Cdigo de alimentacin de lnea
Manejador para la pantalla
El mensaje
Longitud del mensaje

En la secin de iguales, define


CR
EQU 0DH
LF
EQU 0AH
DISPLAY EQU 0001H
En la seccin de datos, define
MESSAGE
L_MESSAGE

DB
EQU

Este es un mensaje.,CR,LF
$-MESSAGE

Estas son las instrucciones :


; escribe un mensaje a la pantalla
MOV
BX,DISPLAY
MOV
CX,L_MESSAGE
LEA
DX,MESSAGE
MOV
AH,40H
INT
21H
El segundo ejemplo escribe a un archivo de disco. El ejemplo usa los siguientes campos dato :
HANDLE
COUNT
OUTBUFF

Manejador a un archivo de disco


Nmero de bytes a escribir
Buffer de salida

Si DOS no escribe el nmero pedidos de bytes, el progranma llama al procedimento DISK_FULL.


; escribe a un archivo
MOV
BX,HANDLE
MOV
CX,COUNT
LEA
DX,OUTBUFF
MOV
AH,40H
INT
21H
; Si no hubo xito : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1 :
; si el disco est lleno : llama a DISK_FULL
CMP
AX,CX
134

JE
CALL

L2
DISK_FULL

L2 :

18.8 Mover un apuntador a archivo


Para cada archivo abierto, DOS mantiene un apuntador a archivo. El apuntador de archivo contiene la
locacin al siguiente byte del archivo a ser procesado.Siempre que un programa lee o escribe en un archivo, DOS
examina el apuntador del archivo para determinar dnde empezar la operacin.
Cuando un programa abre un archivo, DOS pone el apuntador al archivo al primer byte del archivo, el byte 0. Cada
vez que el programa lee o escribe, DOS actualiza el apuntador.
Por ejemplo, si el apuntador al archivo est en el byte 0 y el programa lee 100 bytes, DOS actualiza el apuntador al
byte 100. Si el programa entonces escribe 200 bytes ms, DOS empieza en el byte 100 y mueve el apuntador al
byte 300.
Puede mover el apuntador a una locacin especfica usando la llamada a funcin 42H. Los parmetros de entrada
son
AL
Locacin en el cual moverse
BX
Manejador
CX:DX
Nmero de bytes a moverse
AH
42H
Los parmetros de salida son
DX:AX
Nueva locacin del apuntador al archivo
CF
0 (no hay error) 1 (hay error)
Si CF est puesta a 1, usa la funcin 59H para obteber informacin acerca del tipo de error.
Como entrada, DOS consider a CX y DX para formar un registro grande que contenga un nmero sin signo de 32
bits. Como salida, DX y AX contienen un nmero de tipo similar. Esto te permite usar archivos grandes que puedes
especificar con nmreos entre 0 y 4,294,967,295.
Si trabajas con archivos no mayores de 65,536 (64 K) bytes, el valor de entrada puede caber enteramente en DX.
En este caso, pon CX a 0. Despus de la operacin tendr un 0 y el valor de salida completo estar en AX.
Los valores de entrada en AL describen la posicin inicial del apuntador a archivo. Las posibilidades son las
siguientes.
AL=0
AL=1
AL=2

Inicial al principio del archivo


Inicia desde la posicin actual al apuntador del archivo
Inicia desde el fin del archivo

Para moverte al principo del archivo, pon AL=0 y CX :DX=0. Para moverte al fin de archivo, pon AL=2 y
CX:DX=0.Para encontrar la longitud del archivo, mueve el apuntador al final del mismo y examina la salida de
DX:AX.
Aqu hay algunos ejemplos. Los ejemplos usan el siguiente campo dato.
HANDLE

Manejador del archivo


135

El primer ejemplo mueve el apuntador hacia adelante 100 bytes


; mueve el apuntador 100 lugares adelante
MOV
AL,1
MOV
BX,HANDLE
MOV
CX,0
MOV
DX,100
MOV
AH,42H
INT 21H
; Si hubo error : llama a ERROR
JNC L1
MOV
AH,59H
INT 21H
CALL
ERROR
L1 :
El segundo ejemplo mueve el apuntador de archivo al principio del mismo.
; mueve el apuntador al inicio del archivo
MOV
AL,0
MOV
BX,HANDLE
MOV
CX,0
MOV
DX,0
MOV
AH,42H
INT 21H
; Si no hubo xito : llama a ERROR
JNC L1
MOV
AH,59H
INT 21H
CALL
ERROR
L1 :
Este ltimo ejemplo encuentra el tamao de un archivo y entonces copia los valores al campo FILE_VALUE.
; Encuentra el tamao del archivo
MOV
AL,2
MOV
BX,HANDLE
MOV
CX,0
MOV
DX,0
MOV
AH,42H
INT 21H
; si no hubo xito : llama a ERROR
JNC L1
MOV
AH,59H
INT 21H
CALL
ERROR
L1 :
; copia el tamao del archivo a FILE_SIZE
MOV
FILE_SIZE,AX
18.9 Examinar y modificar los atributos de un archivo
Cada archivo de disco tiene una entrada en un directorio. Esta estrada contiene la siguente informacin acerca
del archivo.
El nombre del archivo y la extensin.
136

La hora y la fecha en que el archivo fue modificado la ltima vez.


La locacin en el disco dnde empieza el archivo.
El tamao del archivo.
Los atributos del archivo.
Los atributos describen si el archivo es o no archivo de solo lectura, oculto, systema o de archivo. Un archivo
puede ser cualquier combinacin de estos caracteres.
Un archivo de solo lectura puede ser ledo pero no modificado.Si un archivo contiene informacin importante,
puedes hacerlo de solo lectura solo por proteccin.
Un archivo oculto no es desplegado durante la bsqueda normal de directorios. Usualmente no hay razones para
esconder un archivo. Sin embargo, los dos archivos de sistema de DOS, IBMDOS.COM y IBMBIO.COM, estn
ocultos as que nunca los ves en el desplegado de directorios. (Estos archivos son de solo lectura.)
Los atributos de archivos de sistema es un anacronismoque ya no se usa. Esto era usado originalmente en el sistema
operativo CP/M (el antecesor de DOS).
Uno de tipo archivo es aquel que ha sido almacenado como copia de seguridad por los comandos de DOS
BACKUP y XCOPY.
Para examinar o modificar los atributos de un archivo desde un programa, usa la llamada a funcin 43H. Los
parmetros de entrada son
AL
Tipo de servicio solicitado
CX
Nuevos atributos
DS:DX
Direccin del string ASCIIZ que contiene el path o el nombre
del archivo.
AH
43H
Los parmetros de salida son
CX
CF

Atributos actuales
0 (no hay error) 1 (error)

Si CF est puesta a 1, usa la funcin 59H para obteber informacin acerca del tipo de error.
El valor de entrada en el control AL determina que servicio ser provisto.
Poner AL a 0 examina los atributos actuales
Poner AL a 1 modifica los atributos actuales
Si pones AL a 0, DOS regresa los atributoa actuales en CX. Aunque CX no es necesario ponerlo como entrada. Si
pones AL a 1, DOS fija los atributos definidos en CX.
Los atributos son descritos usando 3 de 16 bits de CX. De izquierda a derecha, los bits estn numerados
15,14,13,12,11,10,9,8,7,6,5,4,3,2,1, y 0. Los bits que son usados para los atributos son 0,1, y 5. Estos son
mostrados en la tabla 18-2.
Tabla 18-2 Los bits de los atributos
Bit 0 :
0
No de solo lectura
1
Solo lectura
Bit 1 :
0
No oculto
137

1
Bit 5 :

0
1

Oculto
No de archivo
Archivo

Los otros bits de CX no son usados para los atributos. Cuando examinas los atributos de un archivo, debes ignorar
estos bits. Cuando modificas los atributos estos deben estar puestos a 0.
Aqu estn dos ejemplos que usan la llamada a funcin 43H. Estos ejemplos usan el campo dato.
FILE

Path o nombre del archivo

El primero pone los atributos del archivo como oculto, de solo lectura, de no archivo :
; poner los atributos del archivo
; no de archivo, oculto, de solo lectura
MOV
AL,1
MOV
CX,0000000000100011B
LEA
DX,FILE
MOV
AH,43H
INT
21H
; si hubo xito : llama a error
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1 :
El listado siguiente examina los atributos del archivo. Si el archivo est oculto, el ejemplo llama al procedimineto
HIDDEN.
; examina los atributos del archivo
MOV
AL,0
LEA
DX,FILE
MOV
AH,43H
INT
21H
; Si no hubo xito : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1 :
; si el archivo est oculto : llama a HIDDEN
TEST
CX,0000000000000010B
JZ
L2
CALL
HIDDEN
L2 :

18.10 Crear un nuevo archivo


Para crear un nuevo archivo, usa la llamada a funcin 5BH. Los parmetros de entrada son
CX
Atributos del nuevo archivo
DS:DX
Direccin del ASCIIZ que contiene el path o el nombre del
archivo
AH
5BH
138

Los parmetros de salida son


AX
CF

Manejador del nuevo archivo


0 (no hubo error) 1 (error)

Si CF est puesta a 1, usa la funcin 59H para obteber informacin acerca del tipo de error.
Cuando usas est llamada a funcin para crear un archivo, DOS checa si el archivo ya existe. Si es as DOS manda
una seal de error.
Aqu hay un ejemplo que crea un archivo con estos atributos : no de tipo archivo, no oculto, no de solo lectura. El
ejemplo usa los siguientes campos dato :
FILE
El path o el nombre del archivo a crear
HANDLE El manejador posible para el nuevo archivo
Aqu estn las instrucciones :
; crear un nuevo archivo
MOV
CX,0000000000100000B
LEA
DX,FILE
MOV
AH,5BH
INT
21H
; si hay error : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1 :
; copia el manejador a HANDLE
MOV
HANDLE,AX

18.11 Abrir un archivo para salida


Para abrir un archivo, usualmente usas la llamada a funcin 3DH. Sin embargo, si deseas usar el archivo
como salida, existe una llamada a funcin especial, 3CH. Est funcibn es una combinacin de 3DH (abrir) y 5BH
(crear). As es como funciona : Si el archivo existe, DOS lo abre y ajusta su tamao a 0. Si el archivo no existe,
DOS crea uno nuevo. Los parmetros de salida son
CX
Atributos del archivo
DS:DX
Direccin del ASCIIZ que contiene el path o el nombre del
archivo
AH
3CH
Los parmetros de salida son
AX
CF

Manejador del nuevo archivo


0 (no error) 1 (error)

Si CF est puesta a 1, usa la funcin 59H para obteber informacin acerca del tipo de error.
NOTA : Sea cuidadoso con est funcin; porque puede destruir el contenido de un archivo existente.

139

Aqu hay un ejemplo que abre un archivo con estos atributos, no de archivo, no de solo lectura, no oculto. El
ejemplo usa los siguientes campos dato.
FILE
Path o nombre del archivo que contiene el archivo de salida
HANDLE Posible manejador para el archivo
Estas son las instrucciones :
; Abrir un archivo para salida
MOV
CX,0000000000100000B
LEA
DX,FILE
MOV
AH,3CH
INT
21H
; si hubo error : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1 :
; Copiar el manejador a HANDLE
MOV
HANDLE,AX

18.12 Un ejemplo prctico : Copiar del teclado a la impresora


Est secin y la siguiente contienen dos ejemplos que usan manejadores de archivos. Los ejemplos demustran
como combinar la llamadas a funcin de E/S para producir programas tiles. Para ser breves los programas no
comtemplan el manejo de errores, sin embargo esto no debe hacerse en lo posible.
EL primer ejemplo lee datos del teclado y escribe los datos a la impresora directamente. El ejemplo usa los
siguientes campos dato :
KEYBOARD
Manejador de la entrada estndar
PRINTER
Manejador de la impresora estndar
BUFFER
El buffer de lectura/escritura
L_BUFFER
Longitud del buffer
BYTES_READ
El nmero de bytes ledos desde el teclado
En la seccin de iguales, defina
KEYBOARD
PRINTER

EQU 0000H
EQU 0004H

En el segmento de datos, defina


BUFFER
DB 80 DUP( ?)
L_BUFFER
EQU $-BUFFER
BYTES_READ
?
La lgica es la siguiente :
REPEAT
lee un string del teclado
140

s hay fin de archivo entonces termina el ciclo


escribir la cadena en la impresora
UNTIL (fin-de-archivo)
El usuario marca el fin de archivo presionando F6-ENTER al principio de la lnea.
NOTA : Cuando un programa lee desde el teclado, F6 es lo mismo que CTRL-Z, el fin de archivo estndar.
Aqu estn las instrucciones :
; lee una cadena del teclado
READ_STRING:
MOV
BX,KEYBOARD
MOV
CX,L_BUFFER
LEA
DX,BUFFER
MOV
AH,3FH
INT
21H
MOV
BYTES_READ,AX
; si se leyeron 0 bytes, se acaba el ciclo
CMP
BYTES_READ,0
JE
FINISHED
; escribe la cadena a la impresora
MOV
BX,PRINTER
MOV
CX,BYTES_READ
LEA
DX,BUFFER
MOV
AH,40H
INT
21H
; leer la siguiente cadena
JMP
READ_STRING
FINISHED:

18.13 Un ejemplo prctico : Hacer una copia de un archivo de disco


El ejemplo de esta seccin copia un archivo (el archivo de entrada) a otro (el archivo de salida). EL archivo
de salida es abierto usando la llamada a funcin 3CH. As si el archivo ya existe esta ser reemplazado.
El ejemplo usa los siguientes campos dato :
BUFFER
El buffer de lectura/escritura
BYTES_READ
El nmero de bytes a leer
IN_FILE
El nombre del archivo de entrada
IN_HANDLE
El manejador del archivo de entrada
OUT_FILE
El nombre del archivo de salida
OUT_HANDLE El manejador del archivo de salida
En el segmento de datos, declare
BUFFER
DB
BYTES_READ
IN_FILE
DB
IN_HANDLE
OUT_FILE
OUT_HANDLE DW

4096 DUP( ?)
DW ?
C:\WORK\INPUT,00H
DW ?
DB C:\WORK\OUTPUT,00H
?

(Puedes escoger el tamao del buffer para optimizar el programa). La lgica es la siguiente :
141

abrir el archivo de entrada


abrir el archivo de salida
REPEAT
leer del buffer de entrada
si (fin-de-archivo) terminar el ciclo
escribir en el archivo de salida
UNTIL (fin-de-archivo)
cerrar el archivo de entrada
cerrar el archivo de salida
aqu estn las instrucciones :
; abrir el archivo de entrada y copiar el manejador a IN_HANDLE
MOV
AL,02H
LEA
DX,IN_FILE
MOV
AH,3DH
INT
21H
MOV
IN_HANDLE,AX
; abrir el archivo de salida y copiar el manejador a OUT_HANDLE
MOV
CX,0000000000100000B
LEA
DX,OUT_FILE
MOV
AH,3CH
INT
21H
MOV
OUT_HANDLE,AX
; leer del archivo de entrada
READ:
MOV
BX,IN_HANDLE
MOV
CX,SIZE BUFFER
LEA
DX,BUFFER
MOV
AH,3FH
INT
21H
MOV
BYTES_READ,AX
; si se leyeron 0 bytes fin del ciclo
CMP
BYTES_READ,0
JE
FINISHED
; escribir al archivo de salida
MOV
BX,OUT_HANDLE
MOV
CX,BYTES_READ
LEA
DX,BUFFER
MOV
AH,40H
INT
21H
; leer ms
JMP
READ
FINISHED :
; cerrar el archivo de entrada
MOV
BX,IN_HANDLE
MOV
AH,3EH
INT
21H
; cerrar el archivo de salida
MOV
BX,OUT_HANDLE
MOV
AH,3EH
INT
21H

18.14 Borrar un archivo


142

Para borrar un archivo, usa la llamada a funcin 41H. Estos son los parmetros de entrada :
DS:DX
AH

Direccin del ASCIIZ que contiene el path o elnombre del


archivo o ser eliminado
41H

Los parmetros de salida son


CF

0 (no hay error) 1 (error)

Si CF est puesta a 1, usa la funcin 59H para obteber informacin acerca del tipo de error.
Esta funcin no puede borrar una rchivo de sol lectura o un subdirectorio. Si necesitas borrar un archivo de solo
lectura, debes usar la funcin 43H para cambiar los atributos del archivo. Para borrar un subdirectorio usa la
funcin 3AH.
Aqu hay un ejemplo que borra un archivo. El ejemplo usa el sigueinte campo dato
FILE

El path o el nombre del archivo a eliminar

Aqu estn las instrucciones :


; borrar un archivo
LEA
DX,FILE
MOV
AH,41H
INT
21H
; si no hubo xito : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1:

18.15 Renombrar o mover un archivo


Para cambiar el nombre de un archivo, usa la llamada a funcin 56H. Si el nombre nuevo est en el mismo
directorio del nombre antiguo, DOS simplemente renombra el archivo. Si el nuevo nombre est en un directorio
diferente, DOS mueve el archivo a ese directorio. As esta funcin es ms completa que la instruccin RENAME de
DOS porque esta no mueve archivos.
Los parmetros de entrada son :
DS:DX
ES:DI
AH

Direccin del ASCIIZ que contiene el path o el nombre del


archivo a ser movido o renombrado
Direccin del ASCIIZ que contiene el nuevo path o nombre del
archivo
56H

El parmetro de salida es
CF

0 (no error) 1 (error)

Cuando cambies el nombre de un archivo, sigue las siguientes reglas :


El nombre anterior y el nuevo deben referirse a la misma unidad de disco
143

El directorio dstino ya debe existir


Aqu hay dos ejemplo9s. El primer ejemplo renombra el archivo C:\WORK\OLDNAME a
C:\WORK\NEWNAME. El ejemplo usa los siguientes campos dato :
OLDNAME
El nombre anterior
NEWNAME
El nombre nuevo
NEWNAME_ADDR La direccin completa de NEWNAME
En el segmento de datos, define
OLDNAME
DB C:\WORK\OLDNAME,00H
NEWNAME
DB NEWNAME,00H
NEWNAME_ADDR DD NEWNAME
Las instrucciones son las siguientes :
; renombrar un archivo
LEA
DX,OLDNAME
LES
DI,NEWNAME_ADDR
MOV
AH,56H
INT
21H
; ai no hubo xito : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1 :
El segundo ejemplo mueve el archivo C:\OLDDIR\FILE al directorio \NEWDIR.En el segmento de datos, define
OLDNAME
DB C:\OLDDIR\FILE,00H
NEWNAME
DB C:\NEWDIR\FILE,00H
NEWNAME_ADDR DD NEWNAME
Las instrucciones son :
; mover un archivo
LEA
DX,OLDNAME
LES
DI,NEWNAME_ADDR
MOV
AH,56H
INT
21H
; ai no hubo xito : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1 :

18.16 Crear o remover un subdirectorio


Para crear o remover un subdirectorio, usa la llamada a funcin 39H. Para remover un subdirefctorio
existente, use la llamada a funcin 3AH.
144

Los parmetros de entrada son


DS:DX
AH

Direccin del ASCIIZ que contiene el path o el subdirectorio


a crear o eliminar
39H (crear) o 3AH (borrar)

El parmetro de salida es
CF

0 (no hay error) 1 (error)

Si CF est puesta a 1, usa la funcin 59H para obteber informacin acerca del tipo de error.
Como los comandos MKDIR y RMDIR, las llamadas a funcin 39H y 3AH trabajan solo con un subdirectorio a la
vez. De hecho, no puedes crear el subdirectorio \WORK\FILES a menos que WORK ya exista. Y si el
subdirectorio \WORK\FILES existe, no puedes remover \WORK a menos de que elimines a FILES.
Cuando eliminas un subdirectorio. DOS usa las siguientes refglas para prevenir una catastrofe :
D Puedes borrar solo directorios vacos.
D No puede borrar el directorio actual.
D No puedes eliminar el directorio raz.
Aqu hay dos ejemplos. El primero crea un subdirectorio C:\WORK\FILES. El segundo ejemplo bora el mismo
subdirectorio. Los ejemplos usan los siguientes campos dato
DIRNAME

El path o subdirectorio

En el segmento de datos, define


DIRNAME

DB

C:\WORK\FILES,00H

Aqu estn las instrucciones para crear un subdirectorio :


; crea un subdirectorio
LEA
DX,DIRNAME
MOV
AH,39H
INT
21H
; si no hubo xito : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1 :
Las instrucciones para eliminar al subdirectorio son :
; borra un subdirectorio
LEA
DX,DIRNAME
MOV
AH,3AH
INT
21H
; si no hubo xito : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1 :
145

18.17 Obtener el directorio actual


Para obtener el directorio actual ; usa la llamada a funcin 47H. Losparmetros de entrada son
DL
DS:SI

Nmero de undad (0=default, 1=A, 2=B, 3=C,...)


Direccin de un rea de 64 bytes a la cual DOS puede copiar el
path del directorio actual
AH
47H

Los parmetros de salida son


DS:SI
CF

El ASCIIZ conteniendo el path o el directorio actual


0 (no error) 1 (error)

Si CF est puesta a 1, usa la funcin 59H para obteber informacin acerca del tipo de error.
Note que esta funcin usa parmetros un poco diferentes a la de las dems. Primero, el nmero de unidad es
diferente del que usa la funcin 19H (obtener la unidad por omisin) y 0EH (cambiar la unidad por omisin).
Segundo, SI en lugar de DX, mantiene el offset. Esto es debido a que DL es usada para mantener el nmero de
unidad.
DOS regresa un ASCIIZ que contiene el path cpmpleto del directorio actual. Sin embargo, DOS no incluye el
nombre de la unidad ni el primer carcter \ (backslash). Por ejemplo, si el directorio actual es C:\WORK\FILES,
DOS regresa
WORK\FILES
Seguid0o por el byte 00H. si el diectorio actual es C:\ , DOS regresar solo el byte 00H, debido a la omisin del
carcter \ .
Aqu est un ejemplo que obtiene el directorio actual para la unidad por omisin. El ejemplo usa los siguientes
campos dato :
DRIVE
PATHNAME

El nmero que selecciona a la unidad


El rea de 64 bytes que guardar al path

En el segmentpo de datos, define


DRIVE
PATHNAME

DB
DB

0
64 DUP( ?)

Estas son las instrucciones :


; obtener el directorio actual
MOV
DL,DRIVE
LEA
SI,PATHNAME
MOV
AH,47H
INT
21H
; si hubo error : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
146

L1 :

18.18 Cambiar el directorio actual


Para cambiar al directorio actual, usa la llamada a funcin 3BH. Los parmetros de entrada son
DS:DX
Direccin del ASCIIZ que contiene el path del directorio nuevo
AH
3AH
El parmetro de salida es
DS:SI
CF

El ASCIIZ conteniendo el path o el directorio actual


0 (no error) 1 (error)

Si CF est puesta a 1, usa la funcin 59H para obteber informacin acerca del tipo de error.
Aqu hay un ejemplo que cambia el directorio actual del la unidad C: a WORK\FILES. El ejemplo usa el siguuiente
campo dato :
PATHNAME

El path del nuevo directorio

En el segmento de datos, define


PATHNAME

DB

C:\WORK\FILES,00H

Las instrucciones son


; cambiar el directorio actual
LEA
DX,PATHNAME
MOV
AH,3BH
INT
21H
; si hay error : llama a ERROR
JNC
L1
MOV
AH,59H
INT
21H
CALL
ERROR
L1:

18.19 Obtener la unidad de disco por omisin


Para obtener la unidad por omisin, use la llamada a funcin 19H. El parmetro de entrada es
AH
19H
El parmetro de salida es
AL

Nmero de unidad (0=A, 1=B, 2=C,...)

; obtener la unidad por omisin


MOV
AH,19H
INT
21H

147

18.20 Cambiar la unidad por omisin


Para cambiar la unidad por omisin, usa la llamada a funcin 0EH. Los parmetros de entrada son
DL
AH

Nmero de unidad (0=A, 1=B, 2=C,...)


0EH

El parmetro de salida es
AL

Nmero total de unidades

El mnimo nmero de unidades que DOS regresa es 5. Aqu hay un ejemplo que cambia el drive de default por B :
; cambia la unidad por omisin
MOV
DL,1
MOV
AH,0EH
INT
21H

18.21 Cambiar la pantalla y el teclado: ANSI.SYS


En el captulo 17, explique que los manejadores de dispositivos son programas que proveen interfases
estndar a los dispositivos de hardware. El BIOS contiene los manejadores de dispositivos interconstruidos. Puedes
instalar otros manejadores de dispositivos especificandolos en los comandos DEVICE en el CONFIG.SYS. Este
captulo trata solo lo concerniente al ANSI.SYS.
ANSI.SYS te permite el control sobre las operaciones de la pantalla y el teclado. Para instalar el ANSI.SYS incluye
el comando apropiado DEVICE en el archivo CONFIG.SYS, por ejemplo :
DEVICE = C:\DOS\ANSI.SYS
Una vez que colocas esta instruccin en el CONFIG.SYS, DOS instala el ANSI.SYS cada vez que inicias el
sistema.

18.22 Mandar comandos al ANSI.SYS


Una vez instalado el ANSI.SYS, puedes mandarle mensajes escribiendolos en la entrda estndar. Un
comando ANSI.SYS es una cadena de bytes con el siguiente formato :
El primer byte es el cdigo ASCII escape : 1BH.
El segundo byte es el carcter [ (parntesis cuadrado)
Los siguientes bytes son una lista de uno o ms parmetros, seprarados por ;
El ltimo o los dos ltimos son el cdigo del servicio que requieras (ver Tabla 18-3)
Aqu hay tres ejemplos de definiciones de cadenas que guardan comandos del ANSI.SYS :
COM1
COM2
COM3

DB
DB
DB

1BH,[2 ;10H
1BH,[C
1BH,[0 ;68 ;date ;13 ;13P

En el primer ejemplo, hay dos parmetros, 2 y 10, separados por un punto y coma. El cdigo de servicio es el
tlimo, o sea, la letra H.
148

En el segundo ejemplo, no hay parmetros. El cdigo de cervicio es la letra mayscula C.


En el ultimo ejemplo, hay cinco parmetros : 0, 68, date, 13 y 13. El cdigo de servicio es la letra minscula p.
TABLA 18-1 Sumario de comandos del ANSI.SYS
Cdigo
Propsito
H
Mover el cursor a la posicin especificada
A
Mueve el cursor hacia arriba
B
Mueve el cursor abajo
C
Mueve el cursor a la derecha
D
Mueve el cursor a la izquierda
2J
Borra la pantalla
K
Borrar de la posicin del cursor al fin de lnea
m
Ajustar caracterisitcas de la pantalla
p
Redefinir una tecla
Hay dos puntos importantes a comprender. Primero, excepto por el cdigo de escape, todos los bytes son
caracteres. Los parmetros 2, 10, 68, y as son los caracteres 2, 1, 0, 6, y 8, no la representacin
nmerica. Segundo, debes tener cuidado para especificar el cdigode servicio exactamente ; de Hecho en el primer
ejemplo debes usar H, y no h ; en el ltimo ejemplo debes usar p, no P.
Para mandar un comando, define un string que contenga al comando. Entonces uisa la funcin 40H para escribir la
cadena a la salida estndar. Aqu hay un ejemplo de prposito general. Puedes usarlo con cualquier comando que
definas. El ejemplo usa los siguientes campos dato:
ANSI_SYS
Manejador de la salida estndar
ESC
El cdigo de escape
COMMAND
La cadena que contiene al comando
L_COMMAND Longitud de la cadena
En la seccin de iguales, define
ANSI_SYS
ESC

EQU 0001H
EQU 1BH

En el segmento de datos, define


COMMAND
DW ESC,[2 ;10H
L_COMMAND DW $-COMMAND
Las instrucciones son las siguientes:
; mandar un comando al ANSI.SYS
MOV
BX,ANSI_SYS
MOV
CX,L_COMMAND
LEA
DX,COMMAND
MOV
AH,40H
INT
21H
18.23 Mover el cursor
Para mover el cursor a una locacin especfica, manda un comando al ANSI.SYS usando el cdigo H. Este
cdigo usa dos parmetros : el nmero del rengln y la columna a los cuales quieres mover el cursor, el rengln de
arriba es el rengln 1 y la primer columna es la 1. As, para mover el cursor al rengl`on 5, columna 6, usa el
comando :
149

MOVE

DB

ESC,[5 ;6H

Si omites los parmetros, el cursor se mover a la posicin primera en la pantalla (rengln 1, columna 1)
HOME
DB
ESC,[H
Para mover el cursor arriba, abajo, derecha e izquierda, usa los cdigos
A
B
C
D

Arriba
Abajo
Derecha
Izquierda

Estos cdigos usan un parmetro : el nmero de posiciones a mover. Por ejemplo, para mover el cursor hacia arriba
tres renglones, usa est instruccin :
UP3

DB

ESC,[3A

Para mover el cursor 6 posiciones a la izquierda, usa esta :


LEFT6

DB

ESC,[6D

Si no especificas un parmetro, el valor de 1 se asume. Por ejemplo para mover el cursor una columna a la derecha,
usa cualquiera de estos comandos :
RIGHT1
RIGHT1

DB
DB

ESC,[1C
ESC,[C

Nota. El cursor no puede moverse ms alla de los limites de la pantalla. Si se intenta una operacin de este tipo es
ignorada.

18.24 Borrar la pantalla


Para borrar la pantalla completa, manda al ANSI.SYS un comando con el cdigo 2J. Este cdigo tiene el
mismo efecto que la instruccin CLS de DOS. Para borrar la pantalla de la posicin del cursor al fin de la lnea, usa
el cdigo K.
CLS
ERASE

DB
DB

ESC,[2J
ESC,[K

18.25 Ajustar las caracteristicas de la pantalla


Para ajustar las caracteristicas de la pantalla, manda un comando al ANSI.SYS usandpo el cdigo m. Este
cdigo usa uno o ms parmetros. Si usas ms de uno usa el punto y coma para separar los parmetros. Las
opciones para los parmetros estn en las ablas 18-1 y 18-2.
Aqu hay algunos ejemplos. Para ajustar la pantalla a fondo azul con letras rojas, usa esta instruccin:
COMMAND
DB
ESC,[3 ;44m
Para desplegar en la pantalla el mensaje Como ests t con ests en negrita, usa esto:
COMMAND

DB
DB
DB

Como
ESC,[1m ;cambiar a negritas
ests
150

DB
DB

ESC,[0m ;cambiar a normal


t

Tabla 18-1 Parmetros para controlar el color de la pantalla


0
1
5
7
8
Negro
Rojo
Verde
Amarillo
Azul
Magenta
Cyan
Blanco

Resetear a normal
Negritas
Parpardear
Reverso
Invisible

Ajustar el color de letra


30
31
32
33
34
35
36
37

Ajustar el color de fondo


40
41
42
43
44
45
46
47

Tabla 18-2 Parmetros para controlar la pantalla monocromtica


0
1
4
5
7
8

Resetear a normal
Negritas
Subrayado
Parpadeo
Reverso
Invisible

Para desplegar en la pantalla el mensaje Como ests t con ests en negrita y parpadeando, usa esto:
COMMAND

DB
DB
DB
DB
DB

Como
ESC,[1 ;5m ;cambiar a negritas
ests
ESC,[0m ;cambiar a normal
t

18.26 Redefinir las teclas del teclado


Puedes redefinir las teclas del teclado mandando un comando al ANSI.SYS con el cdigo p. De hecho,
puedes redefinir la tecla A para que entre como b o redefinir la tecla F1 para que entre CHKDSK con ENTER.
Para caracteres ASCII regulares, el primer parmetro especifica la tecla que va ha ser redefinida,. El resto de los
parmetros especifican el nuevo significado para la tecla. Por ejemplo, para redefinir la tecla A como b, usa
COMMAND

DB ESC,[a ;bp

Cuando te refieras a un carcter, puedes usar el nombre de la tecla entre comillas o el cdigo ASCII (en decimal).
De hecho, el cdigo ASCII para la a es 97, y el cdigo ASCII para la b es 98, el siguiente comando es
equivalente al anterior.
COMMAND

DB ESC,[97 ;98p
151

Sin embargo, algunas teclas no responden a los caracteres ASCII regulares, como F1 o ALT-3. En este caso, usa le
cdigo extendido que consiste de un 0 seguido de por otro nmero. Por ejemplo, el cdigo extendido para F1 es 0
seguido de 59.
Cuando te refieras a una tecla que usa un cdigo extendido, especifica dos prmetros : el 0 y el segundo nmero.
Por ejemplo para redefinir la tecla F1 como b, usa
COMMAND

DB ESC,[0 ;59 ;bp

La figura 18-3 contiene los cdigos para las teclas no carcter. Basados en los valores de la tabla, aqu hay algunos
ejemplos.
Para redefinir la tecla F1 a CHKDSK y ENTER, usa
COMMAND

DB ESC,[0 ;59 ;chkdsk ;13p

Para redefinir SHIFT-TAB a DEL, usa


COMMAND

DB ESC,[0 ;15 ;0 ;83p

Para redefinir ALT-1 a time ENTER ENTER date ENTER ENTER, usa
COMMAND

DB ESC,[0 ;120 ;time ;13 ;13 ;date ;13 ;13p

Si quieres puedes intercambiar las posiciones de las teclas. Por ejemplo, digamos que no te gusta la posicin de la
tecla ESC. Simplemente intercambiala con otra.
Tabla 18-3 Cdigos de las teclas que no son caracteres
7
BEEP
9
TAB
13 ENTER
27 ESC
Para las siguientes teclas, usa 0 seguido de :
15
71
79
119
117
73
81
132
118

SHIFT-TAB
HOME
END
CTRL-HOME
CTRL-END
PGUP
PGDN
CTRL-PGUP
CTRL-PGDN

F2
60

F3
61

F4
62

F5
63

F6
64

F7
65

F8
66

F9
67

F10
68

SHIFT-F1 F2
84 85

F3
86

F4
87

F5
88

F6
89

F7
90

F8
91

F9
92

F10
93

CTRL94

F2
96

F3
97

F4
98

F5
99

F6 F7 F8 F9 F10
100 101 102 103

F1
59

F1
95

80
75

72 Cursor arriba
Cursor abajo
Cursor izquierda
77 Cursor derecha
115 CTRL-cursor izquierda
116 CTRL-cursor derecha
82 INS
83 DEL

ALT- F1 F2 F3 F4 F5 F6 F7 F8 F9 F10
104 105 106 107 108 109 110 111 112 113
152

ALT- Q
16

W
17

E
18

R
19

T
20

Y
21

U
22

I
23

O
24

ALT- A
30

S
31

D
32

F
33

G
34

H
35

J
36

K
37

L
38

ALT- Z
44

X
45

C
46

V
47

B
48

N
49

M
50

P
25

ALT- 1
2
3
4
5
6
7
8
9
0
120 121 122 123 124 125 126 127 128 129
ALT- =
130 131

18.27 Entrada/Salida de bajo nivel : OUT, INSB, INSW, OUTSB, y OUTSW


En est seccin , se mostrar un ejemplo de un procedimiento que usa entrada/salida de bajo nivel para hacer sonar
un beep.
El ejemplo tiene tres propsitos :
Demostrar las tcnicas del la entrada/salida de bajo nivel.
Proveer un procedimiento til
Convencer que es mejor usar entrada/salida de bajo nivel siempre que sea posible.
En el bajo nivel, un programa se comunica con un dispositivo a travs de la lectura o escritura a un puerto, que es
una coneccin a travs de la cual se pasan datos al dispositivo. Cada puerto tiene un nmero de identificacin de 16
bits en el rango de 0000H a FFFFH. Algunos dispositivos usan varios nmeros, cada uno para un propsito
diferente.
Para leer de puerto, usa la instruccin IN. Para escribir a puerto, usa la instruccin OUT. El formato es :
IN
OUT

registro, puerto
puerto, registro

Dnde registro deben ser AX o AL y puerto es el nmero de puerto.


Estas instrucciones te permiten ejecutar I/O directamente a un dispositivo, una palabra o byte a la vez. Por ejemplo,
para leer un byte de datos del puerto 61H a AL, usa
IN

AL, 61H

Para escribir un byte de datos de AL al puerto 43H, usa


OUT

43H, AL

Si estas trabajando con un dispositivo lo suficientemente rpido, puedes leer o escribir un string completo a la vez.
Usa las instrucciones INSB, INSW, OUTSB y OUTSW, Estas instrucciones trabajan de la misma forma que las
instrucciones regulares de strings.

153

Si tu programa usa instrucciones sucesivas I/O que se refiere al mismo puerto, debes asegurarte que haya suficiente
tiempo entre instrucciones para que el chip I/O pueda recuperarse. Este es el nico problema cuando las
instrucciones estn demasiado cerca.

154

You might also like