                                                                      COMMENT ~
BINARY.ASM -- Binary Conversion Routines

   From `BLUEBOOK of ASSEMBLY ROUTINES for the IBM PC & XT'
         by Christopher L. Morgan
         Copyright (C) 1984 by The Waite Group, Inc.

      >>>>>  See BINARY.DOC for complete description of routines.  <<<<<

     Contents:
     ---------
     BIN16IN    --  Convert from ASCII Binary to 16-bit Binary
     BIN16OUT   --  Convert from 16-bit Binary to ASCII Binary
     BIN8OUT    --  Convert from 8-bit Binary to ASCII Binary
     DEC16IN    --  Convert from ASCII Decimal to 16-bit Binary
     DEC16OUT   --  Convert from 16-bit Binary to ASCII Decimal
     DEC8OUT    --  Convert from 8-bit Binary to ASCII Decimal
     HEX16IN    --  Convert from ASCII Hexadecimal to 16-bit Binary
     HEX16OUT   --  Convert from 16-bit Binary to ASCII Hexadecimal
     HEX8OUT    --  Convert from 8-bit Binary to ASCII Hexadecimal
     OCT16IN    --  Convert from ASCII Octal to 16-bit Binary
     OCT16OUT   --  Convert from 16-bit Binary to ASCII Octal
     OCT8OUT    --  Convert from 8-bit Binary to ASCII Octal
 _____________________________________________________________________________
 This data should be included in the source code calling these routines, and
   this section then be commented out.                                        ~
DATAS   SEGMENT PUBLIC
        TBUFF   DB      5 DUP(?)
DATAS   ENDS
;_____________________________________________________________________________
;
CODES   SEGMENT

        EXTRN   STDIN:FAR,STDOUT:FAR

        PUBLIC BIN16IN,BIN8OUT,BIN16OUT,OCT16IN,OCT8OUT,OCT16OUT
        PUBLIC HEX16IN,HEX8OUT,HEX16OUT,DEC16IN,DEC8OUT,DEC16OUT

ASSUME CS:CODES,DS:DATAS
;_____________________________ I/O ROUTINES __________________________________
;
;Routine to convert from ASCII binary to internal 16-bit binary
;
BIN16IN   PROC   FAR
          PUSH   AX                    ;Save registers
          MOV    DX,0                  ;Initialize DX as 0
BIN16IN1:
          CALL   STDIN                 ;Digit comes in through AL
          SUB    AL,30H                ;Subtract 30H
          JL     BIN16IN2              ;Check if too low
          CMP    AL,1
          JG     BIN16IN2              ;Check if too high
          CBW                          ;Convert to word
          SAL    DX,1                  ;Shift DX left once
          ADD    DX,AX                 ;Add in digit
          JMP    BIN16IN1
BIN16IN2:
          POP    AX                    ;Restore registers
          RET                          ;Return
BIN16IN   ENDP
;-----------------------------------------------------------------------------
;Routine to convert from internal 8-bit binary to ASCII binary
;
BIN8OUT   PROC FAR
;
;A binary number is in DL
          PUSH   CX                    ;Save registers
          PUSH   AX
          MOV    CX,8                  ;Loop for a count of 8
BIN8OUT1:
          ROL    DL,1                  ;Rotate DL left once
          MOV    AL,DL                 ;Move into AL
          AND    AL,1                  ;Keep just digit
          ADD    AL,30H                ;Add 30H to AL
          CALL   STDOUT                ;Send it out
          LOOP   BIN8OUT1
          POP    AX                    ;Restore registers
          POP    CX
          RET                          ;Return
BIN8OUT   ENDP
;-----------------------------------------------------------------------------
;Routine to convert from internal 16-bit binary to ASCII binary
;
BIN16OUT  PROC   FAR
;
;A binary number is in DX
          PUSH   CX                    ;Save registers
          PUSH   AX
          MOV    CX,16                 ;Loop for a count of 16
BIN16OUT1:
          ROL    DX,1                  ;Rotate DX left once
          MOV    AL,DL                 ;Move into AL
          AND    AL,1                  ;Keep just digit
          ADD    AL,30H                ;Add 30H to AL
          CALL   STDOUT                ;Send it out
          LOOP   BIN16OUT1
          POP    AX                    ;Restore registers
          POP    CX
          RET                          ;Return
BIN16OUT  ENDP
;-----------------------------------------------------------------------------
;Routine to convert from ASCII octal to internal 16-bit binary
;
OCT16IN   PROC   FAR
          PUSH   CX                    ;Save registers
          PUSH   AX
          MOV    DX,0                  ;Initialize DX as 0
OCT16IN1:
          CALL   STDIN                 ;A digit comes in AL
          SUB    AL,30H                ;Subtract 30H
          JL     OCT16IN2              ;Check if too low
          CMP    AL,7                  ;
          JG     OCT16IN2              ;Check if too high
          CBW                          ;Convert to word
          MOV    CL,3
          SAL    DX,CL                 ;Shift DX left once
          ADD    DX,AX                 ;Add in digit
          JMP    OCT16IN1
OCT16IN2:
          POP    AX                    ;Restore registers
          POP    CX
          RET                          ;Return
OCT16IN   ENDP
;-----------------------------------------------------------------------------
;Routine to convert from internal 8-bit binary to ASCII octal
;
OCT8OUT   PROC   FAR
;
;A binary number is in DL
          PUSH   CX                    ;Save registers
          PUSH   AX
;
;First octal digit has only 2 bits
          MOV    CL,2                  ;For a count of 2
          ROL    DL,CL                 ;Rotate DL left
          MOV    AL,DL                 ;Move into AL
          AND    AL,3                  ;Keep just digit
          ADD    AL,30H                ;Add 30H to AL
          CALL   STDOUT                ;Send it out
;
;Second and third octal digits have 3 bits each
          MOV    CX,2                  ;Loop for a count of 2
OCT8OUT1:
          PUSH   CX                    ;Save the count
          MOV    CL,3                  ;For a count of 3
          ROL    DL,CL                 ;Rotate DL left
          MOV    AL,DL                 ;Move into AL
          AND    AL,7                  ;Keep just digit
          ADD    AL,30H                ;Add 30H to AL
          CALL   STDOUT                ;Send it out
          POP    CX                    ;Restore count
          LOOP   OCT8OUT1
          POP    AX                    ;Restore registers
          POP    CX
          RET                          ;Return
OCT8OUT ENDP
;-----------------------------------------------------------------------------
;  Routine to convert from internal 16-bit binary to ASCII octal
;
OCT16OUT  PROC   FAR
;
;A binary number is in DX
          PUSH   CX                    ;Save registers
          PUSH   AX
;
;First octal digit has only one bit
          ROL    DX,1                  ;Rotate DX left one
          MOV    AL,DL                 ;Move into AL
          AND    AL,1                  ;Just keep digit
          ADD    AL,30H                ;Add 30H to AL
          CALL   STDOUT                ;Send it out
;
;Last five octal digits have 3 bits each
          MOV    CX,5                  ;Loop for a count of 5
OCT16OUT1:
          PUSH   CX                    ;Save count
          MOV    CL,3                  ;For a count of 3
          ROL    DX,CL                 ;Rotate DL left
          MOV    AL,DL                 ;Move into AL
          AND    AL,7                  ;Keep just digit
          ADD    AL,30H                ;Add 30H to AL
          CALL   STDOUT                ;Send it out
          POP    CX                    ;Restore count
          LOOP   OCT16OUT1
          POP    AX                    ;Restore registers
          POP    CX
          RET                          ;Return
OCT16OUT  ENDP
;-----------------------------------------------------------------------------
;Routine to convert from ASCII hexadecimal to internal 16-bit binary
;
HEX16IN   PROC   FAR
          PUSH   CX                    ;Save registers
          PUSH   AX
          MOV    DX,0                  ;Initialize DX as 0
HEX16IN1:
          CALL   STDIN                 ;A digit comes in AL
          SUB    AL,30H                ;Subtract 30H
          JL     HEX16IN3              ;Check if too low
          CMP    AL,9
          JLE    HEX16IN2              ;Go if OK
          AND    AL,5Fh                ;For lower case too
          SUB    AL,7                  ;Adjust for A-F
          JL     HEX16IN3              ;Too low for A-F
          CMP    AL,15                 ;Check if too high
          JG     HEX16IN3
HEX16IN2:
          CBW
          MOV    CL,4                  ;For count of 4
          SAL    DX,CL                 ;Shift DX left
          ADD    DX,AX                 ;Add in digit
          JMP    HEX16IN1
HEX16IN3:
          POP    AX                    ;Restore registers
          POP    CX
          RET                          ;Return
HEX16IN   ENDP
;-----------------------------------------------------------------------------
;Routine to convert from internal 8-bit binary to ASCII hexadecimal
;
HEX8OUT   PROC   FAR
;
;A binary number is in DL
          PUSH   CX                    ;Save registers
          PUSH   AX
          MOV    CX,2                  ;Loop for a count of 2
HEX8OUT1:
          PUSH   CX                    ;Save the count
          MOV    CL,4                  ;For a count of 4
          ROL    DL,CL                 ;Rotate DL left
          MOV    AL,DL                 ;Move into AL
          AND    AL,00FH               ;Just digit
          DAA                          ;Add 6 if A-F  DLP
          ADD    AL,0F0H               ;Bump a carry if A-F
          ADC    AL,040H               ;Here is the ASCII
          CALL   STDOUT                ;Send it out
          POP    CX
          LOOP   HEX8OUT1
          POP    AX                    ;Restore registers
          POP    CX
          RET                          ;Return
HEX8OUT   ENDP
;------------------------------------------------------------------------------
;Routine to convert from internal 16-bit binary to ASCII hexadecimal
;
HEX16OUT  PROC FAR
;
;A binary number is in DX
          PUSH   CX                    ;Save registers
          PUSH   AX
          MOV    CX,4                  ;Loop for a count of 4
HEX16OUT1:
          PUSH   CX                    ;Save the count
          MOV    CL,4                  ;For a count of 4
          ROL    DX,CL                 ;Rotate DX left
          MOV    AL,DL                 ;Move into AL
          AND    AL,00Fh               ;Just the digit
          DAA                          ;Add 6 if A-F
          ADD    AL,0F0H               ;Bump a carry if A-F
          ADC    AL,040H               ;Here is the ASCII
          CALL   STDOUT                ;Send it out
          POP    CX
          LOOP   HEX16OUT1
          POP    AX                    ;Restore registers
          POP    CX
          RET                          ;Return
HEX16OUT  ENDP
;-----------------------------------------------------------------------------
;Routine to convert from ASCII decimal to internal 16-bit binary
;
DEC16IN   PROC   FAR
          PUSH   CX                    ;Save registers
          PUSH   AX
          MOV    DX,0                  ;Initialize DX as 0
DEC16IN1:
          CALL   STDIN                 ;Digit comes in AL
          SUB    AL,30H                ;Subtract 30H
          JL     DEC16IN2              ;Check if too low
          CMP    AL,9
          JG     DEC16IN2              ;Check if too high
          CBW                          ;Convert to word
          PUSH   AX                    ;Save digit
          MOV    AX,DX
          MOV    CX,10                 ;Multiplier of 10
          MUL    CX                    ;Multiply
          MOV    DX,AX                 ;Result in DX
          POP    AX                    ;Restore digit
          ADD    DX,AX                 ;Add in digit
          JMP    DEC16IN1
DEC16IN2:
          POP    AX                    ;Restore registers
          POP    CX
DEC16IN   ENDP
;-----------------------------------------------------------------------------
;Routine to convert from internal 8-bit to ASCII decimal
;
DEC8OUT   PROC   FAR
;
;A binary number is in DL
          PUSH   DS                    ;Save registers
          PUSH   DI
          PUSH   DX
          PUSH   CX
          PUSH   AX
          MOV    AX,DATAS              ;Point to the data segment
          MOV    DS,AX
;
;Put the digits in a buffer
          MOV    CX,0                  ;Initialize a counter
          MOV    DI,OFFSET TBUFF       ;Point to buffer
DEC8OUT1:
          PUSH   CX                    ;Save CX
          MOV    AL,DL                 ;AX has numerator
          MOV    AH,0                  ;Clear upper half
          MOV    CL,10                 ;Divisor of 10
          DIV    CL                    ;Divide
          MOV    DL,AL                 ;Get quotient
          MOV    AL,AH                 ;Get remainder
          ADD    AL,30H                ;Add 30H
          MOV    [DI],AL               ;Put in buffer
          INC    DI                    ;Pointer to next byte
          POP    CX                    ;Restore CX
          INC    CX                    ;Count the digit
          CMP    DL,0                  ;Done ?
          JNZ    DEC8OUT1
;
;Dump the buffer out
DEC8OUT2:
          DEC    DI                    ;Back up through the buffer
          MOV    AL,[DI]               ;Get the byte from the buffer
          CALL   STDOUT                ;Send it out
          LOOP   DEC8OUT2
          POP    AX                    ;Restore registers
          POP    CX
          POP    DX
          POP    DI
          POP    DS
          RET                          ;Return
DEC8OUT ENDP
;-----------------------------------------------------------------------------
;Routine to convert from internal 16-bit binary to ASCII decimal
;
DEC16OUT  PROC   FAR
;
;A binary number is in DX
          PUSH   DS                    ;Save registers
          PUSH   DI
          PUSH   DX
          PUSH   CX
          PUSH   AX
          MOV    AX,DATAS              ;Point to data segment
          MOV    DS,AX
;
;Put the digits in a buffer
          MOV    CX,0                  ;Initialize the counter
          LEA    DI,TBUFF              ;Point to the buffer
DEC16OUT1:
          PUSH   CX                    ;Save CX
          MOV    AX,DX                 ;Numerator
          MOV    DX,0                  ;Clear upper half
          MOV    CX,10                 ;Divisor of 10
          DIV    CX                    ;Divide
          XCHG   AX,DX                 ;Get quotient
          ADD    AL,30H                ;Add 30H
          MOV    [DI],AL               ;Put in buffer
          INC    DI                    ;Next byte
          POP    CX                    ;Restore CX
          INC    CX                    ;Count the digit
          CMP   DX,0                   ;Done?
          JNZ    DEC16OUT1
;
;Dump the buffer out
DEC16OUT2:
          DEC    DI                    ;Back up through the buffer
          MOV    AL,[DI]               ;Get byte from buffer
          CALL   STDOUT                ;Send it out
          LOOP   DEC16OUT2
          POP    AX                    ;Restore registers
          POP    CX
          POP    DX
          POP    DI
          POP    DS
          RET                          ;Return
DEC16OUT  ENDP
;-----------------------------------------------------------------------------
CODES   ENDS
;
        END
;_____________________________________________________________________________
;>>>>> Physical EOF binary.ASM <<<<<

