.MCALL .MODULE .MODULE CVBTAR,RELEASE=V01,VERSION=04,COMMENT=,IDENT=NO,LIB=YES ; Copyright (c) 1999, 2000 ; Megan Gentry ; Framingham, Massachusetts ; All Rights Reserved ; Commercial Distribution Prohibited ; ; This software may be freely copied and used in its entirety for any ; purpose so long as the above copyright notice and these comments are ; preserved in the source form of this software, and the binary ; copyright is preserved in any image built from it. ; ; The author has used best efforts in the research, design, development ; and testing of this software. The author makes no warranty of any ; kind, expressed or implied, with regard to this software and its ; suitability for a given application. The author shall not be liable ; in any event for incidental or consequential damages in connection ; with, or arising out of, the use or performance of this software. Use ; of this software constitutes acceptance of these terms. ; ; The author is committed to making a best effort at fixing any errors ; found in the software and would welcome any reports of problems, ; comments or suggestions regarding the software. Please send email ; to . .SBTTL Abstract and Edit History ;+ ; ; The code in this module was developed in response to a challenge ; posted in a message on the Classic Computer Collector's Mailing ; List in 1999. ; ; Edit History: ; ; (01) 1999 Megan Gentry ; Original coding and entry ; ; (02) 06-FEB-2000 Megan Gentry ; Addition of standard copyright, abstract and edit history ; ; (03) 10-Feb-2000 Megan Gentry ; Added EIS conditional and Source ID string ; ; (04) 11-Feb-2000 Megan Gentry ; Corrected Release information ; ; Futures: ; o The code should be modified to use the standard calling ; sequence ; ;- .SBTTL Miscellaneous Definitions .IIF NDF FT.EIS FT.EIS = 0 ;By default, don't use EIS .SBTTL Revision and Copyright string for Images .PSECT .COPY. RO,D .NLCSI TYPE=I .ASCII /Copyright (c) 1999, 2000 Megan Gentry/<15><12> .SBTTL CVBTAR - Convert Binary to Ascii Roman Numerals ;+ ; ; CVBTAR ; Converts a binary value to a string of ascii characters which ; represent the binary value in Roman Numerals. ; ; Call: ; R0 = Binary value to convert ; R1 -> Storage space for resulting string (nul-terminated) ; ; Returns: ; R0 = zero ; R1 -> Byte beyond end of nul-terminated string ; (should be at least 16 bytes long) ; other registers are unaffected as they are saved and restored ; ; Notes: ; o Valid range for input is 1 to 3999. ; o Roman numerals are: ; M 1000 ; D 500 ; C 100 ; L 50 ; X 10 ; V 5 ; I 1 ; ; 62 words (132 bytes) of code (non-EIS) ; 5 words (10 bytes) of data ; 7 bytes of text ; 3 words (6 bytes) of stack used ; ; Code ROMable: yes ; Data ROMable: yes ; Code Reentrant: yes ; Data Reentrant: yes ; Undefined opcodes: no ; Undefined behaviour: no ; ;- .GLOBL CVBTAR .PSECT SYS$I,I .ENABL LSB CVBTAR:: ; Range check the input TST R0 ;Is it valid? BLE 100$ ;Nope... CMP R0,#3999. ;Maybe, check upper limit... BGT 100$ ;Nope... ; Save registers and do some setup MOV R2,-(SP) ;Save R2 MOV R3,-(SP) ; and R3 while they are used MOV #BTDTAB,R2 ;R2 -> Binary to decimal conversion table MOV #ROMCHR,R3 ;R3 -> Roman numeral character list BR 20$ ;Just starting conversion... ; Head of the loop 10$: TST @R2 ;End of the conversion table? BEQ 90$ ;Yep, conversion should be complete 20$: MOV R0,-(SP) ;Save current binary on stack CLR R0 ;Reset R0 for conversion 30$: INC R0 ;Bump count for this digit SUB @R2,@SP ;Reduce by this factor of 10 BHIS 30$ ;Continue if still positive... ADD (R2)+,@SP ;We went too far, add it back ; (and bump conversion table pointer) ; remainder is still on stack DEC R0 ;Reduce the count BEQ 80$ ;If zero, no characters to output ; Here we convert the decimal digit to Roman Numerals CMP R0,#9. ;Is it a nine? BNE 40$ ;Nope... MOVB @R3,(R1)+ ;Yes, it converts to current numeral MOVB -2(R3),(R1)+ ; followed by the numeral two higher BR 80$ 40$: CMP R0,#4. ;Is it a four? BNE 50$ ;Nope... MOVB @R3,(R1)+ ;Yes, it converts to current numeral MOVB -1(R3),(R1)+ ; followed by the numeral one higher BR 80$ 50$: SUB #5.,R0 ;Is value five or greater? BLT 60$ ;Nope, in range zero to three... MOVB -1(R3),(R1)+ ;Yes, prefix with next higher numeral SUB #5.,R0 ; followed by one to three current 60$: ADD #5.,R0 ;Reduce value to range zero to three BEQ 80$ ;It was zero, nothing to do... 70$: MOVB @R3,(R1)+ ;Store a numeral .IF EQ FT.EIS DEC R0 ;More to do? BGT 70$ ;Yep... .IFF ;EQ FT.EIS SOB R0,70$ .ENDC ;EQ FT.EIS ; Tail of the loop 80$: ADD #2,R3 ;Bump the numeral pointer by *2* MOV (SP)+,R0 ;Pop the remainder (we've already ; popped power of ten pointer) BNE 10$ ;More conversion to do if non-zero ; Clean-up 90$: MOV (SP)+,R3 ;Restore previously saved R3 MOV (SP)+,R2 ; and R2 BR 110$ ; Out-of-range string 100$: MOVB #'*,(R1)+ ;Out-of-range conversion string ; String termination and return 110$: CLRB (R1)+ ;String is to be nul-terminated RETURN .DSABL LSB .SBTTL Pure Data and Text areas ; Conversion data .PSECT SYS$D,D ; Binary to decimal conversion table BTDTAB: .WORD 1000. .WORD 100. .WORD 10. .WORD 1. .WORD 0 ; ** Table Fence ** ; Roman Numerals (1st, 3rd... entries match entries in BTDTAB) ROMCHR: .ASCII /MDCLXVI/ .EVEN .END