; Guillermo Arturo Mireles Garcia
; COMPILADOR EN EL QUE SE EJECUTO: TASM
; DECLARACION DE CONSTANTES
CR EQU 13 ; Constante CR (Retorno de carro)
LF EQU 10 ; Constante LF (Salto de l?nea)
IMPRIMIR EQU 9
FIN EQU 4C00H
DOS EQU 21H
TAB EQU 09H
BELL EQU 07H
; DECLARACION DEL SEGMENTO DE DATOS
DATOS SEGMENT
;-----------------------------------------------------------------------
ErrorCAP DB 0 ;Bandera de error en la captura de las cantidades
Cantidad DB 0 ;La cantidad sobre la que se opera, si es 0 mse opera sobre la cantidad 1, si es 1 se opera sobre la cantidad 2.
CantUnoR DW 0 ;Variable que guarda la cantidad uno convertida a binario
CantDosR DW 0 ;Variable que guarda la cantidad dos convertida a binario.
CantUnoN DB 6,0,6 DUP (?) ;Variable que almacena la cantidad uno.
CantDosN DB 6,0,6 DUP (?) ;Variable que almacena la cantidad dos
ResultaR DB 11 DUP (?)
Mensaje DB 13,10,13,10,TAB,TAB,TAB,"====================================="
DB 13,10,13,10,TAB,TAB,TAB,"Programa 28:PROGRAMA QUE SUMA DOS NUMEROS ENTEROS"
DB 13,10,13,10,TAB,TAB,TAB,"=====================================",13,10
DB 13,10,13,10,TAB,TAB,TAB,"(las cantidades debe ser < a 65535)",13,10,13,10,13,10,"$"
M_error1 DB BELL,13,10,"ERROR: digito invalido en cantidad 1.",13,10,13,10,"$"
M_error2 DB BELL,13,10,"ERROR: digito invalido en cantidad 2.",13,10,13,10,"$"
M_error3 DB BELL,13,10,"ERROR: cantidad fuera de rango (65535)","!!!.",13,10,13,10,"$"
M_cant_1 DB 13,10,13,10,TAB,TAB,"Dar la primera cantidad:", "$"
M_cant_2 DB 13,10,13,10,TAB,TAB,"Dar la segunda cantidad:", "$"
M_result DB 13,10,13,10,13,10,TAB,TAB,TAB,BELL,"El resultado es: ","$"
M_espaci DB 13,10,13,10,13,10,13,10,13,10,13,10,"$"
;-------------------------------------------------------------
;Tabla de potencias usada para convertir el resultado binario de la
; operacion en formato ASCII. Se usan las potencias de 10 (1,10,100,1000
;y 10000), porque el numero mas grande es 65535. En caso de que quiera
;operar sobre numeros mas grandes amplie la tabla.
;-------------------------------------------------------------
Potencia DW 001h, 000ah, 0064h, 03E8h, 2710h
PotenciaF DW $
;-----------------------------------------------------------------------
DATOS ENDS
; DECLARACION DEL SEGMENTO DE PILA
PILA SEGMENT STACK
;-----------------------------------------------------------------------
DB 64 DUP('PILA')
;-----------------------------------------------------------------------
PILA ENDS
; DECLARACION DEL SEGMENTO DE CODIGO
CODIGO SEGMENT
pe28_sum PROC FAR ; Etiqueta de comienzo de programa
ASSUME CS:CODIGO,DS:DATOS,SS:PILA
;-------------------------------------------------------------
MOV AX, DATOS ; Inicializa DS con la direccion de @Data
MOV DS, AX
MOV DX, Offset Mensaje ; Despliega el mensaje de bienvenida
CALL IMPRIME
MOV SI, Offset ResultaR ;Inicializa la variable ResultaR
ADD SI, 11
MOV AL, "$"
MOV [SI], AL
; Se capturan las cantidades y se guardan en sus respectivas
; variables para poder trabajar sobre ellas mas adelante. La
; captura se basa en la funcion 09 de l aINT 21h. Dicha funcion
; establece que el registro AH contenga 09 y el registro PAR DS:DX
; apunte a la direccion de la variableque almacenara la estructura del
; Buffer el cual debe estar construido de la siguiente manera:
;
; BYTE 1 = Cantidad de bytes por leer
; BYTE 2 = (llenado por MS-DOS) es la cantidad debytes realmente leidos
; BYTE 3 = Buffer donde se almacen ael resultado, debe encontrarse
; inicializado con la misma cantidad de bytes especificados
; por el byte 1.
; Las cantidades capturadas representan una cadena que es necesario
; convertir a binario antes de que se pueda operar sobre ella.
;
;-------------------------------------------------------------
;-------------------------------------------------------------
; captura primera cantidad
;-------------------------------------------------------------
CAPCANT1:
;-------------------------------------------------------------
MOV DX, Offset M_cant_1 ; Mensaje de captura de cantidad 1.
CALL IMPRIME
;-------------------------------------------------------------
MOV AH, 0AH ; Captura la cantidad (hasta 8 digitos)
MOV DX, Offset CantUnoN
INT DOS
;-------------------------------------------------------------
MOV ErrorCAP, 0 ; Supone que no hay errores y que se esta operando sobre la cantidad 1.
MOV Cantidad, 0
;-------------------------------------------------------------
CALL ConvNUM ; Convierte cantidad uno a binario
;-------------------------------------------------------------
CMP ErrorCAP, 1 ;?hubo error?
JZ CAPCANT1 ; Si, regresa a la captura
;-------------------------------------------------------------
MOV CantUnoR, Bx ; Guarda resultado de conversion
;-------------------------------------------------------------
; Captura segunda cantidad
;-------------------------------------------------------------
CAPCANT2:
;-------------------------------------------------------------
MOV ErrorCAP, 0 ; Supone que no hay errore
MOV Cantidad, 1 ; indica a ConvNUM que es la segund acantidad
;-------------------------------------------------------------
MOV Dx, Offset M_cant_2 ; Mensaje sobre captura de cantidad dos.
CALL IMPRIME
;-------------------------------------------------------------
MOV AH, 0Ah ; Captura la segunda cantidad
MOV DX, Offset CantDosN
INT DOS
CALL ConvNUM ; Convierte cantidad dos a binario
;-------------------------------------------------------------
CMP ErrorCAP, 1 ;?hubo error?
JZ CAPCANT2 ; Si, regresa a capturar la cantidad
;-------------------------------------------------------------
MOV CantDosR, BX ; Guarda conversion d ecantidad 2.
;-------------------------------------------------------------
CALL SUMA ; Suma las dos cantidades
;-------------------------------------------------------------
; TERMINA EL PROGRAMA
;-------------------------------------------------------------
MOV AX, FIN ; Termina el progrma sin error
INT DOS ; 21H
;-----------------------------------------------------------------------
pe28_sum ENDP ; Fin del procedimiento p3_iden
;-----------------------------------------------------------------------
; RUTINAS DE SOPORTE
;-------------------------------------------------------------
; Rutina: Suma
; Proposito: Suma dos numeros enteros sin signo
; Parametros: En el registro Ax el primer numero y en BX el segundo
; Regresa: El resultado en el registro par DX:AX, que es desplegado en la pantalla.
;-------------------------------------------------------------
SUMA PROC NEAR
XOR DX, DX ; Dx = 0 Por si acaso existe acarreo.
MOV AX, CantUnoR ; Primera cantidad
MOV BX, CantDosR ; Segunda cantidad
ADD AX, BX ; Las suma
Jnc CONVERTIR_SUMA ; ?Hubo acarreo?
Adc DX, 0 ; Si
CONVERTIR_SUMA:
CALL ConvASCII ; Convierte resultado en ASCII
MOV DX, Offset M_result ; Despliega cadena del resultado
CALL IMPRIME
MOV DX, Offset REsultaR ; Despliega el resultado
CALL IMPRIME
MOV DX, Offset M_espaci ; Despliega espacios despues del reusltado
CALL IMPRIME
RET
SUMA ENDP
;-------------------------------------------------------------
; Rutina: Imprime
; Proposito: Despliega una cadena
; Parametros: El registro DX contiene el desplazamiento de la cadena
; Regresa: Nada
;-------------------------------------------------------------
IMPRIME PROC NEAR
MOV AH, IMPRIMIR ; Prepara para desplegar la cadena a traves de la INT 21h
INT DOS
RET
IMPRIME ENDP
;-------------------------------------------------------------
; Rutina: ConvNUM
; Proposito: Convertir una cadena en un entero largo
; Parametros: La longitud de la cadena y la direccion de la mism, y se pasan a la pila
; Regresa: En el registro BX la cadena convertida en un entero
;-------------------------------------------------------------
ConvNUM PROC NEAR
MOV DX, 0AH ; Multiplicador es 10
CMP Cantidad, 0 ; ?Es la cantidad 1?
Jnz CONVNUM1 ; No, asi que es la cantidad 2
MOV DI, Offset CantUnoN + 1; Bytes leidos de la cantidad 1
MOV CX, [DI]
MOV SI, Offset CantUnoN + 2; La cantidad 1
JMP CONVNUM2
CONVNUM1:
MOV DI, Offset CantDosN +1 ; Bytes leidos de la cantidad 2
MOV CX, [DI]
MOV SI, Offset CantDosN + 2; La cantidad 2
CONVNUM2:
XOR Ch, Ch ; CH = 0
MOV DI, Offset Potencia ; Direccion de la tabla de potencias
Dec SI ; Posiciona Si En el primer byte de la cadena capturada y le suma el desplazamiento de bytes leidos, para que podamos posiionarnos
; en el final de la misma (apunta al ultimo digito capturado). BX =0 y lee la cadena en forma inversa: es decir, de atras hacia adelante.
ADD SI, CX
XOR BX, BX
Std
CONVNUM3:
LODSB ; Levanta un byte del numero (esta instruccion indica que el registro AL sera cargado con el contenido de la direccion apuntada por DS:SI.)
CMP AL, "0" ; ?Es menor que 0? (Entonces NO es un digito valido)
JB CONVNUM4 ; Si Despliega el mensaje de error y termina
CMP AL, "9" ; ?Es mayor que 9? (entonces NO e sun digito valido)
JA CONVNUM4 ; Si, despliega el error y salta
SUB Al, 30h ; convierte el digito de ascii a binario
CBW ; Convierte a palabra
MOV DX, [DI] ; obtiene la potencia de 10 que sera usada para multiplicar,
Mul DX ; Multiplica numero y lo suma a Bx
JC CONVNUM5 ; Revisa si hubo acarreo, y si lo hubo esto
ADD BX, AX ; significa que la cantidad es > 65535
JC CONVNUM5 ; Si hay acarreo la cantidad es mayor a 65535
ADD DI, 2 ; Va a la siguiente potenci ade 10
LOOP CONVNUM3 ; Itera hasta que Cx sea = 0.
JMP CONVNUM6 ;
CONVNUM4:
CALL HuboERROR ; Algo ocurrio, despliega mensaje y salta
JMP CONVNUM6
CONVNUM5:
MOV Cantidad, 2 ; Hubo acarreo en la conversion, por lo tanto la
CALL HuboERROR ; cantidad capturada es mayor que 65535.
CONVNUM6:
CLD ; Regresa la bandera de direccion a su estado normal
RET ; y Regresa.
ConvNUM ENDP
;-------------------------------------------------------------
; Rutina: ConvASCII
; Proposito: Convertir un valor binario en ASCII
; Parametros: El registro par DX:AX
; Regresa: Nada, pero almacena el resultado en el buffer ResultaR
;-------------------------------------------------------------
ConvASCII PROC NEAR
;-------------------------------------------------------------
; Lo primero que se hace es inicializar la variable que contendra al resultado de la conversion
;-------------------------------------------------------------
PUSH DX
PUSH AX ; Guarda el resultado
MOV SI, Offset REsultaR ;Inicializa la variable REsultaR llenandolacon CEROS.
MOV CX, 10
MOV Al, "0"
ConvASCII1:
MOV [SI], AL
INC SI
LOOP ConvASCII1
POP AX
POP DX
MOV BX, AX ; Palabra baja de la cantidad
MOV AX, DX ; Palabra alta de la cantidad
MOV SI, Offset ResultaR ; Cadena donde se guardara el resultado
ADD SI, 11
MOV CX, 10 ; Divisor = 10
OBTENDIGITO:
DEC SI
XOR DX, DX ; DX contendra el residuo
DIV CX ; Divide la palabra alta (AX)
MOV DI, AX ; Guarda cociaente (AX)
MOV AX, BX ; AX = palabra baja (BX)
DIV CX ; DX tenia un residuo de la division anterior
MOV BX, AX ; Gurada el cociente
MOV AX, DI ; Regresa la palabra alta
ADD Dl, 30h ; Convierte residuo en ASCII
MOV [SI], Dl ; Lo almacena
OR AX, AX ; ? Palabra alta es 0 ?
JNZ OBTENDIGITO ; No, sigue PROCesando
OR BX, BX ; ? Palabra baja es 0 ?
JNZ OBTENDIGITO ; No, sigue procesando
RET
ConvASCII ENDP
;-------------------------------------------------------------
; Rutina: HuboERROR
; Proposito: Desplegar elmensaje de error adecuado
; Parametros: Nada
; Regresa: Nada
;-------------------------------------------------------------
HuboERROR PROC NEAR
CMP Cantidad, 0 ; ?Es la cantidad 1?
JNZ HUBOERROR2 ; nO
MOV Dx, Offset M_error1
CALL IMPRIME
MOV ErrorCAP, 1 ; Enciende la bandera de error
JMP HUBOERROR4
HUBOERROR2:
CMP Cantidad, 1 ; ?Es la cantidad 2?
JNZ HUBOERROR3 ; No
MOV Dx, Offset M_error2
CALL IMPRIME
MOV ErrorCAP, 1
JMP HUBOERROR4
HUBOERROR3:
CMP Cantidad, 2 ; CANTIDAD CAPTURADA ESTA FUERA DE RANGO?
JNZ HUBOERROR4 ; No.
MOV DX, Offset M_error3
CALL IMPRIME
MOV ErrorCAP, 1
JMP HUBOERROR4
HUBOERROR4:
RET
HuboERROR ENDP
CODIGO ENDS
END pe28_sum
No hay comentarios:
Publicar un comentario