For the contest...

From: Megan Gentry <gentry_at_zk3.dec.com>
Date: Tue Apr 20 12:34:39 1999

Okay, I have been able to test the routine, and in fact it did work
first time it executed... It didn't assemble first time because I
had left out a local symbol, but with that corrected it built on the
second try.

In designing the algorithm I used, I noted that converting to Roman
is the same as converting a binary value to decimal (finding the
digit 0-9 for a given power-of-ten) but with the added step of
converting that digit to the appropriate characters for the given
power-of-ten.

The routine has a table of values which are used for successively
subtracting a power of ten from the value until it has a digit 0-9 and a
remainder (which is handled by decreasing powers of ten on successive
passes through the loop). It also maintains a pointer to the current
roman numeral corresponding with the current power-of-ten.

The conversion for 0-3 is easy, it simply outputs the requisite number
of the current roman numeral. For 4, it outputs the current numeral
followed by the numeral one higher. For 5-8, it starts by printing
the numeral one higher followed by 0-3 of the current numeral. For
9, it outputs the current numeral followed by the numeral two higher.

At the end of each loop, the power-of-ten pointer is incremented to
the next entry, but the pointer to the roman numeral is also incremented
by two. This way, the 'current numeral' pointer is always pointing to
'M', 'C', 'X', or 'I'. Since no number in the range which can be
converted required numerals above 'M', I only have to worry about C,
X and I. The numeral one higher than each is, respectively, D, L and V.
The numeral two higher than each is, respectively, M, C and X.

That's it...

I didn't get info on cycles, but I did for number of instructions, which
I included in the comments for the routine.

One last thing - since there are quite a few members in the family
of pdp-11 CPUs, the code is written to run correctly on any one of
them. There are no restrictions, so using the T-11 (as I think
Allison mentioned) would be possible.

                                        Megan Gentry
                                        Former RT-11 Developer

+--------------------------------+-------------------------------------+
| Megan Gentry, EMT/B, PP-ASEL | Internet (work): gentry_at_zk3.dec.com |
| Unix Support Engineering Group | (home): mbg_at_world.std.com |
| Compaq Computer Corporation | |
| 110 Spitbrook Rd. ZK03-2/T43 | URL: http://world.std.com/~mbg/ |
| Nashua, NH 03062 | "pdp-11 programmer - some assembler |
| (603) 884 1055 | required." - mbg |
+--------------------------------+-------------------------------------+

- - - - -

        .SBTTL CVBTAR - Convert Binary to Ascii Roman Numerals

;+
;
; Copyright (c) 1999 by Megan Gentry
;
; CVBTAR
; Converts a binary value to string of ascii characters which
; represent the 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
; 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
;
; 60 words (120 bytes) of code
; 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
;
; Value Instructions executed
; 0 5
; 4000 7
; 1 78
; 3999 185
; 3888 220
;
;-

        .PSECT .CODE.

        .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 -> Decimal conversion table
        MOV #ROMCHR,R3 ;R3 -> Roman numeral character list
        BR 20$ ;Just starting conversion...

; Head of the loop

10$: TST _at_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 _at_R2,_at_SP ;Reduce by current factor of 10
        BHIS 30$ ;Continue if still positive...

        ADD (R2)+,_at_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 _at_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 _at_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 one higher numeral
        SUB #5.,R0 ; followed by one to three current
60$: ADD #5.,R0 ;Return value to range zero to three
        BEQ 80$ ;It was zero, nothing to do...
70$: MOVB _at_R3,(R1)+ ;Store a numeral
        DEC R0 ;More to do?
        BGT 70$ ;Yep...

; Tail of the loop

80$: ADD #2,R3 ;Bump the numeral pointer by *2*
        MOV (SP)+,R0 ;Pop the remainder (already popped
                                        ; the 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

; Conversion data

        .PSECT .DATA.

; Binary to decimal conversion table

BTDTAB: .WORD 1000.
        .WORD 100.
        .WORD 10.
        .WORD 1.
        .WORD 0 ; ** Table Fence **

        .PSECT .TEXT.

; Roman Numerals (1st, 3rd... entries match entries in BTDTAB)

ROMCHR: .ASCII /MDCLXVI/
        .EVEN

        .END
Received on Tue Apr 20 1999 - 12:34:39 BST

This archive was generated by hypermail 2.3.0 : Fri Oct 10 2014 - 23:31:44 BST