user: Demonstrate the C code that generates the assembly output below:

```asm
<bn_mul_add_words>:
  endbr64
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x8,%rsp
  mov    %rdi,%rbx
  mov    %rsi,%r12
  mov    %edx,%ebp
  mov    %rcx,%r13
  mov    %edx,%edi
  not    %edi
  shr    $0x1f,%edi
  call   <assert@plt>
  mov    $0x0,%eax
  test   %ebp,%ebp
  jle    L41
  mov    %r13d,%edi
  mov    %r13,%rsi
  shr    $0x20,%rsi
  mov    $0x0,%ecx
  movabs $0x100000000,%r8
  jmp    L28
L89:
  mov    %r9,%r10
  shr    $0x20,%r10
  shl    $0x20,%r9
  add    %r9,%rdx
  adc    %r10,%rcx
  add    %rax,%rdx
  adc    $0x0,%rcx
  add    0x18(%rbx),%rdx
  adc    $0x0,%rcx
  mov    %rdx,0x18(%rbx)
  sub    $0x4,%ebp
  je     L13
  add    $0x20,%r12
  add    $0x20,%rbx
L28:
  mov    (%r12),%rax
  mov    %eax,%edx
  shr    $0x20,%rax
  mov    %rsi,%r9
  imul   %rdx,%r9
  imul   %rdi,%rdx
  mov    %rdi,%r10
  imul   %rax,%r10
  imul   %rsi,%rax
  add    %r10,%r9
  jae    L40
  add    %r8,%rax
L40:
  mov    %r9,%r10
  shr    $0x20,%r10
  shl    $0x20,%r9
  add    %r9,%rdx
  adc    %r10,%rax
  add    %rcx,%rdx
  adc    $0x0,%rax
  add    (%rbx),%rdx
  adc    $0x0,%rax
  mov    %rdx,(%rbx)
  cmp    $0x1,%ebp
  je     L41
  mov    0x8(%r12),%rdx
  mov    %edx,%ecx
  shr    $0x20,%rdx
  mov    %rsi,%r9
  imul   %rcx,%r9
  imul   %rdi,%rcx
  mov    %rdi,%r10
  imul   %rdx,%r10
  imul   %rsi,%rdx
  add    %r10,%r9
  jae    L115
  add    %r8,%rdx
L115:
  mov    %r9,%r10
  shr    $0x20,%r10
  shl    $0x20,%r9
  add    %r9,%rcx
  adc    %r10,%rdx
  add    %rax,%rcx
  adc    $0x0,%rdx
  add    0x8(%rbx),%rcx
  adc    $0x0,%rdx
  mov    %rcx,0x8(%rbx)
  cmp    $0x2,%ebp
  je     L104
  mov    0x10(%r12),%rax
  mov    %eax,%ecx
  shr    $0x20,%rax
  mov    %rsi,%r9
  imul   %rcx,%r9
  imul   %rdi,%rcx
  mov    %rdi,%r10
  imul   %rax,%r10
  imul   %rsi,%rax
  add    %r10,%r9
  jae    L102
  add    %r8,%rax
L102:
  mov    %r9,%r10
  shr    $0x20,%r10
  shl    $0x20,%r9
  add    %r9,%rcx
  adc    %r10,%rax
  add    %rcx,%rdx
  adc    $0x0,%rax
  add    0x10(%rbx),%rdx
  adc    $0x0,%rax
  mov    %rdx,0x10(%rbx)
  cmp    $0x3,%ebp
  je     L41
  mov    0x18(%r12),%rcx
  mov    %ecx,%edx
  shr    $0x20,%rcx
  mov    %rsi,%r9
  imul   %rdx,%r9
  imul   %rdi,%rdx
  mov    %rdi,%r10
  imul   %rcx,%r10
  imul   %rsi,%rcx
  add    %r10,%r9
  jae    L89
  add    %r8,%rcx
  jmp    L89
L104:
  mov    %rdx,%rax
L41:
  add    $0x8,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  ret
L13:
  mov    %rcx,%rax
  jmp    L41
```

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