user: Translate the below assembly code into C programming language:

```asm
<rul__i18n_string_soundex>:
  endbr64
  push   %r14
  push   %r13
  push   %r12
  mov    %rdi,%r12
  xor    %edi,%edi
  push   %rbp
  push   %rbx
  sub    $0x220,%rsp
  mov    %fs:0x28,%rax
  mov    %rax,0x218(%rsp)
  xor    %eax,%eax
  test   %r12,%r12
  je     L67
  xor    %edi,%edi
  cmpb   $0x0,(%r12)
  setne  %dil
L67:
  call   <assert@plt>
  movsbl (%r12),%edi
  mov    %r12,%rbx
  xor    %ebp,%ebp
  test   %dil,%dil
  jne    L41
  jmp    L148
  nopl   0x0(%rax)
L4:
  movsbl (%rbx),%edi
  call   <is_multinational_alpha@plt>
  test   %eax,%eax
  jne    L167
  movsbl 0x1(%rbx),%edi
  add    $0x1,%rbx
  add    $0x1,%rbp
  test   %dil,%dil
  je     L148
L41:
  call   <isalpha@plt>
  test   %eax,%eax
  je     L4
L167:
  movsbl (%rbx),%edi
  test   %dil,%dil
  je     L148
  call   <multinational_to_upper@plt>
  movsbl 0x1(%r12,%rbp,1),%edi
  lea    0x1(%rbp),%r13
  mov    %al,0x110(%rsp)
  mov    %r13,%r14
  test   %dil,%dil
  je     L134
  mov    %rsp,%rbx
  nop
L137:
  call   <get_consonant_group@plt>
  mov    %al,(%rbx,%r14,1)
  add    $0x1,%r14
  movsbl (%r12,%r14,1),%edi
  test   %dil,%dil
  jne    L137
L134:
  movb   $0x0,(%rsp,%r14,1)
  movzbl (%rsp,%r13,1),%edx
  test   %dl,%dl
  je     L93
  lea    (%rsp,%rbp,1),%rcx
  mov    $0x1,%edi
  movzbl 0x2(%rcx),%eax
  cmp    %dl,%al
  je     L155
  cs nopw 0x0(%rax,%rax,1)
L150:
  lea    -0x31(%rdx),%esi
  cmp    $0x8,%sil
  ja     L33
  mov    %dl,0x110(%rsp,%rdi,1)
  add    $0x1,%rdi
L33:
  add    $0x1,%rcx
  test   %al,%al
  je     L165
  mov    %eax,%edx
L87:
  movzbl 0x2(%rcx),%eax
  cmp    %dl,%al
  jne    L150
L155:
  add    $0x1,%rcx
  mov    %eax,%edx
  jmp    L87
L93:
  mov    $0x1,%edi
  nopl   0x0(%rax,%rax,1)
L165:
  lea    0x110(%rsp),%rbp
  movb   $0x0,0x110(%rsp,%rdi,1)
  mov    %rbp,%rdi
  call   <strlen@plt>
  lea    0x1(%rax),%edi
  call   <rul__mem_malloc@plt>
  mov    %rbp,%rsi
  mov    %rax,%rdi
  mov    %rax,%r12
  call   <strcpy@plt>
L96:
  mov    0x218(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L39
  add    $0x220,%rsp
  mov    %r12,%rax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  ret
  nopl   0x0(%rax)
L148:
  mov    $0x1,%edi
  call   <rul__mem_malloc@plt>
  movb   $0x0,(%rax)
  mov    %rax,%r12
  jmp    L96
L39:
  call   <__stack_chk_fail@plt>
```

assistant: ```c
char *rul__i18n_string_soundex(char *str) {
  char in_buff[256 + 1];
  char out_buff[256 + 1];
  long i, start, out_index;
  char ch, *ret_str;
  assert(str && (str[0] != '\0'));
  i = 0;
  while (str[i] != '\0' && !isalpha(str[i]) && !is_multinational_alpha(str[i]))
    i++;
  if (str[i] == '\0') {
    ret_str = (char *)rul__mem_malloc(1);
    ret_str[0] = '\0';
    return (ret_str);
  }
  out_index = 1;
  out_buff[0] = multinational_to_upper(str[i]);
  start = i + 1;
  i = start;
  while ((ch = str[i]) != '\0') {
    in_buff[i] = get_consonant_group(ch);
    i++;
  }
  in_buff[i] = '\0';
  i = start;
  while ((ch = in_buff[i]) != '\0') {
    if (ch != in_buff[i + 1]) {
      if (ch > '0' && ch <= '9') {
        out_buff[out_index] = ch;
        out_index++;
      }
    }
    i++;
  }
  out_buff[out_index] = '\0';
  ret_str = rul__mem_malloc(strlen(out_buff) + 1);
  strcpy(ret_str, out_buff);
  return (ret_str);
}
```