user: What would the C source look like for the assembly code provided here?

```asm
<bn_mul_words>:
  endbr64
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x8,%rsp
  mov    %rdi,%rbp
  mov    %rsi,%r12
  mov    %edx,%ebx
  mov    %rcx,%r13
  mov    %edx,%edi
  not    %edi
  shr    $0x1f,%edi
  call   <assert@plt>
  mov    $0x0,%edx
  test   %ebx,%ebx
  jle    L21
  movzwl %r13w,%esi
  shr    $0x10,%r13
  movzwl %r13w,%ecx
L31:
  mov    (%r12),%rax
  movzwl %ax,%edi
  shr    $0x10,%rax
  movzwl %ax,%eax
  mov    %rsi,%r9
  imul   %rdi,%r9
  mov    %rsi,%r8
  imul   %rax,%r8
  imul   %rcx,%rax
  imul   %rcx,%rdi
  lea    (%rdi,%r8,1),%edi
  lea    0x10000(%rax),%r10
  cmp    %rdi,%r8
  cmova  %r10,%rax
  mov    %rdi,%r8
  shr    $0x10,%r8
  shl    $0x10,%rdi
  mov    %edi,%r10d
  lea    (%r9,%rdi,1),%edi
  cmp    %r10,%rdi
  adc    %r8,%rax
  lea    (%rdx,%rdi,1),%edi
  cmp    %rdx,%rdi
  adc    $0x0,%rax
  mov    %eax,%edx
  mov    %rdi,0x0(%rbp)
  cmp    $0x1,%ebx
  je     L21
  mov    0x8(%r12),%rax
  movzwl %ax,%edi
  shr    $0x10,%rax
  movzwl %ax,%eax
  mov    %rsi,%r9
  imul   %rdi,%r9
  mov    %rsi,%r8
  imul   %rax,%r8
  imul   %rcx,%rax
  imul   %rcx,%rdi
  lea    (%rdi,%r8,1),%edi
  lea    0x10000(%rax),%r10
  cmp    %rdi,%r8
  cmova  %r10,%rax
  mov    %rdi,%r8
  shr    $0x10,%r8
  shl    $0x10,%rdi
  mov    %edi,%r10d
  lea    (%r9,%rdi,1),%edi
  cmp    %r10,%rdi
  adc    %r8,%rax
  lea    (%rdx,%rdi,1),%edi
  cmp    %rdx,%rdi
  adc    $0x0,%rax
  mov    %eax,%edx
  mov    %rdi,0x8(%rbp)
  cmp    $0x2,%ebx
  je     L21
  mov    0x10(%r12),%rax
  movzwl %ax,%edi
  shr    $0x10,%rax
  movzwl %ax,%eax
  mov    %rsi,%r9
  imul   %rdi,%r9
  mov    %rsi,%r8
  imul   %rax,%r8
  imul   %rcx,%rax
  imul   %rcx,%rdi
  lea    (%rdi,%r8,1),%edi
  lea    0x10000(%rax),%r10
  cmp    %rdi,%r8
  cmova  %r10,%rax
  mov    %rdi,%r8
  shr    $0x10,%r8
  shl    $0x10,%rdi
  mov    %edi,%r10d
  lea    (%r9,%rdi,1),%edi
  cmp    %r10,%rdi
  adc    %r8,%rax
  lea    (%rdx,%rdi,1),%edi
  cmp    %rdx,%rdi
  adc    $0x0,%rax
  mov    %eax,%edx
  mov    %rdi,0x10(%rbp)
  cmp    $0x3,%ebx
  je     L21
  mov    0x18(%r12),%rax
  movzwl %ax,%edi
  shr    $0x10,%rax
  movzwl %ax,%eax
  mov    %rsi,%r9
  imul   %rdi,%r9
  mov    %rsi,%r8
  imul   %rax,%r8
  imul   %rcx,%rax
  imul   %rcx,%rdi
  lea    (%rdi,%r8,1),%edi
  lea    0x10000(%rax),%r10
  cmp    %rdi,%r8
  cmova  %r10,%rax
  mov    %rdi,%r8
  shr    $0x10,%r8
  shl    $0x10,%rdi
  mov    %edi,%r10d
  lea    (%r9,%rdi,1),%edi
  cmp    %r10,%rdi
  adc    %r8,%rax
  lea    (%rdx,%rdi,1),%edi
  cmp    %rdx,%rdi
  adc    $0x0,%rax
  mov    %eax,%edx
  mov    %rdi,0x18(%rbp)
  sub    $0x4,%ebx
  je     L21
  add    $0x20,%r12
  add    $0x20,%rbp
  jmp    L31
L21:
  mov    %rdx,%rax
  add    $0x8,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  ret
```

assistant: ```c
unsigned long bn_mul_words(unsigned long *rp, const unsigned long *ap, int num, unsigned long w) {
  unsigned long carry = 0;
  unsigned long bl, bh;
  assert(num >= 0);
  if (num <= 0)
    return ((unsigned long)0);
  bl = ((w) & (0xffff));
  bh = (((w) >> 16) & (0xffff));
  for (;;) {
    {
      unsigned long l, h;
      h = (ap[0]);
      l = ((h) & (0xffff));
      h = (((h) >> 16) & (0xffff));
      {
        unsigned long m, m1, lt, ht;
        lt = l;
        ht = h;
        m = ((bh)) * (lt);
        lt = ((bl)) * (lt);
        m1 = ((bl)) * (ht);
        ht = ((bh)) * (ht);
        m = (m + m1) & (0xffffffffL);
        if (m < m1)
          ht += ((((unsigned long)1) << 16) & (0xffffffffL));
        ht += (((m) >> 16) & (0xffff));
        m1 = (((m) << 16) & (0xffffffffL));
        lt = (lt + m1) & (0xffffffffL);
        if (lt < m1)
          ht++;
        (l) = lt;
        (h) = ht;
      };
      l += (carry);
      if ((l & (0xffffffffL)) < (carry))
        h++;
      (carry) = h & (0xffffffffL);
      (rp[0]) = l & (0xffffffffL);
    };
    if (--num == 0)
      break;
    {
      unsigned long l, h;
      h = (ap[1]);
      l = ((h) & (0xffff));
      h = (((h) >> 16) & (0xffff));
      {
        unsigned long m, m1, lt, ht;
        lt = l;
        ht = h;
        m = ((bh)) * (lt);
        lt = ((bl)) * (lt);
        m1 = ((bl)) * (ht);
        ht = ((bh)) * (ht);
        m = (m + m1) & (0xffffffffL);
        if (m < m1)
          ht += ((((unsigned long)1) << 16) & (0xffffffffL));
        ht += (((m) >> 16) & (0xffff));
        m1 = (((m) << 16) & (0xffffffffL));
        lt = (lt + m1) & (0xffffffffL);
        if (lt < m1)
          ht++;
        (l) = lt;
        (h) = ht;
      };
      l += (carry);
      if ((l & (0xffffffffL)) < (carry))
        h++;
      (carry) = h & (0xffffffffL);
      (rp[1]) = l & (0xffffffffL);
    };
    if (--num == 0)
      break;
    {
      unsigned long l, h;
      h = (ap[2]);
      l = ((h) & (0xffff));
      h = (((h) >> 16) & (0xffff));
      {
        unsigned long m, m1, lt, ht;
        lt = l;
        ht = h;
        m = ((bh)) * (lt);
        lt = ((bl)) * (lt);
        m1 = ((bl)) * (ht);
        ht = ((bh)) * (ht);
        m = (m + m1) & (0xffffffffL);
        if (m < m1)
          ht += ((((unsigned long)1) << 16) & (0xffffffffL));
        ht += (((m) >> 16) & (0xffff));
        m1 = (((m) << 16) & (0xffffffffL));
        lt = (lt + m1) & (0xffffffffL);
        if (lt < m1)
          ht++;
        (l) = lt;
        (h) = ht;
      };
      l += (carry);
      if ((l & (0xffffffffL)) < (carry))
        h++;
      (carry) = h & (0xffffffffL);
      (rp[2]) = l & (0xffffffffL);
    };
    if (--num == 0)
      break;
    {
      unsigned long l, h;
      h = (ap[3]);
      l = ((h) & (0xffff));
      h = (((h) >> 16) & (0xffff));
      {
        unsigned long m, m1, lt, ht;
        lt = l;
        ht = h;
        m = ((bh)) * (lt);
        lt = ((bl)) * (lt);
        m1 = ((bl)) * (ht);
        ht = ((bh)) * (ht);
        m = (m + m1) & (0xffffffffL);
        if (m < m1)
          ht += ((((unsigned long)1) << 16) & (0xffffffffL));
        ht += (((m) >> 16) & (0xffff));
        m1 = (((m) << 16) & (0xffffffffL));
        lt = (lt + m1) & (0xffffffffL);
        if (lt < m1)
          ht++;
        (l) = lt;
        (h) = ht;
      };
      l += (carry);
      if ((l & (0xffffffffL)) < (carry))
        h++;
      (carry) = h & (0xffffffffL);
      (rp[3]) = l & (0xffffffffL);
    };
    if (--num == 0)
      break;
    ap += 4;
    rp += 4;
  }
  return (carry);
}
```