
; いいいいいいいいいいいいいいいいいいいいいいいいいいいいいい
 ;
 ; Sub Append(Dest As String, Optional Str2 As String, _
 ;   Optional Str3 As String, Optional Str4 As String, _
 ;   Optional Str5 As String, Optional Str6 As String)
 ;
; いいいいいいいいいいいいいいいいいいいいいいいいいいいいいい
 ;
 ;  This Sub can replace vb's string & concatenation.
 ;  The speed is very similar for simple appends:
 ;     sResult = sResult & "text"
 ;     Append sResult, "text"
 ;  But for more substrings this routine is much faster
 ;  because vb's multiple appending is very slow:
 ;     sResult = sResult & "some" & "more" & "text"
 ;     Append sResult, "some", "more", "text"
 ;  This Sub will work correctly if an argument is
 ;  omitted or passed empty:
 ;     Append sMsg, "s1", , "s2", "", , "s3"
 ;     Append sMsg, "", , "s4", , "s5", "s6"
 ;
; いいいいいいいいいいいいいいいいいいいいいいいいいいいいいい

; nasm -f bin Append.asm -o Append.bin

 [bits 32]      ; start of code

   push ebp          ; preserve base pointer
   mov ebp, esp      ; set up pointer to args

   push esi
   push edi          ; preserve registers
   push ebx

   xor edx, edx      ; zero total byte length
   mov esi,[ebp+16]  ; copy Str2 descriptor
   mov ebx, edx      ; zero sub-string count
   mov esi,[esi]     ; extract string pointer
   test esi,esi      ; validate string pointer
   jz _str3          ; skip if null str pointer
   mov ecx,[esi-4]   ; extract byte len of str
   test ecx,ecx      ; validate string length
   jz _str3          ; skip zero length string
   push esi          ; preserve string pointer
   push ecx          ; preserve string length
   inc ebx           ; increment sub-string cnt
   mov edx, ecx      ; add to total byte length

  _str3:
   mov esi,[ebp+20]  ; copy Str3 descriptor
   mov esi,[esi]     ; extract string pointer
   test esi,esi      ; validate string pointer
   jz _str4          ; skip if null str pointer
   mov ecx,[esi-4]   ; extract byte len of str
   test ecx,ecx      ; validate string length
   jz _str4          ; skip zero length string
   push esi          ; preserve string pointer
   push ecx          ; preserve string length
   inc ebx           ; increment sub-string cnt
   add edx, ecx      ; add to total byte length

  _str4:
   mov esi,[ebp+24]  ; copy Str4 descriptor
   mov esi,[esi]     ; extract string pointer
   test esi,esi      ; validate string pointer
   jz _str5          ; skip if null str pointer
   mov ecx,[esi-4]   ; extract byte len of str
   test ecx,ecx      ; validate string length
   jz _str5          ; skip zero length string
   push esi          ; preserve string pointer
   push ecx          ; preserve string length
   inc ebx           ; increment sub-string cnt
   add edx, ecx      ; add to total byte length

  _str5:
   mov esi,[ebp+28]  ; copy Str5 descriptor
   mov esi,[esi]     ; extract string pointer
   test esi,esi      ; validate string pointer
   jz _str6          ; skip if null str pointer
   mov ecx,[esi-4]   ; extract byte len of str
   test ecx,ecx      ; validate string length
   jz _str6          ; skip zero length string
   push esi          ; preserve string pointer
   push ecx          ; preserve string length
   inc ebx           ; increment sub-string cnt
   add edx, ecx      ; add to total byte length

  _str6:
   mov esi,[ebp+32]  ; copy Str6 descriptor
   mov esi,[esi]     ; extract string pointer
   test esi,esi      ; validate string pointer
   jz _str1          ; skip if null str pointer
   mov ecx,[esi-4]   ; extract byte len of str
   test ecx,ecx      ; validate string length
   jz _str1          ; skip zero length string
   push esi          ; preserve string pointer
   push ecx          ; preserve string length
   inc ebx           ; increment sub-string cnt
   add edx, ecx      ; add to total byte length

  _str1:
   test ebx,ebx      ; validate sub-string count
   jz _exitp         ; exit if nothing to append
   mov esi,[ebp+12]  ; copy dest str descriptor
   mov eax,[esi]     ; extract string pointer
   test eax,eax      ; validate string pointer
   jz _alloc         ; skip if null str pointer
   add edx,[eax-4]   ; add to total byte length

  _alloc:
   mov edi, edx      ; store total bytes needed
   shr edx, 1        ; convert to character count
   mov ecx, 7876543h ; api address patched on init
   push edx          ; SysReAllocStringLen len param
   push eax          ; string to copy StrPtr(str)
   push esi          ; bstr variable VarPtr(str)
   call ecx          ; call SysReAllocStringLen
   add edi,[esi]     ; offset dest pointer to end

   pop ecx           ; retrieve str length
   pop esi           ; retrieve str pointer
   sub edi, ecx      ; reduce dest pointer
   sub ecx, 2        ; zero base offset

  _s2:
   mov dx,[esi+ecx]  ; copy unicode character
   mov [edi+ecx],dx  ; write unicode character
   sub ecx, 2        ; reduce offset by one char
   jns _s2           ; continue while more chars

   dec ebx           ; reduce sub-string count
   jz _exitp         ; exit if last sub-string

   pop ecx           ; retrieve str length
   pop esi           ; retrieve str pointer
   sub edi, ecx      ; reduce dest pointer
   sub ecx, 2        ; zero base offset

  _s3:
   mov dx,[esi+ecx]  ; copy unicode character
   mov [edi+ecx],dx  ; write unicode character
   sub ecx, 2        ; reduce offset by one char
   jns _s3           ; continue while more chars

   dec ebx           ; reduce sub-string count
   jz _exitp         ; exit if last sub-string

   pop ecx           ; retrieve str length
   pop esi           ; retrieve str pointer
   sub edi, ecx      ; reduce dest pointer
   sub ecx, 2        ; zero base offset

  _s4:
   mov dx,[esi+ecx]  ; copy unicode character
   mov [edi+ecx],dx  ; write unicode character
   sub ecx, 2        ; reduce offset by one char
   jns _s4           ; continue while more chars

   dec ebx           ; reduce sub-string count
   jz _exitp         ; exit if last sub-string

   pop ecx           ; retrieve str length
   pop esi           ; retrieve str pointer
   sub edi, ecx      ; reduce dest pointer
   sub ecx, 2        ; zero base offset

  _s5:
   mov dx,[esi+ecx]  ; copy unicode character
   mov [edi+ecx],dx  ; write unicode character
   sub ecx, 2        ; reduce offset by one char
   jns _s5           ; continue while more chars

   dec ebx           ; reduce sub-string count
   jz _exitp         ; exit if last sub-string

   pop ecx           ; retrieve str length
   pop esi           ; retrieve str pointer
   sub edi, ecx      ; reduce dest pointer
   sub ecx, 2        ; zero base offset

  _s6:
   mov dx,[esi+ecx]  ; copy unicode character
   mov [edi+ecx],dx  ; write unicode character
   sub ecx, 2        ; reduce offset by one char
   jns _s6           ; continue while more chars

  _exitp:
   pop ebx
   pop edi        ; restore registers
   pop esi
   pop ebp        ; restore base pointer

   xor eax, eax   ; clear eax tell VB okay
   ret 28         ; cleanup (obj, p1, p2, p3, p4, p5, p6)

; いいいいいいいいいいいいいいいいいいいいいいいいいいいいいい

