Академический Документы
Профессиональный Документы
Культура Документы
PROCEDIMIENTOS
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 ---
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
direccin
La direccin puede ser directa o indirecta. Usualmente, la direccin es simplemente el nombre del
procedimiento, por ejemplo:
CALL
DISPLAY
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.
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.
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
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
PUSH
PUSH
PUSH
; llamar a CALCULO
CALL
P4
P5
P6
CALCULO
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.
Note que el MAIN debe sacar todos los parmetros que meti, en este caso con un campo dato temporal
TEMP.
valor-pop
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.
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
AX,2
Tienes que asegurarte que la llamada al procedimiento es un del tipo doble palabra:
14
CALL
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;
LARGE+SMALL,PROGRAM;
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
FIRST;
SECOND;
FIRST+SECOND,PROGRAM;
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
AX,9H
DX,MSG1
21H
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.
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
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
valor binario
complemento a dos
00111001
11000111
11000111
00111001
01111111
10000001
10000001
01111111
00000000
00000000
A
22
1100
0000
0100
1010
C
0101
1100
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
AX,VALOR
ERROR
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
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.
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
VALOR1,VALOR2
AX,VALOR2
VALOR1,AX
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.
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
AX
VALOR
SI
28
NEG
CL
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
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
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:
operando, valor-inmediato
destino,operando,valor-inmediato
BP SI
DI
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
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
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.
0010
0000
0001
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.
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.
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
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:
DB
DB
DB
DB
7H
6H
95H
07H
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.
DB 5H,2H,1H
DB 4H,8H,4H
39
DB 56H,43H,21H
DB 45H,68H,54H
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
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.
SI,STRING1
43
LEA
DI,STRING2
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
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.
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
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
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:
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
REP
MOV
LEA
MOV
CLD
STOSB
AL,
DI,STRING
CX,LENGTH STRING
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.
MOV
STRING+3,-
MOV
STRING+4,*
; llenar el string
LEA
SI,STRING
LEA
DI,STRING+5
MOV
CX,LENGTH STRING
CLD
REP
MOVSB
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
DB
30H,31H,32H,33H,34H,35H,36H,37H,38H,39H
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
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.
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
AX,0000111100001111B
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
AX,MASCARA
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
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
AX,0F0FH
O usa un igual
CONVERT_ASCII EQU
AND
0F0FH
AX,CONVERT_ASCII
59
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
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
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
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
AX
Cambia AX a 1100110011001100B.
Si VALOR es un byte que contiene 11110000B, la instruccin:
NOT
VALOR
AX,1111111111111111B
VALOR,11111111B
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.
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
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
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.
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:
68
CAPITULO 17
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
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
vector-interrupcin
21H
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
Entrada/Salida de caracteres
01H
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
Manejo de archivos
43H
4EH
4FH
56H
57H
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
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
75
Redes
4409H
440AH
440BH
5CH
5E00H
5E02H
5E03H
5F02H
5F03H
5F04H
Fecha y hora
2AH
2BH
2CH
2DH
Obtener la fecha
Ajustar la fecha
Obtener la hora
Ajustar la hora
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
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
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
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
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
?
<--<--<--<---
El cdigo de error
La clase de error
La accin recomendada
El lugar
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
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.
84
<--<--<--<---
5H
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
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
;
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
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
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.
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
AX,0000111100001111B
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
AND
AX,MASCARA
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
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
AX,0F0FH
O usa un igual
CONVERT_ASCII EQU
AND
0F0FH
AX,CONVERT_ASCII
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
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
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
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
AX
Cambia AX a 1100110011001100B.
Si VALOR es un byte que contiene 11110000B, la instruccin:
NOT
VALOR
AX,1111111111111111B
VALOR,11111111B
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.
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
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
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:
CAPITULO 17
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
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.
vector-interrupcin
21H
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.
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
Entrada/Salida de caracteres
01H
02H
03H
04H
05H
06H
07H
08H
09H
0AH
0BH
0CH
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
Manejo de archivos
43H
4EH
4FH
56H
57H
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
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
Redes
4409H
440AH
440BH
5CH
5E00H
5E02H
5E03H
5F02H
5F03H
5F04H
Fecha y hora
2AH
2BH
2CH
2DH
Obtener la fecha
Ajustar la fecha
Obtener la hora
Ajustar la hora
6502H
6504H
6505H
6506H
6507H
6520H
6521H
6522H
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
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
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
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
?
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
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
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.
<--<--<--<---
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
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
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
FAR
POP
DS
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
; 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
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.
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.
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
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
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
?
Manejador
3EH
El parmetro de salida es
CF
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
Manejador
Nmero de bytes a leer
Direccin del buffer de entrada
3F
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
EQU 0001H
Manejador
Nmero de bytes a ser escritos
Direccin del buffer de salida
40H
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
DB
EQU
Este es un mensaje.,CR,LF
$-MESSAGE
JE
CALL
L2
DISK_FULL
L2 :
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
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
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 :
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
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
EQU 0000H
EQU 0004H
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
Para borrar un archivo, usa la llamada a funcin 41H. Estos son los parmetros de entrada :
DS:DX
AH
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 parmetro de salida es
CF
El parmetro de salida es
CF
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
DB
C:\WORK\FILES,00H
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
DB
DB
0
64 DUP( ?)
L1 :
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
DB
C:\WORK\FILES,00H
147
El parmetro de salida es
AL
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
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
EQU 0001H
EQU 1BH
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
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.
DB
DB
ESC,[2J
ESC,[K
DB
DB
DB
Como
ESC,[1m ;cambiar a negritas
ests
150
DB
DB
Resetear a normal
Negritas
Parpardear
Reverso
Invisible
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
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
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
Para redefinir ALT-1 a time ENTER ENTER date ENTER ENTER, usa
COMMAND
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
registro, puerto
puerto, registro
AL, 61H
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