Write a function/method/subroutine/... that when given an integer greater than or equal to zero returns a string of the number followed by an apostrophe then the ordinal suffix.



Example

Returns would include 1'st 2'nd 3'rd 11'th 111'th 1001'st 1012'th



Task

Use your routine to show here the output for at least the following (inclusive) ranges of integer inputs:
0..25, 250..265, 1000..1025


Note: apostrophes are now optional to allow correct apostrophe-less English.




		org	100h
		jmp	demo
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		;; Given a 16-bit unsigned integer in HL, return a string
		;; consisting of its ASCII representation plus an ordinal
		;; suffix in HL.
nth:		lxi	b,-10		; Divisor for digit loop
		push	h		; Push integer to stack
		lxi	h,nthsfx	; Pointer to end of digit area
		xthl			; Swap digit pointer with integer
nthdigit:	lxi	d,-1		; Get current digit - DE holds quotient
nthdiv10:	inx	d		; Increment quotient,
		dad	b		; subtract 10 from integer,
		jc	nthdiv10	; Keep going until HL<0
		mvi	a,'0'+10	; Calculate ASCII value for digit
		add	l		; Modulus is in (H)L
		xthl			; Swap integer with pointer
		dcx	h		; Point to one digit further left
		mov	m,a		; Store the digit
		xthl			; Swap pointer with integer
		xchg			; Put quotient in HL
		mov	a,h		; Is it zero?
		ora	l
		jnz	nthdigit	; If not, go calculate next digit
		mvi	e,0		; Default suffix is 'th'.
		lxi	h,nthnum+3	; Look at tens digit
		mov	a,m
		cpi	'1'		; Is it '1'?
		jz	nthsetsfx	; Then it is always 'th'.
		inx	h		; Look at zeroes digit
		mov	a,m
		sui	'0'		; Subtract ASCII '0'
		cpi	4		; 4 or higher?
		jnc	nthsetsfx	; Then it is always 'th'.
		rlc			; Otherwise, suffix is at N*2+nthord
		mov	e,a
nthsetsfx:	mvi	d,0		; Look up suffix in list
		lxi	h,nthord
		dad	d		; Pointer to suffix in HL
		lxi	d,nthsfx	; Pointer to space for suffix in DE
		mov	a,m		; Get first letter of suffix
		stax	d		; Store it in output
		inx	h		; Increment both pointers
		inx	d
		mov 	a,m		; Get second letter of suffix
		stax	d		; Store it in output
		pop	h		; Return pointer to leftmost digit 
		ret 
nthord:		db	'thstndrd'	; Ordinal suffixes
nthnum:		db	'*****'		; Room for digits
nthsfx:		db	'**$'		; Room for suffix
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
demo:		;; Demo code
		lxi	h,0		; Starting at 0...
		mvi	b,26		; ...print 26 numbers [0..25]
		call	printnums
		lxi	h,250		; Starting at 250...
		mvi	b,16		; ...print 16 numbers [250..265]
		call	printnums
		lxi	h,1000		; Starting at 1000...
		mvi	b,26		; ...print 26 numbers [1000..1025]
		;; Print values from HL up to HL+B
printnums:	push	h		; Keep number
		push	b		; Keep counter
		call	nth		; Get string for current HL
		xchg			; Put it in DE
		mvi	c,9		; CP/M print string
		call	5
		mvi	e,' '		; Separate numbers with spaces
		mvi	c,2		; CP/M print character
		call	5
		pop	b		; Restore counter
		pop	h		; Restore number
		inx	h 		; Increment number
		dcr	b		; Decrement counter
		jnz	printnums	; If not zero, print next number
		ret