try this one
notice that the result may not be left-justified in the buffer
but, the result address is returned in EAX
AddAscii PROTO :LPSTR,:LPSTR,:LPSTR
;***********************************************************************************************
ALIGN 16
AddAscii PROC USES EBX ESI EDI lpszVal1:LPSTR,lpszVal2:LPSTR,lpszResult:LPSTR
;Call With: lpszVal1 = address of first ASCII decimal input string
; lpszVal2 = address of second ASCII decimal input string
; lpszResult = address of result buffer (assumed to be large enough)
;
; Returns: EAX = address of result string
;
;Also Uses: EBX, ESI, EDI, EBP are preserved
;--------------------------------
.DATA
ALIGN 4
AddAscTable db 60h,62h,64h,66h,68h,6Ah,6Ch,6Eh,70h,72h
db 61h,63h,65h,67h,69h,6Bh,6Dh,6Fh,71h,73h
;--------------------------------
.CODE
mov edi,lpszVal1
mov esi,lpszVal2
INVOKE StrLen,edi
xchg eax,ebx
INVOKE StrLen,esi
mov edx,lpszResult ;EDX = base address of result buffer
.if eax<ebx
xchg eax,ebx ;EDI,EBX = address,length of shorter input
xchg esi,edi ;ESI,EAX = address,length of longer input
.endif
add edx,eax ;EDX = address of last result byte
lea esi,[esi+eax-1] ;ESI = address of last input byte (longer)
xor ecx,ecx ;ECX = 0
sub eax,ebx ;EAX = length difference (ripple carry count) (clears CF)
mov byte ptr [edx+1],cl ;null terminate result
push eax ;save ripple carry count
mov eax,ecx ;EAX = 0
lea edi,[edi+ebx-1] ;EDI = address of last input byte (shorter)
.repeat
mov cl,[esi]
dec esi
adc cl,[edi]
dec edi
mov al,AddAscTable[ecx-60h]
shr eax,1
dec ebx
mov [edx],al
lea edx,[edx-1]
.until ZERO?
pop ecx ;recall ripple carry count
rcl ebx,1 ;EBX has the last carry bit
.while (ecx) && (ebx)
mov al,[esi]
inc al
dec esi
.if al==3Ah
mov al,30h
.else
mov bl,bh
.endif
mov [edx],al
dec ecx
lea edx,[edx-1]
.endw
.while ecx
mov al,[esi]
dec esi
mov [edx],al
dec ecx
lea edx,[edx-1]
.endw
lea eax,[edx+1]
ret
AddAscii ENDP
;******
*****************************************************************************************