This code will not work on EMU8086 or any processor prior to 80286. Line 40 would need to be changed.

; ============================================================================================
; Converts unsigned integer to NULL terminated ASCII string

;	ENTRY:	AX = 16 bit value to be converted
;		DX = Pointer to destination buffer (must be at least 5 bytes in length)

;	LEAVE:	AX = Pointer to first character of conversion
;		DX = Unchanged and points to ASCII string padded with blanks.
; --------------------------------------------------------------------------------------------

	I2A_16	push	di			; Preserve base pointer
		push	dx
		mov	dx, ax
	; This creates a buffer with leading spaces.  Could be changed to '00' if leading
	; zero's are prefered.
		mov	ax, '  '		; Pad buffer with spaces
		mov	byte [di], 0		; Teminate with NULL
		dec	di			; Bump back to last byte of string
	; It might be a better idea to check flag before changing, but in this case I'm
	; going to assume all routines change to auto increment before completing.
		std				; Auto decrement
	; Cycle until DX is null, but should it be zero at least one '0' will be written.
	 .Next	mov	 al, dl			; Get next byte 
	 	and	 al, 15			; Strip high nibble
	 	or	 al, '0'		; Make ASCII
	 	cmp	 al, 58			; and determine if greater than '9'
	 	jb	$ + 4			; Branch if between '0' & '9'
	 	add	 al, 7			; Makes character 'A' - 'F'
	 	stosb				; Write ASCII character to buffer
		shr	dx, 4			; Shift next nibble into AL
		jnz	.Next			; and continue if not zero
		cld				; Set default direction	
	 	pop	dx			; Restore original contents
		mov	ax, di			; Copy pointer
		inc	ax			; and bump so there are no leading spaces
		pop	di			; Pointer with leading spaces

Line 40 would need to be replaced by:

mov cl, 4
shr dx,cl

In the first x86 processors, only shr dx,1 or shr dx,cl were allowed (for dx or any other register).