home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
GENASM
/
CONVERSI.AQM
/
CONVERSI.ASM
Wrap
Assembly Source File
|
2000-06-30
|
12KB
|
399 lines
;
; CONVERSI.ASM ver 1.1
; Base conversion program
;
;From Heathkit course on assembly language
;
;Converts between ASCII, Binary, Decimal,
;Hexadecimal, Octal, and Split Octal.
;
;Entered by Ben Miller WB8LGH
;on 02/20/80, with routines for CP/M
;I/O. Added prompt for input info.
;Added lower case print on ASCII output.
;
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
BDOS EQU 0005H ;CP/M ENTRY POINT
;
ORG 100H ;ORIGIN OF OBJECT CODE
;
BEGIN LXI SP,STACK;DEFINE TOP OF STACK
LXI H,MESS6 ;SET H-L TO MESSAGE #6
CALL PRINT ;GO PRINT MESSAGE
;
BEGIN1 LXI H,MESS1 ;SET H-L TO MESSAGE #1
CALL PRINT ;GO PRINT MESSAGE
LXI D,0000H ;LOAD D-E REGISTERS WITH 0
CALL INPUT ;GET BASE OF ENTRY
CPI 'D' ;IS IT DECIMAL?
JZ DECIN ;IF DECIMAL GO DECIN
CPI 'H' ;IS IT HEXADECIMAL?
JZ HEXIN ;IF HEXADECIMAL GO HEXIN
CPI 'O' ;IS IT OCTAL?
JZ OCTIN ;IF OCTAL GO OCTIN
CPI 'S' ;IS IT SPLIT OCTAL
JZ SOCTN ;IF SPLIT OCTAL GO SOCTN
CPI 'B' ;IS IT BINARY
JZ BININ ;IF BINARY GO BININ
CPI 'A' ;IS IT ASCII?
JZ ASCIN ;IF ASCII GO ASCIN
CPI 'X' ;ARE YOU DONE?
JZ 0000H ;DO A WARM BOOT
LXI H,MESS2 ;NONE OF THE ABOVE? -MUST BE AN ERROR
CALL PRINT ;GO PRINT ERROR MESSAGE
JMP BEGIN ;START AGAIN TURKEY INPUT IN ERROR
;
PRINT MOV A,M ;GET MESSAGE CHARACTER
ORA A ;CHECK FOR DELIMITER
RZ ;RETURN IF DONE
CALL OUTPT ;DISPLAY CHARACTER
INX H ;SET H-L TO NEXT CHARACTER
JMP PRINT ;DO ANOTHER CHARACTER
;
INPUT PUSH B ;SAVE REGISTERS
PUSH D
PUSH H
MVI C,1 ;READ CONSOLE KBD
CALL BDOS ;CALL CP/M ENTRY
POP H ;RESTORE REGISTERS
POP D
POP B
RET ;RETURN TO MAIN PROGRAM
;
OUTPT PUSH PSW ;SAVE REGISTERS
PUSH B
PUSH D
PUSH H
MOV E,A ;GET CHARACTER FOR CP/M
MVI C,2 ;WRITE CHARACTER TO CRT
CALL BDOS ;CALL CP/M ENTRY
POP H ;RESTORE REGISTERS
POP D
POP B
POP PSW
RET ;RETURN TO MAIN PROGRAM
;
DECIN LXI H,DECIMAL;POINT TO ASCII FOR DECIMAL
CALL VALIN ;SHOW QUESTIONS WITH PROPER BASE
;
NEXT1 CALL GETIN ;GET CHARACTER AND ECHO
JZ CNVRT ;GO CONVERT TO ALL BASES IF SO
SUI 30H ;SUBTRACT 30 HEX FROM ASCII
JC ERROR ;NO GOOD IF CARRY
CPI 10 ;HIGHER THAN "9"?
JNC ERROR ;NO GOOD IF SO
LXI H,0000H ;CLEAR H-L FOR MULTIPLICATION
DAD D ;H-L=D-E TIMES ONE
DAD H ;H-L=D-E TIMES TWO
DAD H ;H-L=D-E TIMES FOUR
DAD D ;H-L=D-E TIMES FIVE
DAD H ;H-L=D-E TIMES TEN
MOV E,A ;NEW KEY VALUE TO E
MVI D,00H ;CLEAR D
DAD D ;ADD UNIT VALUE TO D-E
XCHG ;NEW TOTAL TO D-E
JMP NEXT1 ;LOOP FOR NEXT CHARACTER
;
OCTIN LXI H,OCTAL ;POINT TO ASCII FOR OCTAL
CALL VALIN ;SHOWS QUESTION WITH PROPER BASE
;
NEXT2 CALL GETIN ;GET CHARACTER AND ECHO IT
JZ CNVRT ;GO CONVERT TO ALL BASES IF SO
SUI 30H ;SUBTRACT 30 HEX FROM ASCII
JC ERROR ;NO GOOD IF CARRY
CPI 8 ;HIGHER THAN "7"?
JNC ERROR ;NO GOOD IF SO
LXI H,0000H ;CLEAR H-L FOR MULTIPLICATION
DAD D ;H-L=D-E TIMES ONE
DAD H ;H-L=D-E TIMES TWO
DAD H ;H-L=D-E TIMES FOUR
DAD H ;H-L=D-E TIMES EIGHT
MOV E,A ;NEW KEY VALUE TO E
MVI D,00H ;CLEAR D
DAD D ;ADD UNIT VALUE TO TOTAL
XCHG ;NEW TOTAL TO D-E
JMP NEXT2 ;LOOP FOR NEXT DIGIT
;
HEXIN LXI H,HEXAD ;POINT TO ASCII FOR HEXADECIMAL
CALL VALIN ;SHOWS QUESTION WITH PROPER BASE
;
NEXT3 CALL GETIN ;GET CHARACTER AND ECHO IT
JZ CNVRT ;GO CONVERT TO ALL BASES IF DONE
SUI 30H ;SUBTRACT 30 HEX ASCII
JC ERROR ;NO GOOD IF CARRY
CPI 10 ;IS IT 0 THROUGH 9?
JC HEXOK ;IT'S OK IF SO
SUI 7 ;SUBTRACT 7 MORE FOR LETTERS
CPI 10 ;LOWER THAN 10?
JC ERROR ;NO GOOD IF SO
CPI 16 ;HIGHER THAN 16?
JNC ERROR ;NO GOOD IF SO
;
HEXOK LXI H,0000H ;CLEAR H-L FOR MULTIPLICATION
DAD D ;H-L=D-E TIMES ONE
DAD H ;H-L=D-E TIMES TWO
DAD H ;H-L=D-E TIMES FOUR
DAD H ;H-L=D-E TIMES EIGHT
DAD H ;H-L=D-E TIMES SIXTEEN
MOV E,A ;NEW KEY VALUE TO E
MVI D,00H ;CLEAR D
DAD D ;ADD UNIT VALUE TO TOTAL
XCHG ;NEW TOTAL TO D-E
JMP NEXT3 ;LOOP FOR NEXT DIGIT
;
BININ LXI H,BINRY ;SHOWS ASCII FOR BINARY
CALL VALIN ;SHOWS QUESTION WITH PROPER BASE
;
NEXT4 CALL GETIN ;GET CHARACTER AND ECHO IT
JZ CNVRT ;GO CONVERT IF SO
SUI 30H ;SUBTRACT 30H FROM ASCII
JC ERROR ;NO GOOD IF CARRY
CPI 2 ;IF HIGHER THAN "1"?
JNC ERROR ;NO GOOD IF SO
LXI H,0000H ;CLEAR H-L FOR MULTIPLICATION
DAD D ;H-L=D-E TIMES ONE
DAD H ;H-L=D-E TIMES TWO
MOV E,A ;NEW KEY VALUE TO E
MVI D,00H ;CLEAR D
DAD D ;ADD UNIT VALUE TO TOTAL
XCHG ;NEW TOTAL TO D-E
JMP NEXT4 ;LOOP FOR NEXT DIGIT
;
SOCTN LXI H,SPLIT ;POINT TO ASCII FOR SPLIT OCTAL
CALL VALIN ;SHOWS QUESTION WITH PROPER BASE
;
NEXT5 CALL GETIN ;GET CHARACTER AND ECHO IT
JZ CNVRT ;GO CONVERT TO ALL BASES IF SO
CPI '/' ;IS CHARACTER A SLASH?
JNZ NODOT ;NO-CONTINUE
MOV D,E ;YES - TOTAL IN E BECOMES HIGH BYTE
MVI E,00H ;CLEAR E
JMP NEXT5 ;GO GET NEXT CHARACTER
;
NODOT SUI 30H ;SUBTRACT30H FROM ASCII
JC ERROR ;NO GOOD IF CARRY
CPI 8 ;HIGHER THAN "7"?
JNC ERROR ;NO GOOD IF SO
MOV L,A ;SAVE NEW KEY VALUE IN L
MOV A,E ;PREVIOUS TOTAL TO A
ADD A ;PREVIOUS TOTAL TIMES TWO
ADD A ;PREVIOUS TOTAL TIMES FOUR
ADD A ;PREVIOUS TOTAL TIMES EIGHT
ADD L ;ADD NEW KEY TO MULTIPLIED TOTAL
MOV E,A ;NEWTOTAL BACK TO E
JMP NEXT5 ;LOOP FOR NEXT DIGIT
;
ASCIN LXI H,ASCII ;POINT TO ASCII FOR ASCII
CALL VALIN ;SHOWS QUESTION WITH PROPER BASE
;
NEXT6 CALL GETIN ;GET CHARACTER AND ECHO IT
JZ CNVRT ;GO CONVERT TO ALL BASES IF SO
MOV D,E ;LAST CHARACTER MOVES TO D
MOV E,A ;NEW CHARACTER GOES IN E
JMP NEXT6 ;LOOP FOR NEXT CHARACTER
;
CNVRT LXI H,MESS5 ;SET H-L TO BEGINNING OF MESSAGE
CALL PRINT ;DISPLAY MESSAGE
;
DOUT XCHG ;SWAP UNKNOWN INTO H-L
PUSH H ;SAVE UNKNOWN ON STACK
LXI B,10000D;LOAD B-C WITH 10000 DECIMAL
CALL SUBTR ;SUBTRACT AND DISPLAY
LXI B,1000D ;LOAD B-C WITH 1000 DECIMAL
CALL SUBTR ;SUBTRACT AND DISPLAY
LXI B,100D ;LOAD B-C WITH 100 DECIMAL
CALL SUBTR ;SUBTRACT AND DISPLAY
LXI B,10D ;LOAD B-C WITH 10 DECIMAL
CALL SUBTR ;SUBTRACT AND DISPLAY
MOV A,L ;WHAT'S LEFT IS UNITS ONLY
ADI 30H ;MAKE IT ASCII
CALL OUTPT ;DISPLAY UNITS
POP D ;GET ORIGINAL BACK
CALL SPACES ;OUTPUT TWO SPACES
;
HOUT MOV A,D ;HIGH BYTE OF UNKNOWN TO A
CALL DOHEX ;CONVERT HEX AND DISPLAY
MOV A,E ;LOW BYTE OF UNKNOWN TO A
CALL DOHEX ;CONVERT AND DISPLAY
CALL SPACES ;OUTPUT TWO SPACES
;
OOUT MOV A,D ;HIGH BYTE OF UNKNOWN TO A
RAL ;ROTATE LEFT MOST BIT
RAL ; INTO RIGHTMOST POSITION
PUSH PSW ;SAVE NEW BYTE ON STACK
ANI 01H ;ZER0 ALL BUT RIGHT BIT
CALL OCTOUT ;MAKE ASCII AND DISPLAY ON CRT
POP PSW ;GET MODIFIED BYTE BACK
CALL ROTES ;GO NEXT 3 BYTES 2 TIMES
MOV A,E ;LOW BYTE OF UNKNOWN TO A
CALL ROTES ;DO LEFTOVER OF HIGH AND 5 OF LOW
CALL ROTER ;DO LAST THREE BYETE
CALL SPACES ;OUTPUT TWO SPACES
;
SOOUT MOV A,D ;HIGH BYTE OF UNKNOWN TO A
CALL SOCT ;CONVERT TO OCTAL DISPLAY
MVI A,'/' ;SET UP A '/' TO DISPLAY
CALL OUTPT ;DISPLAY ON CRT
MOV A,E ;LOW BYTE OF UNKNOWN TO A
CALL SOCT ;CONVERT TO OCTAL AND DISPLAY
CALL SPACES ;OUTPUT TWO SPACES
;
BOUT MOV A,D ;HIGH BYTE OF UNKNOWN TO A
CALL BINOUT ;DISPLAY AS 0'S AND 1'S
MOV A,E ;LOW BYTE OF UNKNOWN TO A
CALL BINOUT ;DISPLAY AS O'S AND 1'S
CALL SPACES ;OUTPUT TWO SPACES
;
AOUT MOV A,D ;HIGH BYTE OF UNKNOWN TO A
CALL ATEST ;TEST FOR LEGAL AND DISPLAY
MVI A,' ' ;NEED A SPACE TO SEPERATE
CALL OUTPT ;DISPLAY THE SPACE
MOV A,E ;LOW BYTE OF UNKNOWN TO A
CALL ATEST ;TEST FOR LEGAL AND DISPLAY
CALL CRLF ;DO A CAR RET AND LINE FEED
CALL CRLF ;ONE MORE MAKES IT NICE
JMP BEGIN1 ;START ALL OVER AGAIN???
;
CRLF MVI A,0DH ;SETUP A CARRIAGE RETURN
CALL OUTPT ;DISPLAY IT
MVI A,0AH ;SET UP A LINE FEED
JMP OUTPT ;DISPLAY IT AND RETURN TO WHEREVER
;
ATEST CPI ' ' ;LOWER THAN A SPACE?
JC DODOT ;DISPLAY A '.' IF SO
CPI 7FH ;HIGHER THAN A RUBOUT?
JC OUTPT ;DISPLAY A CHARACTER IF SO
;
DODOT MVI A,'.' ;SETUP A DOT TO DISPLAY
JMP OUTPT ;DISPLAY THE DOT ON THE CRT
BINOUT MVI B,08H ;8 BITS TO DO - SETUP COUNTER
;
BLOOP RAL ;ROTATE A BIT INTO CARRY
PUSH PSW ;SAVE THE MODIFIED BYTE
MVI A,'1' ;ASSUME BIT LOGIC IS 1
JC BINOK ;DISPLAY IT IF A-OK
MVI A,'0' ;OOPS CHANGED MY MIND FICKLE
;
BINOK CALL OUTPT ;DISPLAY WHATEVER
POP PSW ;GET MODIFIED BYTE BACK
DCR B ;COUNT ONE BIT COMPLETED
JNZ BLOOP ;DO ANOTHER UNTILL ALL 8 ARE DONE
RET ;THEN GO BACK TO WHEREVER
;
SOCT RAL ;ROTATE TWO LEFTMOST BITS
RAL ; INTO TWO RIGHTMOST
RAL ; POSITIONS
PUSH PSW ;SAVE MODIFIED BYTE ON STACK
ANI 03H ;ZERO ALL BUT TWO RIGHTMOST BITS
CALL SPOUT ;MAKE ASCII AND DISPLAY ON CRT
POP PSW ;GET MODIFIED BYTE BACK
CALL SPINR ;DO 3 BITS AND FALL INTO 3 MORE
;
SPINR RAL ;ROTATE TWO LEFTMOST BITS
RAL ; INOT TWO RIGHTMOST
RAL ; POSITIONS
;
SPOUT PUSH PSW ;SAVE MODIFIED BYTE ON STACK
ANI 07H ;ZERO ALL BUT THREE RIGHT BITS
ADI 30H ;ADD ASCII OFFSET
CALL OUTPT ;DISPLAY CHARACTER ON CRT
POP PSW ;GET MODIFIED BYTE BACK
RET ;GO BACK TO WHERE YOU CAME FROM
;
ROTES CALL ROTER ;DO 3 BITS AND FALL INTO 3 MORE
;
ROTER RAL ;ROTATE CARRY PLUS LEFTMOST
RAL ; TWO BITS OF DATA BYTE INTO
RAL ; THREE RIGHTMOST BITS
;
OCTOUT PUSH PSW ;SAVE MODIFIED BYTE ON STACK
ANI 07H ;ZERO ALL BUT RIGHT THREE BITS
ADI 30H ;ADD IN ASCII OFFSET
CALL OUTPT ;DISPLAY CHARACTER ON CRT
POP PSW ;GET MODIFIEY BYTE BACK
RET ;RETURN TO MAIN PROGRAM
;
DOHEX PUSH PSW ;SAVE BYTE ON STACK
RRC ;ROTATE
RRC ;LEFT
RRC ; FOUR BITS
RRC ; INTO PLACE
CALL HEXOUT ;MAKE ASCII AND DISPLAY
POP PSW ;GET BYTE BACK
;
HEXOUT ANI 0FH ;KEEP ONLY RIGHT FOUR BITS
ADI 30H ;ADD ASCII OFFSET
CPI ':' ;IS IT A NUMBER
JC OUTPT ;DISPLAY IT ON CRT IF SO
ADI 07H ;MAKE IT A LETTER
JMP OUTPT ;AND DISPLAY ON CRT
;
SUBTR MVI D,0FFH ;D REGISTER TO MINUS ONE
;
LOOP5 MOV A,L ;LOW BYTE OF UNKNOWN TO A
SUB C ;SUBTRACT LOW BYTE OF DIVISOR
MOV L,A ;DIFFERENCE BACK TO L
MOV A,H ;HIGHT BYTE OF UNKNOWN TO A
SBB B ;SUBTRACT B AND BORROW IF ANY
MOV H,A ;DIFFERENCE BACK TO H
INR D ;COUNT ONE SUBTRACTION
JNC LOOP5 ;SUBTRACT AGAIN IF NO BORROW
DAD B ;ADD DIVISOR BACK TO UNKNOWN
MOV A,D ;COUNT TO A
ADI 30H ;MAKE IT ASCII
JMP OUTPT ;DISPLAY ON CRT
;
ERROR LXI H,MESS4 ;SET H-L TO BEGINNING OF MESSAGE
CALL PRINT ;GO PRINT IT
JMP BEGIN ;START OVER
;
SPACES MVI A,' ' ;PUT A SPACE IN REGISTER A
CALL OUTPT ;PRINT IT
JMP OUTPT ;OUTPUT ANOTHER SPACE THEN RETURN
;
GETIN CALL INPUT ;GET CHARACTER FROM KEYBOARD
CPI 0DH ;ARE THEY DONE ENTERING?
RNZ ;BACK TO WHOEVER IF NOT
JMP CNVRT ;JMP TO CONVERT ALL BASES
;
VALIN PUSH H ;SAVE BASE POINTER
LXI H,WHAT ;POINT TO QUESTION
CALL PRINT ;SHOWS THE QUESTION
POP H ;GET THE BASE NAME POINTER BACK
CALL PRINT ;PRINT IT
LXI H,VALUE ;POINT TO VALUE
JMP PRINT ;PRINT IT THEN JUMP WHEREVER
;
WHAT DB CR,LF,'What''s your ',0
VALUE DB ' Value? ',0
DECIMAL DB 'Decimal',0
HEXAD DB 'Hexadecimal',0
OCTAL DB 'Octal',0
SPLIT DB 'Split Octal',0
BINRY DB 'Binary',0
ASCII DB 'ASCII',0
MESS1 DB CR,LF,'What base is your entry? ',0
MESS2 DB CR,LF,'Sorry that is not a base I can work with. ',0
MESS4 DB CR,LF
DB 'Input character wrong for base specified, '
DB 're-enter',0
MESS5 DB CR,LF,' Decimal Hex Octal S/Octal Binary'
DB ' ASCII',CR,LF,' ',0
MESS6 DB CR,LF,'Possible choices are: ',CR,LF
DB CR,LF,' A = ASCII '
DB CR,LF,' B = Binary '
DB CR,LF,' D = Decimal '
DB CR,LF,' H = Hexadecimal'
DB CR,LF,' O = Octal '
DB CR,LF,' S = Split Octal '
DB CR,LF,' X = Exit '
DB CR,LF,0
;
DS 60 ;RESERVE SPACE FOR STACK
STACK EQU $ ;TOP OF STACK
;
END