jueves, 8 de diciembre de 2016

Programa 28:PROGRAMA QUE SUMA DOS NUMEROS ENTEROS

; FUNCION : Suma de dos numeros.
 ; 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