user: 请从给定的汇编指令推导出C源代码:

```asm
<String_Concat>:
  endbr64
  push   %r12
  push   %rbp
  push   %rbx
  mov    %rsi,%rbx
  test   %rdi,%rdi
  je     L41
  mov    %rdi,%r12
  test   %rsi,%rsi
  je     L30
  call   <String_Length@plt>
  mov    %rbx,%rdi
  mov    %eax,%ebp
  call   <String_Length@plt>
  mov    %eax,%edx
  test   %eax,%eax
  jle    L170
  movslq %ebp,%rcx
  lea    0x1(%rbx),%rdi
  lea    -0x1(%rax),%eax
  add    %r12,%rcx
  mov    %rcx,%rsi
  sub    %rdi,%rsi
  cmp    $0xe,%rsi
  jbe    L149
  cmp    $0x6,%eax
  jbe    L149
  cmp    $0xe,%eax
  jbe    L182
  mov    %edx,%esi
  xor    %eax,%eax
  shr    $0x4,%esi
  shl    $0x4,%rsi
  nopl   0x0(%rax,%rax,1)
L111:
  movdqu (%rbx,%rax,1),%xmm0
  movups %xmm0,(%rcx,%rax,1)
  add    $0x10,%rax
  cmp    %rsi,%rax
  jne    L111
  mov    %edx,%eax
  and    $0xfffffff0,%eax
  mov    %eax,%esi
  lea    0x0(%rbp,%rax,1),%edi
  cmp    %eax,%edx
  je     L25
  mov    %edx,%r8d
  sub    %eax,%r8d
  lea    -0x1(%r8),%r9d
  cmp    $0x6,%r9d
  jbe    L35
L53:
  mov    (%rbx,%rax,1),%r9
  mov    %r9,(%rcx,%rax,1)
  mov    %r8d,%eax
  and    $0xfffffff8,%eax
  add    %eax,%edi
  add    %eax,%esi
  cmp    %eax,%r8d
  je     L25
L35:
  movslq %esi,%rcx
  lea    0x1(%rsi),%eax
  lea    0x1(%rdi),%r8d
  movzbl (%rbx,%rcx,1),%r9d
  movslq %edi,%rcx
  mov    %r9b,(%r12,%rcx,1)
  cmp    %edx,%eax
  jge    L25
  cltq
  lea    0x2(%rsi),%ecx
  lea    0x2(%rdi),%r9d
  movslq %r8d,%r8
  movzbl (%rbx,%rax,1),%eax
  mov    %al,(%r12,%r8,1)
  cmp    %ecx,%edx
  jle    L25
  movslq %ecx,%rcx
  lea    0x3(%rsi),%eax
  lea    0x3(%rdi),%r8d
  movslq %r9d,%r9
  movzbl (%rbx,%rcx,1),%ecx
  mov    %cl,(%r12,%r9,1)
  cmp    %eax,%edx
  jle    L25
  cltq
  lea    0x4(%rsi),%ecx
  lea    0x4(%rdi),%r9d
  movslq %r8d,%r8
  movzbl (%rbx,%rax,1),%eax
  mov    %al,(%r12,%r8,1)
  cmp    %ecx,%edx
  jle    L25
  movslq %ecx,%rcx
  lea    0x5(%rsi),%eax
  lea    0x5(%rdi),%r8d
  movslq %r9d,%r9
  movzbl (%rbx,%rcx,1),%ecx
  mov    %cl,(%r12,%r9,1)
  cmp    %eax,%edx
  jle    L25
  cltq
  movslq %r8d,%r8
  add    $0x6,%esi
  add    $0x6,%edi
  movzbl (%rbx,%rax,1),%eax
  mov    %al,(%r12,%r8,1)
  cmp    %esi,%edx
  jle    L25
  movslq %esi,%rsi
  movslq %edi,%rdi
  movzbl (%rbx,%rsi,1),%eax
  mov    %al,(%r12,%rdi,1)
L25:
  add    %edx,%ebp
  movslq %edx,%rdx
  add    %rdx,%rbx
L170:
  movzbl (%rbx),%eax
  movslq %ebp,%rbp
  mov    %al,(%r12,%rbp,1)
L30:
  mov    %r12,%rax
  pop    %rbx
  pop    %rbp
  pop    %r12
  ret
  nopw   0x0(%rax,%rax,1)
L149:
  mov    %edx,%edi
  xor    %eax,%eax
  nopl   0x0(%rax)
L45:
  movzbl (%rbx,%rax,1),%esi
  mov    %sil,(%rcx,%rax,1)
  add    $0x1,%rax
  cmp    %rdi,%rax
  jne    L45
  add    %edx,%ebp
  movslq %edx,%rdx
  add    %rdx,%rbx
  jmp    L170
  nopl   0x0(%rax,%rax,1)
L41:
  mov    %rsi,%r12
  pop    %rbx
  pop    %rbp
  mov    %r12,%rax
  pop    %r12
  ret
L182:
  mov    %edx,%r8d
  mov    %ebp,%edi
  xor    %eax,%eax
  xor    %esi,%esi
  jmp    L53
```

assistant: ```c
char *String_Concat(char *str1, char *str2) {
  if (str1 == NULL)
    return str2;
  if (str2 == NULL)
    return str1;
  int i = String_Length(str1);
  int j = String_Length(str2);
  int k = 0;
  while (k < j)
    str1[i++] = str2[k++];
  str1[i] = str2[k];
  return str1;
}
```