MCALL .MODULE
MODULE CVBTAR,RELEASE=V01,VERSION=04,COMMENT=<CVBTAR/MBGLIB>,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 <
[email protected]>.
.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