user: Please show me the C implementation that matches the assembly code listed below:

```asm
<bn_mul_recursive>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x60,%rsp
  mov    %rdi,-0x38(%rbp)
  mov    %rsi,-0x40(%rbp)
  mov    %rdx,-0x48(%rbp)
  mov    %ecx,-0x4c(%rbp)
  mov    %r8,-0x58(%rbp)
  mov    -0x4c(%rbp),%eax
  mov    %eax,%edx
  shr    $0x1f,%edx
  add    %edx,%eax
  sar    %eax
  mov    %eax,-0x20(%rbp)
  cmpl   $0xf,-0x4c(%rbp)
  jg     L132
  mov    -0x4c(%rbp),%edi
  mov    -0x48(%rbp),%rcx
  mov    -0x4c(%rbp),%edx
  mov    -0x40(%rbp),%rsi
  mov    -0x38(%rbp),%rax
  mov    %edi,%r8d
  mov    %rax,%rdi
  call   <bn_mul_normal@plt>
  jmp    L91
L132:
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x40(%rbp),%rax
  lea    (%rdx,%rax,1),%rcx
  mov    -0x20(%rbp),%edx
  mov    -0x40(%rbp),%rax
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <bn_cmp_words@plt>
  mov    %eax,-0x2c(%rbp)
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x48(%rbp),%rax
  lea    (%rdx,%rax,1),%rcx
  mov    -0x20(%rbp),%edx
  mov    -0x48(%rbp),%rax
  mov    %rax,%rsi
  mov    %rcx,%rdi
  call   <bn_cmp_words@plt>
  mov    %eax,-0x1c(%rbp)
  movl   $0x0,-0x28(%rbp)
  mov    -0x28(%rbp),%eax
  mov    %eax,-0x24(%rbp)
  mov    -0x2c(%rbp),%edx
  mov    %edx,%eax
  add    %eax,%eax
  add    %eax,%edx
  mov    -0x1c(%rbp),%eax
  add    %edx,%eax
  add    $0x4,%eax
  cmp    $0x8,%eax
  ja     L113
  mov    %eax,%eax
  lea    0x0(,%rax,4),%rdx
  lea    D3(%rip),%rax
  mov    (%rdx,%rax,1),%eax
  cltq
  lea    D3(%rip),%rdx
  add    %rdx,%rax
  notrack jmp *%rax
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x40(%rbp),%rax
  lea    (%rdx,%rax,1),%rsi
  mov    -0x20(%rbp),%ecx
  mov    -0x40(%rbp),%rdx
  mov    -0x58(%rbp),%rax
  mov    %rax,%rdi
  call   <bn_sub_words@plt>
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x48(%rbp),%rax
  lea    (%rdx,%rax,1),%rsi
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x58(%rbp),%rax
  lea    (%rdx,%rax,1),%rdi
  mov    -0x20(%rbp),%edx
  mov    -0x48(%rbp),%rax
  mov    %edx,%ecx
  mov    %rsi,%rdx
  mov    %rax,%rsi
  call   <bn_sub_words@plt>
  jmp    L113
  movl   $0x1,-0x24(%rbp)
  jmp    L113
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x40(%rbp),%rax
  lea    (%rdx,%rax,1),%rsi
  mov    -0x20(%rbp),%ecx
  mov    -0x40(%rbp),%rdx
  mov    -0x58(%rbp),%rax
  mov    %rax,%rdi
  call   <bn_sub_words@plt>
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x48(%rbp),%rax
  lea    (%rdx,%rax,1),%rsi
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x58(%rbp),%rax
  lea    (%rdx,%rax,1),%rdi
  mov    -0x20(%rbp),%edx
  mov    -0x48(%rbp),%rax
  mov    %edx,%ecx
  mov    %rax,%rdx
  call   <bn_sub_words@plt>
  movl   $0x1,-0x28(%rbp)
  jmp    L113
  movl   $0x1,-0x24(%rbp)
  jmp    L113
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x40(%rbp),%rax
  lea    (%rdx,%rax,1),%rdi
  mov    -0x20(%rbp),%edx
  mov    -0x40(%rbp),%rsi
  mov    -0x58(%rbp),%rax
  mov    %edx,%ecx
  mov    %rdi,%rdx
  mov    %rax,%rdi
  call   <bn_sub_words@plt>
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x48(%rbp),%rax
  lea    (%rdx,%rax,1),%rsi
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x58(%rbp),%rax
  lea    (%rdx,%rax,1),%rdi
  mov    -0x20(%rbp),%edx
  mov    -0x48(%rbp),%rax
  mov    %edx,%ecx
  mov    %rsi,%rdx
  mov    %rax,%rsi
  call   <bn_sub_words@plt>
  movl   $0x1,-0x28(%rbp)
  jmp    L113
  movl   $0x1,-0x24(%rbp)
  jmp    L113
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x40(%rbp),%rax
  lea    (%rdx,%rax,1),%rdi
  mov    -0x20(%rbp),%edx
  mov    -0x40(%rbp),%rsi
  mov    -0x58(%rbp),%rax
  mov    %edx,%ecx
  mov    %rdi,%rdx
  mov    %rax,%rdi
  call   <bn_sub_words@plt>
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x48(%rbp),%rax
  lea    (%rdx,%rax,1),%rsi
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x58(%rbp),%rax
  lea    (%rdx,%rax,1),%rdi
  mov    -0x20(%rbp),%edx
  mov    -0x48(%rbp),%rax
  mov    %edx,%ecx
  mov    %rax,%rdx
  call   <bn_sub_words@plt>
  nop
L113:
  mov    -0x4c(%rbp),%eax
  add    %eax,%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x58(%rbp),%rax
  add    %rdx,%rax
  mov    %rax,-0x18(%rbp)
  cmpl   $0x0,-0x24(%rbp)
  jne    L125
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x58(%rbp),%rax
  lea    (%rdx,%rax,1),%rsi
  mov    -0x4c(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x58(%rbp),%rax
  lea    (%rdx,%rax,1),%rdi
  mov    -0x18(%rbp),%rcx
  mov    -0x20(%rbp),%edx
  mov    -0x58(%rbp),%rax
  mov    %rcx,%r8
  mov    %edx,%ecx
  mov    %rsi,%rdx
  mov    %rax,%rsi
  call   <bn_mul_recursive>
  jmp    L72
L125:
  mov    -0x4c(%rbp),%eax
  cltq
  shl    $0x3,%eax
  mov    %eax,%edx
  mov    -0x4c(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rcx
  mov    -0x58(%rbp),%rax
  add    %rcx,%rax
  mov    $0x0,%esi
  mov    %rax,%rdi
  call   <memset@plt>
L72:
  mov    -0x18(%rbp),%rdi
  mov    -0x20(%rbp),%ecx
  mov    -0x48(%rbp),%rdx
  mov    -0x40(%rbp),%rsi
  mov    -0x38(%rbp),%rax
  mov    %rdi,%r8
  mov    %rax,%rdi
  call   <bn_mul_recursive>
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x48(%rbp),%rax
  add    %rax,%rdx
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rcx
  mov    -0x40(%rbp),%rax
  lea    (%rcx,%rax,1),%rsi
  mov    -0x4c(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rcx
  mov    -0x38(%rbp),%rax
  lea    (%rcx,%rax,1),%rdi
  mov    -0x18(%rbp),%rcx
  mov    -0x20(%rbp),%eax
  mov    %rcx,%r8
  mov    %eax,%ecx
  call   <bn_mul_recursive>
  mov    -0x4c(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x38(%rbp),%rax
  lea    (%rdx,%rax,1),%rdi
  mov    -0x4c(%rbp),%edx
  mov    -0x38(%rbp),%rsi
  mov    -0x58(%rbp),%rax
  mov    %edx,%ecx
  mov    %rdi,%rdx
  mov    %rax,%rdi
  call   <bn_add_words@plt>
  mov    %eax,-0x2c(%rbp)
  cmpl   $0x0,-0x28(%rbp)
  je     L12
  mov    -0x4c(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x58(%rbp),%rax
  lea    (%rdx,%rax,1),%rsi
  mov    -0x4c(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x58(%rbp),%rax
  lea    (%rdx,%rax,1),%rdi
  mov    -0x4c(%rbp),%edx
  mov    -0x58(%rbp),%rax
  mov    %edx,%ecx
  mov    %rsi,%rdx
  mov    %rax,%rsi
  call   <bn_sub_words@plt>
  sub    %eax,-0x2c(%rbp)
  jmp    L62
L12:
  mov    -0x4c(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x58(%rbp),%rax
  lea    (%rdx,%rax,1),%rsi
  mov    -0x4c(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x58(%rbp),%rax
  lea    (%rdx,%rax,1),%rdi
  mov    -0x4c(%rbp),%edx
  mov    -0x58(%rbp),%rax
  mov    %edx,%ecx
  mov    %rax,%rdx
  call   <bn_add_words@plt>
  add    %eax,-0x2c(%rbp)
L62:
  mov    -0x4c(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x58(%rbp),%rax
  add    %rax,%rdx
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rcx
  mov    -0x38(%rbp),%rax
  lea    (%rcx,%rax,1),%rsi
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x0(,%rax,8),%rcx
  mov    -0x38(%rbp),%rax
  lea    (%rcx,%rax,1),%rdi
  mov    -0x4c(%rbp),%eax
  mov    %eax,%ecx
  call   <bn_add_words@plt>
  add    %eax,-0x2c(%rbp)
  cmpl   $0x0,-0x2c(%rbp)
  je     L91
  mov    -0x20(%rbp),%edx
  mov    -0x4c(%rbp),%eax
  add    %edx,%eax
  cltq
  lea    0x0(,%rax,8),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    %rax,-0x18(%rbp)
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  mov    %rax,-0x10(%rbp)
  mov    -0x2c(%rbp),%eax
  movslq %eax,%rdx
  mov    -0x10(%rbp),%rax
  add    %rdx,%rax
  and    $0xffffffff,%eax
  mov    %rax,-0x8(%rbp)
  mov    -0x18(%rbp),%rax
  mov    -0x8(%rbp),%rdx
  mov    %rdx,(%rax)
  mov    -0x2c(%rbp),%eax
  cltq
  cmp    %rax,-0x8(%rbp)
  jae    L91
L122:
  addq   $0x8,-0x18(%rbp)
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  mov    %rax,-0x10(%rbp)
  mov    -0x10(%rbp),%rax
  add    $0x1,%rax
  and    $0xffffffff,%eax
  mov    %rax,-0x8(%rbp)
  mov    -0x18(%rbp),%rax
  mov    -0x8(%rbp),%rdx
  mov    %rdx,(%rax)
  cmpq   $0x0,-0x8(%rbp)
  je     L122
L91:
  leave
  ret
```

assistant: ```c
void bn_mul_recursive(unsigned long *r, unsigned long *a, unsigned long *b, int n2, unsigned long *t) {
  int n = n2 / 2, c1, c2;
  unsigned int neg, zero;
  unsigned long ln, lo, *p;
  if (n2 < (16)) {
    bn_mul_normal(r, a, n2, b, n2);
    return;
  }
  c1 = bn_cmp_words(a, &(a[n]), n);
  c2 = bn_cmp_words(&(b[n]), b, n);
  zero = neg = 0;
  switch (c1 * 3 + c2) {
  case -4:
    bn_sub_words(t, &(a[n]), a, n);
    bn_sub_words(&(t[n]), b, &(b[n]), n);
    break;
  case -3:
    zero = 1;
    break;
  case -2:
    bn_sub_words(t, &(a[n]), a, n);
    bn_sub_words(&(t[n]), &(b[n]), b, n);
    neg = 1;
    break;
  case -1:
  case 0:
  case 1:
    zero = 1;
    break;
  case 2:
    bn_sub_words(t, a, &(a[n]), n);
    bn_sub_words(&(t[n]), b, &(b[n]), n);
    neg = 1;
    break;
  case 3:
    zero = 1;
    break;
  case 4:
    bn_sub_words(t, a, &(a[n]), n);
    bn_sub_words(&(t[n]), &(b[n]), b, n);
    break;
  }
  {
    p = &(t[n2 * 2]);
    if (!zero)
      bn_mul_recursive(&(t[n2]), t, &(t[n]), n, p);
    else
      memset(&(t[n2]), 0, n2 * sizeof(unsigned long));
    bn_mul_recursive(r, a, b, n, p);
    bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, p);
  }
  c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));
  if (neg) {
    c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));
  } else {
    c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2));
  }
  c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
  if (c1) {
    p = &(r[n + n2]);
    lo = *p;
    ln = (lo + c1) & (0xffffffffL);
    *p = ln;
    if (ln < (unsigned long)c1) {
      do {
        p++;
        lo = *p;
        ln = (lo + 1) & (0xffffffffL);
        *p = ln;
      } while (ln == 0);
    }
  }
}
```