; ROMAN80 - VERSION 0.2 ; ; ROMAN CONVERSION PROGRAM ; ; DATE: 10-OCT-78 ; BY: M PEDDER ; ; ; DEFINITIONS ; ORG 100H ;ALLOCATE START: JMP ROMAN CR: EQU 0DH LF: EQU 0AH CONSTA: EQU 1H ;Console status port CONDAT: EQU 0H ;Console data port B$KDR: EQU 02H ;Data available mask STACK: EQU 400H B$VDR: EQU 01H ;Tx ready mask ; ; MESSAGES ; STM DB 'COPYRIGHT (C) 1978 M PEDDER',CR,LF DB '"ROMAN" ACCEPTS DECIMAL NUMBERS IN THE RANGE 1 - 3999' DB CR,LF DB 'AND CONVERTS TO ROMAN NUMERALS, CHECKING VALIDITY.' DB CR,LF,LF DB 'ENTER DATA FOLLOWING "READY =", ENDING WITH "CR"' DB CR,LF,'$' RDM DB CR,LF,'READY = $' TOOL: DB ' TOO LARGE$' INV: DB ' INVALID CHARACTER$' LIST: DB 0,0,'IVXLCDM' ; ; WORKSPACE: ; DBUF: DS 5 ;DECIMAL BUFFER RBUF: DS 16 ;ROMAN BUFFER DCNT: DS 1 ;DECIMAL COUNT STK: DS 2 ;SP HOLDER ; ; SUPERVISORY: ; ROMAN: LXI H,0 DAD SP SHLD STK LXI SP,STACK ;PREPARE STACK LXI H,STM ;POINT TO START MESSAGE CALL PRINS ;AND OUTPUT IT RDY: CALL RDYM ;PRODUCE READY MESSAGE, AND SET UP CALL INPUT ;GET DATA JC RDY ;IF IT IS VALID CALL ENC ;ENCODE AND OUTPUT IT JMP RDY PAGE ; ; READY MESSAGE AND SETTING UP: ; RDYM: LXI H,RDM ;POINT TO READY MESSAGE CALL PRINS ;AND OUTPUT IT LXI B,DBUF ;PREPARE DECIMAL POINTER LXI H,DCNT ;AND COUNT POINTER MVI M,00H ;CLEAR COUNTER RET ; ; GET INPUT FROM CONSOLE INTO DBUF, CHECKING VALIDITY: ; INPUT: IN CONSTA ;IF CHARACTER ANI B$KDR ;IS AVAILABLE JZ INPUT IN CONDAT ;GET IT ANI 7FH ;STRIP PARITY CPI 03H ;IF IT IS EXIT CMD JZ EXIT ;THEN GO CPI 0DH ;IF IT IS 'CR' JNZ ECHO ;THEN MVI A,20H ;LOAD 'SPACE' CALL PRINC ;AND OUTPUT IT CALL PRINC ;TWICE MVI A,'$' ;MARK END STAX B ;OF DATA ORA A ;CLEAR FLAG RET ; EXIT: LHLD STK SPHL RET ; ECHO: CALL PRINC ;ECHO CHARACTER CPI '0' ;IF IT IS ZERO OR MORE JM INVCH ;AND CPI ':' ;IF IT IS NINE OR LESS JP INVCH ;THEN IT IS VALID CHARACTER INR M ;SO COUNT IT STAX B ;AND STORE IT INX B ;ADVANCE POINTER MOV A,M ;CHECK COUNT CPI 05H ;IF IT IS LESS THAN FIVE JM INPUT ;THEN CONTINUE LXI H,TOOL ;ELSE POINT TO 'TOO LARGE' JMP MES ; INVCH: LXI H,INV ;POINT TO 'INVALID CHARACTER' MES: CALL PRINS ;AND OUTPUT IT STC ;SET ERROR FLAG RET ; ; PAGE ; ; PREPARE TO ENCODE: ; ENC: LXI B,DBUF ;PREPARE DECIMAL POINTER LXI D,LIST ;PREPARE LIST POINTER LXI H,DCNT ;PREPARE COUNT POINTER MOV A,M ;GET COUNT CPI 04H ;IF IT IS NOT FOUR JNZ CONT ;CONTINUE LDAX B ;ELSE GET FIRST CHARACTER CPI 34H ;IF IT IS NOT FOUR JM CONT ;CONTINUE LXI H,TOOL ;ELSE LOAD 'TOO LARGE' CALL PRINS ;AND OUTPUT IT RET ; CONT: MOV L,M ;GET COUNT MVI H,00H ;INTO HL DAD H ;DOUBLE IT DAD D ;ADD TO LIST XCHG ;AND RESTORE LIST LXI H,RBUF ;PREPARE ROMAN POINTER ; ; ENCODE CHARACTER STREAM IN DBUF: ; ENCA: LDAX B ;GET A CHARACTER INX B ;UPDATE THE POINTER CPI '$' ;IF IT IS NOT "END MARKER" RZ ;THEN CPI '9' ;IF IT IS NOT A NINE JZ NINE ;THEN CPI '5' ;IF IT IS NOT FIVE OR MORE JP FIVE ;THEN CPI '4' ;IF IT IS NOT FOUR JZ FOUR ;THEN ETA: CPI '0' ;IF IT IS ZERO JNZ ONE ;THEN ETB: DCX D ;MODIFY ROMAN POINTER DCX D ;TWICE LDA DCNT ;REDUCE COUNT DCR A ;AND STA DCNT ;IF IT IS NOT ZERO JNZ ENCA ;THEN LOOP MVI A,'$' ;ELSE MARK END CALL STOR ;AND STORE IT JMP ROUT ;ENCODE COMPLETED ; PAGE ; ; ITS A 1=I, 10=X, 100=C, 1000=M OR MORE: ; ONE: PUSH PSW ;SAVE DATA LDAX D ;LOAD ROMAN CHARACTER CALL STOR ;AND STORE IT POP PSW ;UNSAVE DATA DCR A ;SUBTRACT ONE JMP ETA ;AND TRY AGAIN ; ; ITS A 4=IV, 40=XL, 400=CD: ; FOUR: LDAX D ;LOAD ROMAN CHARACTER I, X OR C CALL STOR ;AND STORE IT INX D ;GET NEXT LDAX D ;ROMAN CHARACTER V, L OR D CALL STOR ;AND STORE THAT DCX D ;RESTORE POINTER JMP ETB ;AND EXIT ; ; ITS A 5=V, 50=L, 500=D OR MORE: ; FIVE: PUSH PSW ;SAVE DATA INX D ;PREPARE POINTER LDAX D ;GET ROMAN CHARACTER V, L OR D CALL STOR ;AND STORE IT DCX D ;RESTORE POINTER POP PSW ;AND DATA SUI 05H ;SUBTRACT FIVE JMP ETA ;AND TRY AGAIN ; ; ITS A 9=IX, 90=XC, OR 900=CM: ; NINE: LDAX D ;GET ROMAN CHARACTER I, X OR C CALL STOR ;AND STORE IT INX D ;MOVE INX D ;POINTER LDAX D ;GET ROMAN CHARACTER X, C OR M CALL STOR ;AND STORE THAT DCX D ;RESTORE DCX D ;POINTER JMP ETB ;AND EXIT ; PAGE ; ; STORE ROMAN CHARACTER IN RBUF FOR OUTPUT: ; STOR: MOV M,A ;STORE DATA IN BUFFER INX H ;AND MOVE POINTER RET ; ; ROMAN OUTPUT TO CONSOLE: ; ROUT: LXI H,RBUF ;POINT TO ROMAN BUFFER CALL PRINS ;AND OUTPUT IT RET ; ; OUTPUT A STRING OF CHARACTERS: ; PRX: CALL PRINC ;OUTPUT IT PRINS: MOV A,M ;GET CHARACTER INX H ;POINT TO NEXT CPI '$' ;IF IT IS NOT END JNZ PRX ;THEN GO RET ; ; OUTPUT A CHARACTER TO CONSOLE: ; PRINC: PUSH PSW ;SAVE DATA PRA: IN CONSTA ;IF CHARACTER ANI B$VDR ;CAN BE TAKEN JZ PRA POP PSW ;UNSAVE CHARACTER OUT CONDAT ;AND OUTPUT IT RET ; END