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

```asm
<playfair_encipher>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x50,%rsp
  mov    %rdi,-0x38(%rbp)
  mov    %rsi,-0x40(%rbp)
  mov    %rdx,-0x48(%rbp)
  movl   $0x0,-0x20(%rbp)
  mov    -0x40(%rbp),%rax
  mov    %rax,%rdi
  call   <strlen@plt>
  mov    %eax,-0x1c(%rbp)
  movl   $0x0,-0x20(%rbp)
  jmp    L116
L146:
  mov    -0x20(%rbp),%eax
  movslq %eax,%rdx
  mov    -0x40(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  mov    %eax,%edi
  call   <tolower@plt>
  mov    %al,-0x22(%rbp)
  mov    -0x20(%rbp),%eax
  cltq
  lea    0x1(%rax),%rdx
  mov    -0x40(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  mov    %eax,%edi
  call   <tolower@plt>
  mov    %al,-0x21(%rbp)
  movsbl -0x22(%rbp),%edx
  mov    -0x38(%rbp),%rax
  mov    %edx,%esi
  mov    %rax,%rdi
  call   <strchr@plt>
  mov    %eax,%edx
  mov    -0x38(%rbp),%rax
  mov    %eax,%ecx
  mov    %edx,%eax
  sub    %ecx,%eax
  mov    %eax,-0x18(%rbp)
  movsbl -0x21(%rbp),%edx
  mov    -0x38(%rbp),%rax
  mov    %edx,%esi
  mov    %rax,%rdi
  call   <strchr@plt>
  mov    %eax,%edx
  mov    -0x38(%rbp),%rax
  mov    %eax,%ecx
  mov    %edx,%eax
  sub    %ecx,%eax
  mov    %eax,-0x14(%rbp)
  mov    -0x18(%rbp),%eax
  movslq %eax,%rdx
  imul   $0x66666667,%rdx,%rdx
  shr    $0x20,%rdx
  sar    %edx
  sar    $0x1f,%eax
  mov    %eax,%ecx
  mov    %edx,%eax
  sub    %ecx,%eax
  mov    %eax,-0x10(%rbp)
  mov    -0x14(%rbp),%eax
  movslq %eax,%rdx
  imul   $0x66666667,%rdx,%rdx
  shr    $0x20,%rdx
  sar    %edx
  sar    $0x1f,%eax
  mov    %eax,%ecx
  mov    %edx,%eax
  sub    %ecx,%eax
  mov    %eax,-0xc(%rbp)
  mov    -0x18(%rbp),%eax
  movslq %eax,%rdx
  imul   $0x66666667,%rdx,%rdx
  shr    $0x20,%rdx
  sar    %edx
  mov    %eax,%esi
  sar    $0x1f,%esi
  mov    %edx,%ecx
  sub    %esi,%ecx
  mov    %ecx,%edx
  shl    $0x2,%edx
  add    %ecx,%edx
  sub    %edx,%eax
  mov    %eax,-0x8(%rbp)
  mov    -0x14(%rbp),%eax
  movslq %eax,%rdx
  imul   $0x66666667,%rdx,%rdx
  shr    $0x20,%rdx
  sar    %edx
  mov    %eax,%esi
  sar    $0x1f,%esi
  mov    %edx,%ecx
  sub    %esi,%ecx
  mov    %ecx,%edx
  shl    $0x2,%edx
  add    %ecx,%edx
  sub    %edx,%eax
  mov    %eax,-0x4(%rbp)
  mov    -0x10(%rbp),%eax
  cmp    -0xc(%rbp),%eax
  jne    L88
  cmpl   $0x4,-0x8(%rbp)
  jne    L119
  mov    -0x18(%rbp),%eax
  cltq
  lea    -0x4(%rax),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  mov    -0x14(%rbp),%eax
  cltq
  lea    0x1(%rax),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rdx
  lea    0x1(%rdx),%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  jmp    L104
L119:
  cmpl   $0x4,-0x4(%rbp)
  jne    L129
  mov    -0x18(%rbp),%eax
  cltq
  lea    0x1(%rax),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  mov    -0x14(%rbp),%eax
  cltq
  lea    -0x4(%rax),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rdx
  lea    0x1(%rdx),%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  jmp    L104
L129:
  mov    -0x18(%rbp),%eax
  cltq
  lea    0x1(%rax),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  mov    -0x14(%rbp),%eax
  cltq
  lea    0x1(%rax),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rdx
  lea    0x1(%rdx),%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  jmp    L104
L88:
  mov    -0x8(%rbp),%eax
  cmp    -0x4(%rbp),%eax
  jne    L120
  cmpl   $0x4,-0x10(%rbp)
  jne    L36
  mov    -0x18(%rbp),%eax
  cltq
  lea    -0x14(%rax),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  mov    -0x14(%rbp),%eax
  cltq
  lea    0x5(%rax),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rdx
  lea    0x1(%rdx),%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  jmp    L104
L36:
  cmpl   $0x4,-0xc(%rbp)
  jne    L96
  mov    -0x18(%rbp),%eax
  cltq
  lea    0x5(%rax),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  mov    -0x14(%rbp),%eax
  cltq
  lea    -0x14(%rax),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rdx
  lea    0x1(%rdx),%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  jmp    L104
L96:
  mov    -0x18(%rbp),%eax
  cltq
  lea    0x5(%rax),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  mov    -0x14(%rbp),%eax
  cltq
  lea    0x5(%rax),%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rdx
  lea    0x1(%rdx),%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  jmp    L104
L120:
  mov    -0x10(%rbp),%edx
  mov    %edx,%eax
  shl    $0x2,%eax
  add    %eax,%edx
  mov    -0x4(%rbp),%eax
  add    %edx,%eax
  movslq %eax,%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
  mov    -0xc(%rbp),%edx
  mov    %edx,%eax
  shl    $0x2,%eax
  add    %eax,%edx
  mov    -0x8(%rbp),%eax
  add    %edx,%eax
  movslq %eax,%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  mov    -0x20(%rbp),%edx
  movslq %edx,%rdx
  lea    0x1(%rdx),%rcx
  mov    -0x48(%rbp),%rdx
  add    %rcx,%rdx
  movzbl (%rax),%eax
  mov    %al,(%rdx)
L104:
  addl   $0x2,-0x20(%rbp)
L116:
  mov    -0x20(%rbp),%eax
  cmp    -0x1c(%rbp),%eax
  jl     L146
  nop
L78:
  mov    -0x20(%rbp),%eax
  cmp    -0x1c(%rbp),%eax
  jl     L78
  mov    -0x1c(%rbp),%eax
  movslq %eax,%rdx
  mov    -0x48(%rbp),%rax
  add    %rdx,%rax
  movb   $0x0,(%rax)
  nop
  leave
  ret
```

assistant: ```c
void playfair_encipher(char *key, const char *plaintext, char *ciphertext) {
  int i = 0, length = strlen(plaintext);
  char a, b;
  int a_ind, b_ind, a_row, b_row, a_col, b_col;
  for (i = 0; i < length; i += 2) {
    a = tolower(plaintext[i]);
    b = tolower(plaintext[i + 1]);
    a_ind = (int)strchr(key, a) - (int)key;
    b_ind = (int)strchr(key, b) - (int)key;
    a_row = a_ind / 5;
    b_row = b_ind / 5;
    a_col = a_ind % 5;
    b_col = b_ind % 5;
    if (a_row == b_row) {
      if (a_col == 4) {
        ciphertext[i] = key[a_ind - 4];
        ciphertext[i + 1] = key[b_ind + 1];
      } else if (b_col == 4) {
        ciphertext[i] = key[a_ind + 1];
        ciphertext[i + 1] = key[b_ind - 4];
      } else {
        ciphertext[i] = key[a_ind + 1];
        ciphertext[i + 1] = key[b_ind + 1];
      }
    } else if (a_col == b_col) {
      if (a_row == 4) {
        ciphertext[i] = key[a_ind - 20];
        ciphertext[i + 1] = key[b_ind + 5];
      } else if (b_row == 4) {
        ciphertext[i] = key[a_ind + 5];
        ciphertext[i + 1] = key[b_ind - 20];
      } else {
        ciphertext[i] = key[a_ind + 5];
        ciphertext[i + 1] = key[b_ind + 5];
      }
    } else {
      ciphertext[i] = key[5 * a_row + b_col];
      ciphertext[i + 1] = key[5 * b_row + a_col];
    }
  }
  while (i < length)
    ;
  ciphertext[length] = '\0';
}
```