user: Converte this assembly snippet into its equivalent C code:

```asm
<write_lba48>:
  endbr64
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x8,%rsp
  mov    %edi,%ebx
  mov    %esi,%ebp
  mov    %edx,%r12d
  mov    %rcx,%r13
  mov    $0x40,%esi
  mov    $0x1f6,%edi
  mov    $0x0,%eax
  call   <outb@plt>
  mov    %r12d,%eax
  movzbl %ah,%esi
  mov    $0x1f2,%edi
  mov    $0x0,%eax
  call   <outb@plt>
  mov    %ebx,%esi
  shr    $0x18,%esi
  mov    $0x1f3,%edi
  mov    $0x0,%eax
  call   <outb@plt>
  movzbl %bpl,%esi
  mov    $0x1f4,%edi
  mov    $0x0,%eax
  call   <outb@plt>
  mov    %ebp,%eax
  movzbl %ah,%esi
  mov    $0x1f5,%edi
  mov    $0x0,%eax
  call   <outb@plt>
  movzbl %r12b,%esi
  mov    $0x1f2,%edi
  mov    $0x0,%eax
  call   <outb@plt>
  movzbl %bl,%esi
  mov    $0x1f3,%edi
  mov    $0x0,%eax
  call   <outb@plt>
  movzbl %bh,%esi
  mov    $0x1f4,%edi
  mov    $0x0,%eax
  call   <outb@plt>
  mov    %ebx,%esi
  shr    $0x10,%esi
  movzbl %sil,%esi
  mov    $0x1f5,%edi
  mov    $0x0,%eax
  call   <outb@plt>
  mov    $0x34,%esi
  mov    $0x1f7,%edi
  mov    $0x0,%eax
  call   <outb@plt>
  test   %r12w,%r12w
  je     L117
  lea    0x200(%r13),%rbp
  movzwl %r12w,%r12d
  lea    -0x1(%r12),%eax
  shl    $0x9,%rax
  lea    0x400(%r13,%rax,1),%r12
  lea    D0(%rip),%r13
  jmp    L70
L42:
  mov    %r13,%rdi
  mov    $0x0,%eax
  call   <print@plt>
L104:
  mov    $0x1f0,%edx
L90:
  movzwl (%rbx),%eax
  out    %ax,(%dx)
  add    $0x2,%rbx
  cmp    %rbp,%rbx
  jne    L90
  add    $0x200,%rbp
  cmp    %r12,%rbp
  je     L117
L70:
  lea    -0x200(%rbp),%rbx
  mov    $0x3f6,%edi
  mov    $0x0,%eax
  call   <inb@plt>
  mov    $0x3f6,%edi
  mov    $0x0,%eax
  call   <inb@plt>
  mov    $0x3f6,%edi
  mov    $0x0,%eax
  call   <inb@plt>
  mov    $0x3f6,%edi
  mov    $0x0,%eax
  call   <inb@plt>
L107:
  mov    $0x3f6,%edi
  mov    $0x0,%eax
  call   <inb@plt>
  test   $0x21,%al
  jne    L42
  test   %al,%al
  jns    L104
  test   $0x8,%al
  je     L107
  jmp    L104
L117:
  mov    $0x3f6,%edi
  mov    $0x0,%eax
  call   <inb@plt>
  mov    $0x3f6,%edi
  mov    $0x0,%eax
  call   <inb@plt>
  mov    $0x3f6,%edi
  mov    $0x0,%eax
  call   <inb@plt>
  mov    $0x3f6,%edi
  mov    $0x0,%eax
  call   <inb@plt>
L64:
  mov    $0x3f6,%edi
  mov    $0x0,%eax
  call   <inb@plt>
  test   $0x21,%al
  jne    L93
  test   %al,%al
  jns    L59
  test   $0x8,%al
  je     L64
  jmp    L59
L93:
  lea    D0(%rip),%rdi
  mov    $0x0,%eax
  call   <print@plt>
L59:
  mov    $0xe7,%esi
  mov    $0x1f7,%edi
  mov    $0x0,%eax
  call   <outb@plt>
  add    $0x8,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  ret
```

tool_calls: name: extract_symbolic_data
arguments: data_label: D0
datatype: string

tool: D0: ata: drive error


assistant: ```c
void write_lba48(unsigned int lba_low, unsigned int lba_high, unsigned short count, unsigned char *buf) {
  unsigned char c;
  int i, j;
  outb(0x1f0 + 6, (1 << 6));
  outb(0x1f0 + 2, (count >> 8) & 0xff);
  outb(0x1f0 + 3, (lba_low >> 24) & 0xff);
  outb(0x1f0 + 4, lba_high & 0xff);
  outb(0x1f0 + 5, (lba_high >> 8) & 0xff);
  outb(0x1f0 + 2, count & 0xff);
  outb(0x1f0 + 3, lba_low & 0xff);
  outb(0x1f0 + 4, (lba_low >> 8) & 0xff);
  outb(0x1f0 + 5, (lba_low >> 16) & 0xff);
  outb(0x1f0 + 7, 0x34);
  for (i = 0; i < count; ++i) {
    (void)inb(0x3f6);
    (void)inb(0x3f6);
    (void)inb(0x3f6);
    (void)inb(0x3f6);
    do {
      c = inb(0x3f6);
      if ((c & (1 << 0)) || (c & (1 << 5)))
        break;
    } while ((c & (1 << 7)) && !(c & (1 << 3)));
    if ((c & (1 << 0)) || (c & (1 << 5)))
      print("ata: drive error\n");
    for (j = 0; j < 256; ++j) {
      asm volatile("outw %%ax, %%dx" ::"a"(((unsigned short *)buf)[j]), "d"(0x1f0 + 0) : "memory");
    }
    buf += 512;
  }
  (void)inb(0x3f6);
  (void)inb(0x3f6);
  (void)inb(0x3f6);
  (void)inb(0x3f6);
  do {
    c = inb(0x3f6);
    if ((c & (1 << 0)) || (c & (1 << 5)))
      break;
  } while ((c & (1 << 7)) && !(c & (1 << 3)));
  if ((c & (1 << 0)) || (c & (1 << 5)))
    print("ata: drive error\n");
  outb(0x1f0 + 7, 0xe7);
}
```