user: 请从给定的汇编指令推导出C源代码:

```asm
<bsearch_range>:
  endbr64
  push   %r15
  push   %r14
  mov    %rdi,%r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x28,%rsp
  mov    %rsi,0x10(%rsp)
  mov    0x68(%rsp),%r13
  mov    %rdx,0x8(%rsp)
  mov    %rcx,0x18(%rsp)
  mov    %r9,(%rsp)
  test   %r9,%r9
  je     L185
  mov    %r8,%rbp
  mov    %r9,%rbx
  xor    %r12d,%r12d
  nop
L46:
  mov    0x60(%rsp),%rsi
  lea    (%r12,%rbx,1),%rdx
  mov    %r14,%rdi
  shr    %rdx
  imul   %rdx,%rsi
  mov    %rdx,%r15
  add    %rbp,%rsi
  call   *%r13
  test   %eax,%eax
  jle    L127
  lea    0x1(%r15),%r12
  cmp    %rbx,%r12
  jb     L46
L141:
  xor    %eax,%eax
  cmp    %r12,(%rsp)
  jbe    L111
  mov    0x60(%rsp),%rcx
  imul   %r12,%rcx
  lea    0x0(%rbp,%rcx,1),%rax
L111:
  mov    0x8(%rsp),%rcx
  mov    0x10(%rsp),%rsi
  mov    %r14,%rdi
  mov    %rax,(%rcx)
  call   *%r13
  test   %eax,%eax
  jg     L114
  mov    (%rsp),%rax
  mov    %rbx,%r14
  mov    %rax,%r8
  cmp    %rbx,%rax
  jbe    L180
  nopl   0x0(%rax)
L64:
  mov    0x60(%rsp),%rsi
  lea    (%r8,%r14,1),%rdx
  mov    %r8,0x8(%rsp)
  shr    %rdx
  mov    0x10(%rsp),%rdi
  imul   %rdx,%rsi
  mov    %rdx,%r12
  add    %rbp,%rsi
  call   *%r13
  test   %eax,%eax
  js     L43
  mov    (%rsp),%rax
  mov    0x8(%rsp),%r8
  lea    0x1(%r12),%r14
  cmp    %r8,%rax
  cmova  %r8,%rax
  cmp    %r14,%rax
  ja     L64
L39:
  cmp    %r14,(%rsp)
  je     L182
  mov    0x60(%rsp),%r12
  mov    0x10(%rsp),%rdi
  imul   %r14,%r12
  add    %rbp,%r12
  mov    %r12,%rsi
  call   *%r13
  test   %eax,%eax
  jns    L79
L182:
  cmp    %r14,%rbx
  jae    L114
  lea    -0x1(%r14),%rcx
  imul   0x60(%rsp),%rcx
  lea    0x0(%rbp,%rcx,1),%r12
  jmp    L79
L127:
  mov    %r15,%rbx
  cmp    %r12,%r15
  ja     L46
  jmp    L141
  nopl   0x0(%rax)
L43:
  mov    (%rsp),%rax
  cmp    %r12,%rax
  cmova  %r12,%rax
  cmp    %r14,%rax
  jbe    L39
  mov    %r12,%r8
  jmp    L64
L185:
  movq   $0x0,(%rdx)
  call   *%r13
  nopw   0x0(%rax,%rax,1)
L114:
  xor    %r12d,%r12d
L79:
  mov    0x18(%rsp),%rax
  mov    %r12,(%rax)
  add    $0x28,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L180:
  je     L114
  imul   0x60(%rsp),%rbx
  mov    0x10(%rsp),%rdi
  lea    0x0(%rbp,%rbx,1),%r12
  mov    %r12,%rsi
  call   *%r13
  test   %eax,%eax
  jns    L79
  jmp    L114
```

assistant: ```c
void bsearch_range(const void *key1, const void *key2, void *p1, void *p2, const void *base, size_t nmemb, size_t size, int (*cmp)(const void *, const void *)) {
  const char *b = (const char *)base;
  size_t l1, u1, l2, u2;
  l1 = 0;
  u1 = nmemb;
  while (l1 < u1) {
    size_t idx = (l1 + u1) / 2;
    int comp = (*cmp)(key1, b + idx * size);
    if (comp <= 0)
      u1 = idx;
    else
      l1 = idx + 1;
  }
  if (l1 < nmemb)
    *(const void **)p1 = b + l1 * size;
  else
    *(const void **)p1 = NULL;
  if (((*cmp)(key1, key2)) > 0) {
    *(const void **)p2 = NULL;
    return;
  }
  l2 = u1;
  u2 = nmemb;
  while (l2 < u2 && l2 < nmemb) {
    size_t idx = (l2 + u2) / 2;
    int comp = (*cmp)(key2, b + idx * size);
    if (comp < 0)
      u2 = idx;
    else
      l2 = idx + 1;
  }
  if (l2 == nmemb || ((*cmp)(key2, b + l2 * size)) < 0) {
    if (l2 > u1)
      *(const void **)p2 = b + (l2 - 1) * size;
    else
      *(const void **)p2 = NULL;
  } else
    *(const void **)p2 = b + l2 * size;
}
```