.MODEL    SMALL
.CODE

     PUBLIC    WRITE_HEX
;-----------------------------------------------------------------------;
; Este procedimiento convierte el byte que se halla en el registro DL   ;
; en hexadecimal y escribe los dos d¡gitos hexadecimales en la posi-    ;
; ci¢n actual del cursor.                                               ;
;                                                                       ;
; A la entrada:     DL   Byte a convertir a hexadecimal                 ;
;                                                                       ;
; Usa:         WRITE_HEX_DIGIT                                          ;
;-----------------------------------------------------------------------;
WRITE_HEX PROC                ;Punto de entrada

     PUSH CX                  ;Salva los registros usados en este procedimiento
     PUSH DX
     MOV  DH,DL               ;Hace una copia del byte
     MOV  CX,4                ;Pone el nibble superior en DL
     SHR  DL,CL
     CALL WRITE_HEX_DIGIT     ;Escribe el primer d¡gito hexadecimal
     MOV  DL,DH               ;Poen el nibble inferior en DL
     AND  DL,0Fh              ;Suprime el nibble superior
     CALL WRITE_HEX_DIGIT     ;Escribe el segundo d¡gito hexadecimal
     POP  DX
     POP  CX
     RET
WRITE_HEX ENDP

     PUBLIC    WRITE_HEX_DIGIT
;-----------------------------------------------------------------------;
; Este procedimiento convierte los 4 bits bajos de DL en un d¡gito he-  ;
; xadecimal, y lo imprime en la pantalla.                               ;
;                                                                       ;
; A la entrada:  DL Los cuatro bits bajos contienen el n£mero que se va ;
;                a imprimir en hexadecimal.                             ;
;                                                                       ;
; Usa:         WRITE_CHAR                                               ;
;-----------------------------------------------------------------------;
WRITE_HEX_DIGIT          PROC
     PUSH DX                  ;Salva los registros usados
     CMP  DL,10               ;šEs este nibble < 10?
     JAE  HEX_LETTER          ;No, convertir en una letra
     ADD  DL,"0"              ;S¡, convertir en un d¡gito
     JMP  Short WRITE_DIGIT   ;Ahora escribe este car cter
HEX_LETTER:
     ADD  DL,"A"-10           ;Convertir en letra hexadecimal
WRITE_DIGIT:
     CALL WRITE_CHAR          ;Escribe la letra en la pantalla
     POP  DX                  ;Restablece el valor antiguo de DX
     RET
WRITE_HEX_DIGIT          ENDP

     PUBLIC    WRITE_CHAR
;-----------------------------------------------------------------------;
; Este procedimiento imprime un car cter en la pantalla usando la lla-  ;
; mada de funci¢n del DOS. WRITE_CHAR cambia los caracteres de 0 a 1Fh  ;
; por un punto.                                                         ;
;                                                                       ;
; A la entrada:     DL   El byte que se va a imprimir en la pantalla.   ;
;-----------------------------------------------------------------------;
WRITE_CHAR     PROC
     PUSH AX
     PUSH DX
     CMP  DL,32          ;šEst  el car cter delante de un espacio?
     JAE  IS_PRINTABLE   ;No, imprimir tal cual
     MOV  DL,'.'         ;S¡, sustituir por un punto
IS_PRINTABLE:
     MOV  AH,2           ;Llamada para escribir el car cter
     INT  21h            ;Escribe el caracter contenido en el registro DL
     POP  DX             ;Restablece el valor antiguo de AX y DX
     POP  AX
     RET
WRITE_CHAR     ENDP

     PUBLIC    WRITE_DECIMAL
;-----------------------------------------------------------------------;
; Este procedimiento escribe en la pantalla, en notaci¢n decimal, un    ;
; n£mero sin signo de 16 bits.                                          ;
;                                                                       ;
; A la entrada:     DX   N : n£mero sin signo de 16 bits.               ;
;                                                                       ;
; Usa:    WRITE_HEX_DIGIT                                               ;
;-----------------------------------------------------------------------;

WRITE_DECIMAL  PROC
     PUSH AX             ;Salva los registros que se usan en el programa
     PUSH CX
     PUSH DX
     PUSH SI
     MOV  AX,DX
     MOV  SI,10          ;Divide entre 10 usando SI
     XOR  CX,CX          ;Contador de los d¡gitos que hay en la pila
NON_ZERO:
     XOR  DX,DX          ;Pone a 0 la palabra m s alta de N
     DIV  SI             ;Calcula N/10 y (N mod 10)
     PUSH DX             ;Mueve un d¡gito a la pila
     INC  CX             ;A€adido un d¡gito m s
     OR   AX,AX          ;šEs N = 0 ya?
     JNE  NON_ZERO       ;No, continuar
WRITE_DIGIT_LOOP:
     POP  DX             ;Pone los d¡gitos en orden inverso
     CALL WRITE_HEX_DIGIT
     LOOP WRITE_DIGIT_LOOP
END_DECIMAL:
     POP  SI
     POP  DX
     POP  CX
     POP  AX
     RET
WRITE_DECIMAL  ENDP

     PUBLIC    WRITE_CHAR_N_TIMES
;-----------------------------------------------------------------------;
; Este procedimiento escribe m s de una copia de un car cter.           ;
;                                                                       ;
; A la entrada: DL  C¢digo del car cter.                                ;
;               CX  N£mero de veces que hay que escribir el car cter.   ;
;                                                                       ;
; Usa:         WRITE_CHAR                                               ;
;-----------------------------------------------------------------------;
WRITE_CHAR_N_TIMES  PROC
     PUSH CX
N_TIMES:
     CALL WRITE_CHAR
     LOOP N_TIMES
     POP  CX
     RET
WRITE_CHAR_N_TIMES  ENDP

     PUBLIC    WRITE_PATTERN
;-----------------------------------------------------------------------;
; Este procedimiento escribe una l¡nea en la pantalla, bas ndose en los ;
; con el siguiente formato                                              ;
;                                                                       ;
;    DB   {car cter, n£mero de veces que se ha de escribir el           ;
;          car cter, 0.                                                 ;
; Donde {x} significa que x se puede repetir cualquier n£mero de veces. ;
; A la entrada:  DS:DX   Direcci¢n de la sentencia de datos anterior.   ;
;                                                                       ;
; Usa:         WRITE_CHAR_N_TIMES                                       ;
;-----------------------------------------------------------------------;
WRITE_PATTERN  PROC
     PUSH AX
     PUSH CX
     PUSH DX
     PUSH SI
     PUSHF                    ;Salva el indicador de direcci¢n
     CLD                      ;Poen el indicador de direcci¢n para incremento
     MOV  SI,DX               ;Mueve el desplazamiento al registro SI de LODSB
PATTERN_LOOP:
     LODSB                    ;Pone los datos de car cter en AL
     OR   AL,AL               ;šEs el final de los datos (0h)?
     JZ   END_PATTERN         ;Si, regresa
     MOV  DL,AL               ;No, se prepara para escribir el car cter N veces
     LODSB                    ;Pone el contador de repetici¢n en AL
     MOV  CL,AL               ;Y pone en CX para WRITE_CHAR_N_TIMES
     XOR  CH,CH               ;Pone a cero el byte superior de CX
     CALL WRITE_CHAR_N_TIMES
     JMP  PATTERN_LOOP
END_PATTERN:
     POPF                     ;Restablece el indicador de direcci¢n
     POP  SI
     POP  DX
     POP  CX
     POP  AX
     RET
WRITE_PATTERN  ENDP

     END

