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

```asm
<MD5_String2binary>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0xb0,%rsp
  mov    %rdi,-0xa8(%rbp)
  mov    %rsi,-0xb0(%rbp)
  mov    %fs:0x28,%rax
  mov    %rax,-0x8(%rbp)
  xor    %eax,%eax
  lea    -0x60(%rbp),%rax
  mov    %rax,-0x80(%rbp)
  lea    -0x60(%rbp),%rax
  add    $0x4,%rax
  mov    %rax,-0x78(%rbp)
  lea    -0x60(%rbp),%rax
  add    $0x8,%rax
  mov    %rax,-0x70(%rbp)
  lea    -0x60(%rbp),%rax
  add    $0xc,%rax
  mov    %rax,-0x68(%rbp)
  mov    -0x80(%rbp),%rax
  movl   $0x67452301,(%rax)
  mov    -0x78(%rbp),%rax
  movl   $0xefcdab89,(%rax)
  mov    -0x70(%rbp),%rax
  movl   $0x98badcfe,(%rax)
  mov    -0x68(%rbp),%rax
  movl   $0x10325476,(%rax)
  mov    -0xa8(%rbp),%rax
  mov    %rax,%rdi
  call   <strlen@plt>
  mov    %eax,-0x90(%rbp)
  mov    -0xa8(%rbp),%rax
  mov    %rax,-0x88(%rbp)
  mov    -0x90(%rbp),%eax
  mov    %eax,-0x94(%rbp)
  jmp    L32
L48:
  mov    -0x68(%rbp),%rdi
  mov    -0x70(%rbp),%rcx
  mov    -0x78(%rbp),%rdx
  mov    -0x80(%rbp),%rsi
  mov    -0x88(%rbp),%rax
  mov    %rdi,%r8
  mov    %rax,%rdi
  call   <MD5_Round_Calculate@plt>
  subl   $0x40,-0x94(%rbp)
  addq   $0x40,-0x88(%rbp)
L32:
  cmpl   $0x3f,-0x94(%rbp)
  jg     L48
  mov    -0x90(%rbp),%eax
  and    $0x3f,%eax
  mov    %eax,-0x8c(%rbp)
  mov    -0x8c(%rbp),%edx
  mov    -0x88(%rbp),%rcx
  lea    -0x50(%rbp),%rax
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <strncpy@plt>
  mov    $0x40,%eax
  sub    -0x8c(%rbp),%eax
  mov    %eax,%edx
  mov    -0x8c(%rbp),%eax
  lea    -0x50(%rbp),%rcx
  add    %rcx,%rax
  mov    $0x0,%esi
  mov    %rax,%rdi
  call   <memset@plt>
  mov    -0x8c(%rbp),%eax
  movzbl -0x50(%rbp,%rax,1),%eax
  or     $0xffffff80,%eax
  mov    %eax,%edx
  mov    -0x8c(%rbp),%eax
  mov    %dl,-0x50(%rbp,%rax,1)
  cmpl   $0x37,-0x8c(%rbp)
  jbe    L27
  mov    -0x68(%rbp),%rdi
  mov    -0x70(%rbp),%rcx
  mov    -0x78(%rbp),%rdx
  mov    -0x80(%rbp),%rsi
  lea    -0x50(%rbp),%rax
  mov    %rdi,%r8
  mov    %rax,%rdi
  call   <MD5_Round_Calculate@plt>
  lea    -0x50(%rbp),%rax
  mov    $0x38,%edx
  mov    $0x0,%esi
  mov    %rax,%rdi
  call   <memset@plt>
L27:
  mov    -0x90(%rbp),%eax
  shl    $0x3,%eax
  mov    %eax,-0x9c(%rbp)
  lea    -0x9c(%rbp),%rax
  lea    -0x50(%rbp),%rdx
  lea    0x38(%rdx),%rcx
  mov    $0x4,%edx
  mov    %rax,%rsi
  mov    %rcx,%rdi
  call   <memcpy@plt>
  cmpl   $0x1fffffff,-0x90(%rbp)
  jbe    L42
  mov    -0x90(%rbp),%eax
  sub    $0x1fffffff,%eax
  shl    $0x3,%eax
  mov    %eax,-0x98(%rbp)
  lea    -0x98(%rbp),%rax
  lea    -0x50(%rbp),%rdx
  lea    0x3c(%rdx),%rcx
  mov    $0x4,%edx
  mov    %rax,%rsi
  mov    %rcx,%rdi
  call   <memcpy@plt>
  jmp    L12
L42:
  lea    -0x50(%rbp),%rax
  add    $0x3c,%rax
  mov    $0x4,%edx
  mov    $0x0,%esi
  mov    %rax,%rdi
  call   <memset@plt>
L12:
  mov    -0x68(%rbp),%rdi
  mov    -0x70(%rbp),%rcx
  mov    -0x78(%rbp),%rdx
  mov    -0x80(%rbp),%rsi
  lea    -0x50(%rbp),%rax
  mov    %rdi,%r8
  mov    %rax,%rdi
  call   <MD5_Round_Calculate@plt>
  lea    -0x60(%rbp),%rcx
  mov    -0xb0(%rbp),%rax
  mov    $0x10,%edx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <memcpy@plt>
  nop
  mov    -0x8(%rbp),%rax
  sub    %fs:0x28,%rax
  je     L57
  call   <__stack_chk_fail@plt>
L57:
  leave
  ret
```

assistant: ```c
void MD5_String2binary(const char *string, unsigned char *output) {
  unsigned char padding_message[64];
  const unsigned char *pstring;
  unsigned int string_byte_len, string_bit_len, copy_len, msg_digest[4];
  unsigned int *A = &msg_digest[0], *B = &msg_digest[1], *C = &msg_digest[2], *D = &msg_digest[3];
  int i;
  *A = 0x67452301;
  *B = 0xefcdab89;
  *C = 0x98badcfe;
  *D = 0x10325476;
  string_byte_len = (unsigned int)strlen(string);
  pstring = (const unsigned char *)string;
  for (i = string_byte_len; 64 <= i; i -= 64, pstring += 64)
    MD5_Round_Calculate(pstring, A, B, C, D);
  copy_len = string_byte_len % 64;
  strncpy((char *)padding_message, (const char *)pstring, copy_len);
  memset(padding_message + copy_len, 0, 64 - copy_len);
  padding_message[copy_len] |= 0x80;
  if (56 <= copy_len) {
    MD5_Round_Calculate(padding_message, A, B, C, D);
    memset(padding_message, 0, 56);
  }
  string_bit_len = string_byte_len * 8;
  memcpy(&padding_message[56], &string_bit_len, 4);
  if (0xffffffff / 8 < string_byte_len) {
    unsigned int high = (string_byte_len - 0xffffffff / 8) * 8;
    memcpy(&padding_message[60], &high, 4);
  } else
    memset(&padding_message[60], 0, 4);
  MD5_Round_Calculate(padding_message, A, B, C, D);
  memcpy(output, msg_digest, 16);
}
```