Task

Create a function taking a positive integer as its parameter and returning a string containing the Roman numeral representation of that integer. Modern Roman numerals are written by expressing each digit separately, starting with the left most digit and skipping any digit with a value of zero.



In Roman numerals:

 1990 is rendered: 1000=M, 900=CM, 90=XC; resulting in MCMXC
 2008 is written as 2000=MM, 8=VIII; or MMVIII
 1666 uses each Roman symbol in descending order: MDCLXVI


		org	100h
		jmp	test
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		;; Takes a 16-bit integer in HL, and stores it
		;; as a 0-terminated string starting at BC.
		;; On exit, all registers destroyed; BC pointing at
		;; end of string. 
mkroman:	push	h	; put input on stack
		lxi	h,mkromantab
mkromandgt:	mov	a,m	; scan ahead to next entry
		ana	a
		inx	h
		jnz	mkromandgt
		xthl		; load number
		mov	a,h	; if zero, we're done
		ora	l
		jz	mkromandone
		xthl		; load next entry from table
		mov	e,m	; de = number
		inx	h
		mov	d,m
		inx	h
		xthl		; load number
		xra	a	; find how many we need
subtract:	inr	a	; with trial subtraction
		dad	d
		jc	subtract
		push	psw	; keep counter
		mov	a,d	; we subtracted one too many
		cma		; so we need to add one back
		mov	d,a
		mov	a,e
		cma
		mov	e,a
		inx	d
		dad	d
		pop	d	; restore counter (into D)
		xthl		; load table pointer
stringouter:	dcr	d	; do we need to include one?
		jz	mkromandgt
		push	h	; keep string location
stringinner:	mov	a,m	; copy string into target
		stax	b
		ana	a	; done yet?
		jz	stringdone
		inx	h
		inx	b	; copy next character
		jmp	stringinner
stringdone:	pop	h	; restore string location
		jmp	stringouter
mkromandone:	pop	d	; remove temporary variable from stack
		ret
mkromantab:	db	0
		db	18h,0fch,'M',0		; The value for each entry
		db	7ch,0fch,'CM',0		; is stored already negated
		db	0ch,0feh,'D',0		; so that it can be immediately
		db	70h,0feh,'CD',0		; added using `dad'.
		db	9ch,0ffh,'C',0		; This also has the convenient
		db	0a6h,0ffh,'XC',0	; property of not having any
		db	0ceh,0ffh,'L',0		; zero bytes except the string
		db	0d8h,0ffh,'XL',0	; and row terminators.
		db	0f6h,0ffh,'X',0
		db	0f7h,0ffh,'IX',0
		db	0fbh,0ffh,'V',0
		db	0fch,0ffh,'IV',0
		db	0ffh,0ffh,'I',0
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		;; Test code
test:		mvi	c,10	; read string from console
		lxi	d,dgtbufdef
		call	5
		lxi	h,0	; convert to integer
		lxi	b,dgtbuf
readdgt:	ldax	b
		ana	a
		jz	convert
		dad	h	; hl *= 10
		mov	d,h
		mov	e,l
		dad	h
		dad	h
		dad	d
		sui	'0'
		mov	e,a
		mvi	d,0
		dad	d
		inx	b
		jmp	readdgt
convert:	lxi	b,romanbuf	; convert to roman
		call	mkroman
		mvi	a,'$'	; switch string terminator
		stax	b
		mvi	c,9	; output result
		lxi	d,romanbuf
		jmp	5
nl:		db	13,10,'$'
dgtbufdef:	db	5,0
dgtbuf:		ds	6
romanbuf: