
; いいいいいいいいいいいいいいいいいいいいいいいいいいいいいい
 ;
 ; Function Appends(Optional Str1 As String, Optional Str2 As String, _
 ;                  Optional Str3 As String, Optional Str4 As String, _
 ;                  Optional Str5 As String) As String
 ;
; いいいいいいいいいいいいいいいいいいいいいいいいいいいいいい
 ;
 ;  This function can replace vb's string & concatenation.
 ;  The speed is very similar for simple appends:
 ;     sResult = "some" & "text"
 ;     sResult = Appends("some", "text")
 ;  But for more substrings this function is much faster
 ;  because vb's multiple appending is very slow:
 ;     sResult = "this" & "is" & "some" & "text"
 ;     sResult = Appends("this", "is", "some", "text")
 ;  Notice you can safely pass as an argument the variable
 ;  that the function is assigning back to (compiler safe).
 ;     sResult = Appends(sResult, "some", "more", "text")
 ;  This function will work correctly if an argument is
 ;  omitted or passed empty:
 ;     sMsg = Appends("s1", , "s2", "", "s3")
 ;     MsgBox Appends("", sMsg, "s4", , "s5")
 ;
; いいいいいいいいいいいいいいいいいいいいいいいいいいいいいい

; nasm -f bin Appends.asm -o Appends.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+12]  ; copy Str1 descriptor
   mov ebx, edx      ; zero sub-string count
   mov esi,[esi]     ; extract string pointer
   test esi,esi      ; validate string pointer
   jz _str2          ; skip if null str pointer
   mov ecx,[esi-4]   ; extract byte len of str
   test ecx,ecx      ; validate string length
   jz _str2          ; 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

  _str2:
   mov esi,[ebp+16]  ; copy Str2 descriptor
   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
   add 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 _alloc         ; skip if null str pointer
   mov ecx,[esi-4]   ; extract byte len of str
   test ecx,ecx      ; validate string length
   jz _alloc         ; 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

  _alloc:
   mov edi, edx      ; store total bytes needed
   shr edx, 1        ; convert to character count
   jz _exitp         ; zero total sub-string len
   mov eax, 8876543h ; api address patched on init
   push edx          ; SysAllocStringLen len param
   push 0            ; null string pointer (no copy)
   call eax          ; call SysAllocStringLen api
   add edi, eax      ; 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

  _s1:
   mov dx,[esi+ecx]  ; copy unicode character
   mov [edi+ecx],dx  ; write unicode character
   sub ecx, 2        ; reduce offset by one char
   jns _s1           ; 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

  _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

  _exitp:
   mov edx,[ebp+32]  ; copy string descriptor
   mov [edx],edi     ; return string pointer

   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, rc)

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

