main.cpp
#include <stdio.h>
#include <stdint.h>
#include <wchar.h>

extern "C" int ConcatStrings(wchar_t* des, int des_size, const wchar_t* const* src, int src_n);

int main(int argc, char* argv[])
{
	printf("\nResults for ConcatStrings\n");
	
	// Destination buffer large enough
	wchar_t* src1[] = { (wchar_t*)(L"One "), (wchar_t*)(L"Two "), (wchar_t*)(L"Three "), (wchar_t*)(L"Four") };
	int src1_n = sizeof(src1) / sizeof(wchar_t*);
	const int des1_size = 64;
	wchar_t des1[des1_size];

	int des1_len = ConcatStrings(des1, des1_size, src1, src1_n);
	wchar_t* des1_temp = (*des1 != '\0') ? des1 : ((wchar_t*)(L"<empty>"));
	printf("  des_len: %d (%d) des: %ls \n", des1_len, wcslen(des1_temp), des1_temp);
	
	// Destination buffer too small
	wchar_t* src2[] = { (wchar_t*)(L"Red "), (wchar_t*)(L"Green "), (wchar_t*)(L"Blue "), (wchar_t*)(L"Yellow ") };
	int src2_n = sizeof(src2) / sizeof(wchar_t*);
	const int des2_size = 16;
	wchar_t des2[des2_size];

	int des2_len = ConcatStrings(des2, des2_size, src2, src2_n);
	wchar_t* des2_temp = (*des2 != '\0') ? des2 : (wchar_t*)(L"<empty>");
	printf("  des_len: %d (%d) des: %ls \n", des2_len, wcslen(des2_temp), des2_temp);
	
	// Empty string test
	wchar_t* src3[] = { (wchar_t*)(L"Airplane "), (wchar_t*)(L"Car "), (wchar_t*)(L""), (wchar_t*)(L"Truck "), (wchar_t*)(L"Boat ") };
	int src3_n = sizeof(src3) / sizeof(wchar_t*);
	const int des3_size = 128;
	wchar_t des3[des3_size];
	
	int des3_len = ConcatStrings(des3, des3_size, src3, src3_n);
	wchar_t* des3_temp = (*des3 != '\0') ? des3 : (wchar_t*)(L"<empty>");
	printf("  des_len: %d (%d) des: %ls \n", des3_len, wcslen(des3_temp), des3_temp);
	
	return 0;
}
concatstrings.asm
; Name:     concatstrings.asm
;
; Build:    g++ -m32 -c main.cpp -o main.o
;           nasm -f elf32 -o concatstrings.o concatstrings.asm
;           g++ -m32 -o concatstrings concatstrings.o main.o
;
; Source:   Modern x86 Assembly Language Programming p.76

global  ConcatStrings

section .text

; extern "C" int ConcatStrings(wchar_t* des, int des_size, const wchar_t* const* src, int src_n);
;
; Description:  This function performs string concatenation using
;               multiple input strings.
;
; Returns:      -1          Invalid 'des_size'
;               n >= 0      Length of concatenated string
;
; Locals Vars:  [ebp-4] = des_index
;               [ebp-8] = i

%define des_index   [ebp-4]
%define i           [ebp-8]
%define des         [ebp+8]
%define des_size    [ebp+12]
%define src         [ebp+16]
%define src_n       [ebp+20]
	
ConcatStrings:
    push    ebp
    mov     ebp,esp
    sub     esp,8
    push    ebx
    push    esi
    push    edi
    ; Make sure 'des_size' is valid
    mov     eax,-1                      ;set error code
    mov     ecx,des_size                ;ecx = 'des_size'
    cmp     ecx,0
    jle     .error
    ; Perform required initializations
    xor     eax,eax                     ;set error code
    mov     ebx,des                     ;ebx = 'des'
    mov     [ebx],eax                   ;*des = '\0'
    mov     des_index,eax               ;des_index = 0
    mov     i,eax                       ;i = 0
    ; Repeat loop until concatenation is finished
.Lp1:
    mov     eax,src                     ;eax = 'src'
    mov     edx,i                       ;edx = i
    mov     edi,[eax+edx*4]             ;edi = src[i]
    mov     esi,edi                     ;esi = src[i]
    ; Compute length of s[i]
    xor     eax,eax
    mov     ecx,-1
    repne   scasd                       ;find '\0'
    not     ecx
    dec     ecx                         ;ecx = len(src[i])
    ; Compute des_index + src_len
    mov     eax,des_index               ;eax= des_index
    mov     edx,eax                     ;edx = des_index_temp
    add     eax,ecx                     ;des_index + len(src[i])
    ; Is des_index + src_len >= des_size?
    cmp     eax,des_size
    jge     .done
    ; Update des_index
    add     des_index,ecx               ;des_index += len(src[i])
    ; Copy src[i] to &des[des_index] (esi already contains src[i])
    inc     ecx                         ;ecx = len(src[i]) + 1
    lea     edi,[ebx+edx*4]             ;edi = &des[des_index_temp]
    rep     movsd                       ;perform string move
    ; Update i and repeat if not done
    mov     eax,i
    inc     eax
    mov     i,eax                       ;i++
    cmp     eax,src_n
    jl      .Lp1                        ;jump if i < src_n
    ; Return length of concatenated string
.done:
    mov     eax,des_index               ;eax = des_index
.error:
    pop     edi
    pop     esi
    pop     ebx
    mov     esp,ebp
    pop     ebp
    ret
build
g++ -m32 -c main.cpp -o main.o
nasm -f elf32 -o concatstrings.o concatstrings.asm
g++ -m32 -o concatstrings concatstrings.o main.o