home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Underground
/
UNDERGROUND.ISO
/
share
/
d86
/
hexout.8
< prev
Wrap
Text File
|
1987-04-06
|
4KB
|
94 lines
;---------------
; HEXOUT
;---------------
; (C)1986 Eric Isaacson. Permission to modify or use this file is granted
; to registered A86 and D86 users only. I grant public domain to the
; .COM file that results from assembling this source file.
; HEXOUT is a program that accepts a sequence of hexadecimal numbers in its
; invocation line, and outputs the associated binary values to standard
; output. This is useful, for example, to send a sequence of control
; codes to your printer. You could type HEXOUT >PRN followed by the hex
; values you want to be sent.
; HEXOUT assumes correct input; it does not support error detection.
TAIL_BUFF EQU 081 ; we'll read command tail right where MSDOS gives it to us
HEXOUT:
MOV SI,TAIL_BUFF ; point to the command tail
L1: ; loop here to fetch every hex byte
CALL GET_HEX ; fetch the next value
JC >L2 ; jump if there were no more values
CALL OUT_VALUE ; output the resulting byte
JMP L1 ; loop for another byte
L2: ; scanning is complete
MOV AX,04C00 ; MS-DOS function-number for successful exit
INT 33 ; go back to the operating system
; GET_HEX advances SI to the next hex number, and reads that number. If we
; reach the terminating carriage-return before the next hex digit, we
; return Carry. Otherwise, we return NoCarry, with AL set to the value
; of the hex number, and SI advanced beyond the number.
GET_HEX:
LODSB ; fetch the next byte
CMP AL,0D ; is it the terminator?
STC ; set Carry in case it is
JE RET ; return Carry if it is
CALL HEX_DIGIT? ; is the byte a hex digit?
JC GET_HEX ; loop if not, to find the first hex digit
MOV AH,AL ; it is a digit: save the value in AH
LODSB ; fetch the next byte
CALL HEX_DIGIT? ; is it also a hex digit?
JC >L1 ; jump if not: 1-digit value
SHL AH,1 ; two hex digits: pack the values into AL
SHL AH,1 ; AH * 4
SHL AH,1 ; AH * 8
SHL AH,1 ; AH * 16
OR AL,AH ; AL = AH * 16 + AL -- values are now packed into AL
RET ; NoCarry set by OR signals success
L1: ; the number has a single digit
DEC SI ; retreat input pointer back to the following non-digit
MOV AL,AH ; fetch the single digit's value
CLC ; NoCarry signals success
RET
; HEX_DIGIT? returns NoCarry if AL is an ASCII hex digit; it also transforms
; AL into the associated binary value. Return Carry if AL was not a hex
; digit.
HEX_DIGIT?:
SUB AL,'0' ; reduce decimal digits to their binary values
JC RET ; return Carry if AL was below decimal-digit range
CMP AL,10 ; was the value a decimal digit?
JB >L1 ; return NoCarry if it was
ADD AL,'0' ; restore input AL
AND AL,0DF ; coerce letters to upper case
SUB AL,'A'-10 ; reduce A--F range to 10--15
CMP AL,10 ; was input below the A--F range?
JB RET ; return Carry if it was
CMP AL,16 ; was input above the A--F range? NoCarry now set if yes
L1: ; Carry flag is now the opposite of its return value
CMC ; flip it to the correct value
RET
; OUT_VALUE outputs AL to standard output.
OUT_VALUE:
PUSH AX ; push AL value onto the stack
MOV DX,SP ; MS-DOS memory-pointer now points to the AL-value
MOV CX,1 ; we will output 1 byte
MOV BX,1 ; open-file handle for standard output is 1
MOV AH,040 ; function number for MS-DOS write is 040
INT 33 ; write the AL-value to standard output
POP AX ; pop AL back off the stack
RET