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

```asm
<cbssort>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x68,%rsp
  mov    %rdi,0x20(%rsp)
  mov    %esi,0x2c(%rsp)
  mov    %edx,0x3c(%rsp)
  mov    %rcx,%r14
  test   %rdi,%rdi
  je     L78
  mov    %edx,%ebx
  test   %esi,%esi
  js     L78
  test   %edx,%edx
  setg   %al
  test   %rcx,%rcx
  setne  %dil
  movzbl %dil,%edi
  and    %eax,%edi
  call   <assert@plt>
  mov    %ebx,%edi
  call   <malloc@plt>
  mov    %rax,0x40(%rsp)
  test   %rax,%rax
  je     L53
  mov    0x2c(%rsp),%eax
  lea    -0x1(%rax),%edx
  movslq %edx,%rax
  imul   $0x55555556,%rax,%rax
  shr    $0x20,%rax
  sar    $0x1f,%edx
  mov    %eax,%r15d
  sub    %edx,%r15d
  jmp    L62
L78:
  mov    $0x0,%edi
  call   <assert@plt>
  mov    0x3c(%rsp),%edi
  call   <malloc@plt>
  mov    %rax,0x40(%rsp)
  test   %rax,%rax
  je     L53
L3:
  mov    0x2c(%rsp),%ecx
  lea    -0x1(%rcx),%edx
  movslq %edx,%rax
  imul   $0x55555556,%rax,%rax
  shr    $0x20,%rax
  sar    $0x1f,%edx
  mov    %eax,%r15d
  sub    %edx,%r15d
  cmp    $0xffffffff,%ecx
  jge    L62
L19:
  mov    0x40(%rsp),%rdi
  call   <free@plt>
  add    $0x68,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L53:
  lea    D5(%rip),%rdi
  call   <cbmyfatal@plt>
  jmp    L3
L104:
  mov    %r12d,0xc(%rsp)
  jmp    L7
L175:
  mov    0x4c(%rsp),%r12d
  mov    0x50(%rsp),%r13
L7:
  mov    0xc(%rsp),%eax
  mov    0x3c(%rsp),%edx
  imul   %edx,%eax
  movslq %eax,%rdi
  add    0x20(%rsp),%rdi
  mov    0x40(%rsp),%rsi
  call   <memcpy@plt>
L181:
  add    %r15d,%r12d
  mov    0x30(%rsp),%rcx
  add    %rcx,%r13
  add    %rcx,(%rsp)
  mov    0x38(%rsp),%edx
  add    %edx,0x28(%rsp)
  cmp    %r12d,0x2c(%rsp)
  jle    L188
L180:
  mov    0x20(%rsp),%rax
  lea    0x0(%r13,%rax,1),%rbx
  mov    (%rsp),%rdi
  add    %rax,%rdi
  mov    %rbx,%rsi
  call   *%r14
  test   %eax,%eax
  jle    L181
  mov    0x3c(%rsp),%edx
  mov    %rbx,%rsi
  mov    0x40(%rsp),%rdi
  call   <memcpy@plt>
  cmp    %r12d,%r15d
  jg     L104
  movslq 0x28(%rsp),%rbx
  add    0x20(%rsp),%rbx
  mov    %r12d,%ebp
  mov    %r13,%rax
  sub    (%rsp),%rax
  mov    %rax,0x10(%rsp)
  mov    %r12d,0x4c(%rsp)
  mov    %r13,0x50(%rsp)
  mov    0x40(%rsp),%r12
  mov    0x3c(%rsp),%r13d
L120:
  mov    %ebp,0xc(%rsp)
  sub    %r15d,%ebp
  mov    %r12,%rsi
  mov    %rbx,%rdi
  call   *%r14
  test   %eax,%eax
  js     L175
  mov    0x10(%rsp),%rax
  lea    (%rax,%rbx,1),%rdi
  mov    %r13d,%edx
  mov    %rbx,%rsi
  call   <memcpy@plt>
  add    0x18(%rsp),%rbx
  cmp    %r15d,%ebp
  jge    L120
  mov    0x4c(%rsp),%r12d
  mov    0x50(%rsp),%r13
  mov    %ebp,0xc(%rsp)
  jmp    L7
L188:
  addl   $0x1,0x48(%rsp)
  mov    0x48(%rsp),%eax
  mov    0x3c(%rsp),%edx
  add    %edx,0x58(%rsp)
  cmp    %eax,%r15d
  jle    L97
L122:
  mov    0x48(%rsp),%r12d
  add    0x5c(%rsp),%r12d
  cmp    %r12d,0x2c(%rsp)
  jle    L188
  mov    0x38(%rsp),%eax
  mov    0x58(%rsp),%esi
  add    %esi,%eax
  movslq %eax,%r13
  mov    %esi,%eax
  movslq %esi,%rsi
  mov    %rsi,(%rsp)
  mov    %eax,0x28(%rsp)
  jmp    L180
L97:
  cmp    $0x1,%r15d
  jle    L19
  lea    -0x1(%r15),%edx
  movslq %edx,%rax
  imul   $0x55555556,%rax,%rax
  shr    $0x20,%rax
  sar    $0x1f,%edx
  mov    %eax,%r15d
  sub    %edx,%r15d
L62:
  cmp    $0x4,%r15d
  mov    $0x1,%eax
  cmovle %eax,%r15d
  mov    %r15d,0x5c(%rsp)
  mov    0x3c(%rsp),%ecx
  mov    %ecx,%eax
  imul   %r15d,%eax
  mov    %eax,0x38(%rsp)
  cltq
  mov    %rax,0x30(%rsp)
  mov    %r15d,%eax
  neg    %eax
  imul   %ecx,%eax
  cltq
  mov    %rax,0x18(%rsp)
  movl   $0x0,0x58(%rsp)
  movl   $0x0,0x48(%rsp)
  jmp    L122
```

tool_calls: name: disassemble_data
arguments: data_label: D5
type_guessed: string

tool: D5: out of memory

assistant: ```c
void cbssort(void *base, int nmemb, int size, int (*compar)(const void *, const void *)) {
  char *bp, *swap;
  int step, bottom, i, j;
  assert(base && nmemb >= 0 && size > 0 && compar);
  bp = (char *)base;
  (((swap) = malloc(size)) ? (swap) : cbmyfatal("out of memory"));
  for (step = (nmemb - 1) / 3; step >= 0; step = (step - 1) / 3) {
    if (step < 5)
      step = 1;
    for (bottom = 0; bottom < step; bottom++) {
      for (i = bottom + step; i < nmemb; i += step) {
        if (compar(bp + (i - step) * size, bp + i * size) > 0) {
          memcpy(swap, bp + i * size, size);
          for (j = i; j > step - 1; j -= step) {
            if (compar(bp + (j - step) * size, swap) < 0)
              break;
            memcpy(bp + j * size, bp + (j - step) * size, size);
          }
          memcpy(bp + j * size, swap, size);
        }
      }
    }
    if (step < 2)
      break;
  }
  free(swap);
}
```