								      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 <<<<<
               
