user: 请将以下的汇编代码转换成C语言代码:

```asm
<bn_mul_add_words>:
  endbr64
  mov    %edx,%r8d
  mov    %rcx,%r9
  mov    $0x0,%ecx
  test   %edx,%edx
  jle    L40
  test   $0xfffffffc,%edx
  je     L60
L46:
  mov    %r9,%rax
  mulq   (%rsi)
  add    %rax,%rcx
  adc    $0x0,%rdx
  add    %rcx,(%rdi)
  adc    $0x0,%rdx
  mov    %rdx,%r10
  mov    %r9,%rax
  mulq   0x8(%rsi)
  mov    %r10,%rcx
  add    %rax,%rcx
  adc    $0x0,%rdx
  add    %rcx,0x8(%rdi)
  adc    $0x0,%rdx
  mov    %rdx,%r10
  mov    %r9,%rax
  mulq   0x10(%rsi)
  add    %rax,%r10
  adc    $0x0,%rdx
  add    %r10,0x10(%rdi)
  adc    $0x0,%rdx
  mov    %rdx,%rcx
  mov    %r9,%rax
  mulq   0x18(%rsi)
  add    %rax,%rcx
  adc    $0x0,%rdx
  add    %rcx,0x18(%rdi)
  adc    $0x0,%rdx
  mov    %rdx,%rcx
  add    $0x20,%rsi
  add    $0x20,%rdi
  sub    $0x4,%r8d
  test   $0xfffffffc,%r8d
  jne    L46
  test   %r8d,%r8d
  jne    L42
L40:
  mov    %rcx,%rax
  ret
L60:
  mov    $0x0,%ecx
L42:
  mov    %r9,%rax
  mulq   (%rsi)
  add    %rax,%rcx
  adc    $0x0,%rdx
  add    %rcx,(%rdi)
  adc    $0x0,%rdx
  mov    %rdx,%r10
  mov    %rdx,%rcx
  cmp    $0x1,%r8d
  je     L40
  mov    %r9,%rax
  mulq   0x8(%rsi)
  add    %rax,%r10
  adc    $0x0,%rdx
  add    %r10,0x8(%rdi)
  adc    $0x0,%rdx
  mov    %rdx,%r11
  mov    %rdx,%rcx
  cmp    $0x2,%r8d
  je     L40
  mov    %r9,%rax
  mulq   0x10(%rsi)
  add    %rax,%r11
  adc    $0x0,%rdx
  add    %r11,0x10(%rdi)
  adc    $0x0,%rdx
  mov    %rdx,%rcx
  jmp    L40
```

assistant: ```c
unsigned long bn_mul_add_words(unsigned long *rp, const unsigned long *ap, int num, unsigned long w) {
  unsigned long c1 = 0;
  if (num <= 0)
    return (c1);
  while (num & ~3) {
    do {
      register unsigned long high, low;
      asm("mulq %3" : "=a"(low), "=d"(high) : "a"(w), "m"(ap[0]) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+r"(c1), "+d"(high) : "a"(low), "g"(0) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+m"(rp[0]), "+d"(high) : "r"(c1), "g"(0) : "cc");
      c1 = high;
    } while (0);
    do {
      register unsigned long high, low;
      asm("mulq %3" : "=a"(low), "=d"(high) : "a"(w), "m"(ap[1]) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+r"(c1), "+d"(high) : "a"(low), "g"(0) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+m"(rp[1]), "+d"(high) : "r"(c1), "g"(0) : "cc");
      c1 = high;
    } while (0);
    do {
      register unsigned long high, low;
      asm("mulq %3" : "=a"(low), "=d"(high) : "a"(w), "m"(ap[2]) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+r"(c1), "+d"(high) : "a"(low), "g"(0) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+m"(rp[2]), "+d"(high) : "r"(c1), "g"(0) : "cc");
      c1 = high;
    } while (0);
    do {
      register unsigned long high, low;
      asm("mulq %3" : "=a"(low), "=d"(high) : "a"(w), "m"(ap[3]) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+r"(c1), "+d"(high) : "a"(low), "g"(0) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+m"(rp[3]), "+d"(high) : "r"(c1), "g"(0) : "cc");
      c1 = high;
    } while (0);
    ap += 4;
    rp += 4;
    num -= 4;
  }
  if (num) {
    do {
      register unsigned long high, low;
      asm("mulq %3" : "=a"(low), "=d"(high) : "a"(w), "m"(ap[0]) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+r"(c1), "+d"(high) : "a"(low), "g"(0) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+m"(rp[0]), "+d"(high) : "r"(c1), "g"(0) : "cc");
      c1 = high;
    } while (0);
    if (--num == 0)
      return c1;
    do {
      register unsigned long high, low;
      asm("mulq %3" : "=a"(low), "=d"(high) : "a"(w), "m"(ap[1]) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+r"(c1), "+d"(high) : "a"(low), "g"(0) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+m"(rp[1]), "+d"(high) : "r"(c1), "g"(0) : "cc");
      c1 = high;
    } while (0);
    if (--num == 0)
      return c1;
    do {
      register unsigned long high, low;
      asm("mulq %3" : "=a"(low), "=d"(high) : "a"(w), "m"(ap[2]) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+r"(c1), "+d"(high) : "a"(low), "g"(0) : "cc");
      asm("addq %2,%0; adcq %3,%1" : "+m"(rp[2]), "+d"(high) : "r"(c1), "g"(0) : "cc");
      c1 = high;
    } while (0);
    return c1;
  }
  return (c1);
}
```