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

```asm
<serialOpen>:
  endbr64
  push   %r15
  push   %r14
  mov    %esi,%r14d
  push   %r13
  mov    %r8d,%r13d
  push   %r12
  push   %rbp
  mov    %edx,%ebp
  push   %rbx
  mov    %ecx,%ebx
  sub    $0x28,%rsp
  mov    %fs:0x28,%rax
  mov    %rax,0x18(%rsp)
  mov    D11(%rip),%rax
  mov    (%rax),%esi
  mov    D108(%rip),%rax
  or     (%rax),%esi
  mov    D238(%rip),%rax
  or     (%rax),%esi
  call   <open@plt>
  mov    %eax,%r12d
  test   %eax,%eax
  jg     L53
L137:
  mov    0x18(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L7
  add    $0x28,%rsp
  mov    %r12d,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopw   0x0(%rax,%rax,1)
L53:
  mov    D81(%rip),%rax
  xor    %edx,%edx
  mov    %r12d,%edi
  mov    %rsp,%r15
  mov    (%rax),%esi
  call   <fcntl@plt>
  mov    %r15,%rsi
  mov    %r12d,%edi
  call   <tcgetattr@plt>
  mov    %r15,%rdi
  call   <cfmakeraw@plt>
  mov    D95(%rip),%rdx
  mov    (%rsp),%rax
  mov    (%rdx),%rdx
  movl   $0x0,(%rax,%rdx,4)
  mov    D32(%rip),%rdx
  mov    (%rdx),%rdx
  movl   $0x14,(%rax,%rdx,4)
  cmp    $0x2580,%r14d
  je     L12
  ja     L71
  cmp    $0x708,%r14d
  je     L207
  cmp    $0x12c0,%r14d
  jne    L57
  mov    D301(%rip),%rax
  mov    (%rax),%r14d
  cs nopw 0x0(%rax,%rax,1)
L34:
  mov    %r14d,%esi
  mov    %r15,%rdi
  call   <cfsetispeed@plt>
  mov    %r14d,%esi
  mov    %r15,%rdi
  call   <cfsetospeed@plt>
  mov    D91(%rip),%rax
  mov    D276(%rip),%rcx
  mov    (%rax),%edx
  mov    D285(%rip),%rax
  or     (%rax),%edx
  mov    D21(%rip),%rax
  not    %edx
  and    0x8(%rsp),%edx
  mov    (%rax),%eax
  or     (%rcx),%eax
  not    %eax
  mov    D311(%rip),%rcx
  and    %eax,0xc(%rsp)
  mov    D338(%rip),%rax
  mov    (%rax),%eax
  or     (%rcx),%eax
  or     %edx,%eax
  mov    D56(%rip),%rdx
  mov    (%rdx),%edx
  not    %edx
  and    %edx,0x14(%rsp)
  cmp    $0x6,%ebp
  je     L215
  cmp    $0x7,%ebp
  je     L9
  cmp    $0x5,%ebp
  je     L77
  mov    D145(%rip),%rdx
  or     (%rdx),%eax
L139:
  mov    D274(%rip),%rdx
  mov    (%rdx),%ecx
  mov    %ecx,%edx
  or     %eax,%edx
  cmp    $0x65,%bl
  je     L190
  jg     L29
  cmp    $0x45,%bl
  je     L190
  cmp    $0x4f,%bl
  jne    L149
L309:
  mov    D146(%rip),%rax
  and    (%rax),%edx
L155:
  mov    D184(%rip),%rax
  mov    %edx,%ecx
  mov    %r12d,%edi
  mov    (%rax),%eax
  and    %eax,%ecx
  not    %eax
  and    %edx,%eax
  cmp    $0x2,%r13d
  mov    D163(%rip),%rdx
  cmove  %ecx,%eax
  mov    %eax,0x8(%rsp)
  mov    D176(%rip),%rax
  mov    (%rax),%eax
  or     (%rdx),%eax
  mov    D25(%rip),%rdx
  or     (%rdx),%eax
  mov    D159(%rip),%rdx
  or     (%rdx),%eax
  mov    %r15,%rdx
  not    %eax
  and    %eax,0x10(%rsp)
  mov    D31(%rip),%rax
  mov    (%rax),%esi
  call   <tcsetattr@plt>
  jmp    L137
  nopl   0x0(%rax,%rax,1)
L29:
  cmp    $0x6f,%bl
  je     L309
L149:
  not    %ecx
  and    %eax,%ecx
  mov    %ecx,%edx
  jmp    L155
  nopl   (%rax)
L57:
  cmp    $0x4b0,%r14d
  jne    L88
  mov    D106(%rip),%rax
  mov    (%rax),%r14d
  jmp    L34
  nopl   0x0(%rax)
L71:
  cmp    $0xe100,%r14d
  je     L235
  cmp    $0x1c200,%r14d
  jne    L91
  mov    D205(%rip),%rax
  mov    (%rax),%r14d
  jmp    L34
  nopl   (%rax)
L91:
  cmp    $0x9600,%r14d
  jne    L88
  mov    D324(%rip),%rax
  mov    (%rax),%r14d
  jmp    L34
L190:
  mov    D146(%rip),%rax
  mov    (%rax),%eax
  not    %eax
  and    %eax,%edx
  jmp    L155
  nopw   0x0(%rax,%rax,1)
L77:
  mov    D232(%rip),%rdx
  or     (%rdx),%eax
  jmp    L139
  cs nopw 0x0(%rax,%rax,1)
L9:
  mov    D249(%rip),%rdx
  or     (%rdx),%eax
  jmp    L139
  xchg   %ax,%ax
L215:
  mov    D294(%rip),%rdx
  or     (%rdx),%eax
  jmp    L139
  xchg   %ax,%ax
L88:
  mov    D263(%rip),%rax
  mov    (%rax),%r14d
  jmp    L34
  nop
L235:
  mov    D323(%rip),%rax
  mov    (%rax),%r14d
  jmp    L34
  nop
L12:
  mov    D231(%rip),%rax
  mov    (%rax),%r14d
  jmp    L34
  nop
L207:
  mov    D250(%rip),%rax
  mov    (%rax),%r14d
  jmp    L34
L7:
  call   <__stack_chk_fail@plt>
```

assistant: ```c
int serialOpen(const char *device, unsigned int baudrate, unsigned int bits, char parity, unsigned int stop) {
  int fd = -1;
  struct termios optnew;
  speed_t speed = B19200;
  fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
  if (fd > 0) {
    fcntl(fd, F_SETFL, 0);
    tcgetattr(fd, &optnew);
    cfmakeraw(&optnew);
    optnew.c_cc[VMIN] = 0;
    optnew.c_cc[VTIME] = 2 * 10;
    switch (baudrate) {
    case 1200:
      speed = B1200;
      break;
    case 1800:
      speed = B1800;
      break;
    case 4800:
      speed = B4800;
      break;
    case 9600:
      speed = B9600;
      break;
    case 19200:
      speed = B19200;
      break;
    case 38400:
      speed = B38400;
      break;
    case 57600:
      speed = B57600;
      break;
    case 115200:
      speed = B115200;
      break;
    default:
      speed = B19200;
      break;
    }
    cfsetispeed(&optnew, speed);
    cfsetospeed(&optnew, speed);
    optnew.c_cflag &= ~CSIZE;
    optnew.c_cflag &= ~CRTSCTS;
    optnew.c_iflag &= ~(ICRNL | IXON);
    optnew.c_cflag |= CLOCAL | CREAD;
    optnew.c_oflag &= ~OPOST;
    switch (bits) {
    case 5:
      optnew.c_cflag |= CS5;
      break;
    case 6:
      optnew.c_cflag |= CS6;
      break;
    case 7:
      optnew.c_cflag |= CS7;
      break;
    default:
      optnew.c_cflag |= CS8;
      break;
    }
    optnew.c_cflag |= PARENB;
    switch (parity) {
    case 'e':
    case 'E':
      optnew.c_cflag &= ~PARODD;
      break;
    case 'o':
    case 'O':
      optnew.c_cflag &= PARODD;
      break;
    default:
      optnew.c_cflag &= ~PARENB;
      break;
    }
    if (stop == 2)
      optnew.c_cflag &= CSTOPB;
    else
      optnew.c_cflag &= ~CSTOPB;
    optnew.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    tcsetattr(fd, TCSANOW, &optnew);
  }
  return fd;
}
```