user: Translate the below assembly code into C programming language:

```asm
<sd_get_clock_divider>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x40,%rsp
  mov    %edi,-0x34(%rbp)
  mov    %esi,-0x38(%rbp)
  movl   $0x0,-0x28(%rbp)
  mov    -0x38(%rbp),%eax
  cmp    -0x34(%rbp),%eax
  jle    L121
  movl   $0x1,-0x28(%rbp)
  jmp    L106
L121:
  mov    -0x34(%rbp),%eax
  cltd
  idivl  -0x38(%rbp)
  mov    %eax,-0x28(%rbp)
  mov    -0x34(%rbp),%eax
  cltd
  idivl  -0x38(%rbp)
  mov    %edx,-0x18(%rbp)
  cmpl   $0x0,-0x18(%rbp)
  je     L106
  subl   $0x1,-0x28(%rbp)
L106:
  movl   $0xffffffff,-0x24(%rbp)
  movl   $0x1f,-0x20(%rbp)
  jmp    L11
L92:
  mov    -0x20(%rbp),%eax
  mov    $0x1,%edx
  mov    %eax,%ecx
  shl    %cl,%edx
  mov    %edx,%eax
  mov    %eax,-0x14(%rbp)
  mov    -0x28(%rbp),%eax
  and    -0x14(%rbp),%eax
  test   %eax,%eax
  je     L43
  mov    -0x20(%rbp),%eax
  mov    %eax,-0x24(%rbp)
  mov    -0x14(%rbp),%eax
  not    %eax
  and    %eax,-0x28(%rbp)
  cmpl   $0x0,-0x28(%rbp)
  je     L55
  addl   $0x1,-0x24(%rbp)
  jmp    L55
L43:
  subl   $0x1,-0x20(%rbp)
L11:
  cmpl   $0x0,-0x20(%rbp)
  jns    L92
  jmp    L21
L55:
  nop
L21:
  cmpl   $0xffffffff,-0x24(%rbp)
  jne    L73
  movl   $0x1f,-0x24(%rbp)
L73:
  cmpl   $0x1f,-0x24(%rbp)
  jle    L72
  movl   $0x1f,-0x24(%rbp)
L72:
  cmpl   $0x0,-0x24(%rbp)
  je     L8
  mov    -0x24(%rbp),%eax
  sub    $0x1,%eax
  mov    $0x1,%edx
  mov    %eax,%ecx
  shl    %cl,%edx
  mov    %edx,%eax
  mov    %eax,-0x24(%rbp)
L8:
  cmpl   $0x3ff,-0x24(%rbp)
  jle    L130
  movl   $0x3ff,-0x24(%rbp)
L130:
  mov    -0x24(%rbp),%eax
  movzbl %al,%eax
  mov    %eax,-0x10(%rbp)
  mov    -0x24(%rbp),%eax
  sar    $0x8,%eax
  and    $0x3,%eax
  mov    %eax,-0xc(%rbp)
  mov    -0x10(%rbp),%eax
  shl    $0x8,%eax
  mov    %eax,%edx
  mov    -0xc(%rbp),%eax
  shl    $0x6,%eax
  or     %edx,%eax
  mov    %eax,-0x8(%rbp)
  movl   $0x1,-0x1c(%rbp)
  cmpl   $0x0,-0x24(%rbp)
  je     L44
  mov    -0x24(%rbp),%eax
  add    %eax,%eax
  mov    %eax,-0x1c(%rbp)
L44:
  mov    -0x34(%rbp),%eax
  cltd
  idivl  -0x1c(%rbp)
  mov    %eax,-0x4(%rbp)
  mov    -0x8(%rbp),%edi
  mov    -0x4(%rbp),%esi
  mov    -0x24(%rbp),%ecx
  mov    -0x38(%rbp),%edx
  mov    -0x34(%rbp),%eax
  mov    %edi,%r9d
  mov    %esi,%r8d
  mov    %eax,%esi
  lea    D7(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x8(%rbp),%eax
  leave
  ret
```

tool_calls: name: extract_symbolic_data
arguments: tag: D7
datatype: string

tool: D7: EMMC: base_clock: %i, target_rate: %i, divisor: %08x, actual_clock: %i, ret: %08x


assistant: ```c
uint32_t sd_get_clock_divider(uint32_t base_clock, uint32_t target_rate) {
  uint32_t targetted_divisor = 0;
  if (target_rate > base_clock)
    targetted_divisor = 1;
  else {
    targetted_divisor = base_clock / target_rate;
    uint32_t mod = base_clock % target_rate;
    if (mod)
      targetted_divisor--;
  }
  if (1) {
    int divisor = -1;
    for (int first_bit = 31; first_bit >= 0; first_bit--) {
      uint32_t bit_test = (1 << first_bit);
      if (targetted_divisor & bit_test) {
        divisor = first_bit;
        targetted_divisor &= ~bit_test;
        if (targetted_divisor) {
          divisor++;
        }
        break;
      }
    }
    if (divisor == -1)
      divisor = 31;
    if (divisor >= 32)
      divisor = 31;
    if (divisor != 0)
      divisor = (1 << (divisor - 1));
    if (divisor >= 0x400)
      divisor = 0x3ff;
    uint32_t freq_select = divisor & 0xff;
    uint32_t upper_bits = (divisor >> 8) & 0x3;
    uint32_t ret = (freq_select << 8) | (upper_bits << 6) | (0 << 5);
    int denominator = 1;
    if (divisor != 0)
      denominator = divisor * 2;
    int actual_clock = base_clock / denominator;
    printf("EMMC: base_clock: %i, target_rate: %i, divisor: %08x, "
           "actual_clock: %i, ret: %08x\n",
           base_clock, target_rate, divisor, actual_clock, ret);
    return ret;
  } else {
    printf("EMMC: unsupported host version\n");
    return 0xffffffff;
  }
}
```