user: 请将这段汇编代码片段转换成等效的C代码：

```asm
<cpuid_print_exts>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x60,%rsp
  mov    %fs:0x28,%rax
  mov    %rax,-0x8(%rbp)
  xor    %eax,%eax
  movl   $0x0,-0x5c(%rbp)
  movl   $0x0,-0x58(%rbp)
  movl   $0x0,-0x54(%rbp)
  movl   $0x0,-0x50(%rbp)
  movl   $0x0,-0x4c(%rbp)
  movl   $0x0,-0x48(%rbp)
  movl   $0x0,-0x44(%rbp)
  movl   $0x0,-0x40(%rbp)
  movl   $0x0,-0x3c(%rbp)
  movl   $0x0,-0x38(%rbp)
  movl   $0x0,-0x34(%rbp)
  movl   $0x0,-0x30(%rbp)
  movl   $0x0,-0x2c(%rbp)
  lea    -0x20(%rbp),%rax
  mov    $0x0,%esi
  mov    %rax,%rdi
  call   <cpuid@plt>
  mov    -0x20(%rbp),%eax
  mov    %eax,-0x28(%rbp)
  lea    -0x20(%rbp),%rax
  mov    $0x80000000,%esi
  mov    %rax,%rdi
  call   <cpuid@plt>
  mov    -0x20(%rbp),%eax
  mov    %eax,-0x24(%rbp)
  cmpl   $0x0,-0x28(%rbp)
  jle    L0
  lea    -0x20(%rbp),%rax
  mov    $0x1,%esi
  mov    %rax,%rdi
  call   <cpuid@plt>
  mov    -0x14(%rbp),%eax
  and    $0x800000,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x58(%rbp)
  mov    -0x14(%rbp),%eax
  and    $0x2000000,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x54(%rbp)
  mov    -0x14(%rbp),%eax
  and    $0x4000000,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x50(%rbp)
  mov    -0x18(%rbp),%eax
  and    $0x1,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x4c(%rbp)
  mov    -0x18(%rbp),%eax
  and    $0x200,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x48(%rbp)
  mov    -0x18(%rbp),%eax
  and    $0x80000,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x44(%rbp)
  mov    -0x18(%rbp),%eax
  and    $0x100000,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x40(%rbp)
  mov    -0x18(%rbp),%eax
  and    $0x10000000,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x38(%rbp)
  mov    -0x18(%rbp),%eax
  and    $0x1000,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x30(%rbp)
L0:
  mov    -0x24(%rbp),%eax
  cmp    $0x80000000,%eax
  jbe    L17
  lea    -0x20(%rbp),%rax
  mov    $0x80000001,%esi
  mov    %rax,%rdi
  call   <cpuid@plt>
  mov    -0x14(%rbp),%eax
  and    $0x20000000,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x5c(%rbp)
  mov    -0x18(%rbp),%eax
  and    $0x40,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x3c(%rbp)
  mov    -0x18(%rbp),%eax
  and    $0x10000,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x2c(%rbp)
  mov    -0x18(%rbp),%eax
  and    $0x800,%eax
  test   %eax,%eax
  setne  %al
  movzbl %al,%eax
  mov    %eax,-0x34(%rbp)
L17:
  lea    D113(%rip),%rax
  mov    %rax,%rdi
  call   <puts@plt>
  mov    -0x5c(%rbp),%eax
  mov    %eax,%esi
  lea    D80(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x58(%rbp),%eax
  mov    %eax,%esi
  lea    D37(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x54(%rbp),%eax
  mov    %eax,%esi
  lea    D28(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x50(%rbp),%eax
  mov    %eax,%esi
  lea    D129(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x4c(%rbp),%eax
  mov    %eax,%esi
  lea    D11(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x48(%rbp),%eax
  mov    %eax,%esi
  lea    D70(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x3c(%rbp),%eax
  mov    %eax,%esi
  lea    D118(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x44(%rbp),%eax
  mov    %eax,%esi
  lea    D57(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x40(%rbp),%eax
  mov    %eax,%esi
  lea    D8(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x38(%rbp),%eax
  mov    %eax,%esi
  lea    D25(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x30(%rbp),%eax
  mov    %eax,%esi
  lea    D134(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x2c(%rbp),%eax
  mov    %eax,%esi
  lea    D65(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x34(%rbp),%eax
  mov    %eax,%esi
  lea    D29(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    $0xa,%edi
  call   <putchar@plt>
  nop
  mov    -0x8(%rbp),%rax
  sub    %fs:0x28,%rax
  je     L8
  call   <__stack_chk_fail@plt>
L8:
  leave
  ret
```

tool_calls: name: extract_symbolic_data
arguments: data_tag: D113
datatype: string
name: extract_symbolic_data
arguments: data_tag: D80
datatype: string
name: extract_symbolic_data
arguments: data_tag: D37
datatype: string
name: extract_symbolic_data
arguments: data_tag: D28
datatype: string
name: extract_symbolic_data
arguments: data_tag: D129
datatype: string
name: extract_symbolic_data
arguments: data_tag: D11
datatype: string
name: extract_symbolic_data
arguments: data_tag: D70
datatype: string
name: extract_symbolic_data
arguments: data_tag: D118
datatype: string
name: extract_symbolic_data
arguments: data_tag: D57
datatype: string
name: extract_symbolic_data
arguments: data_tag: D8
datatype: string
name: extract_symbolic_data
arguments: data_tag: D25
datatype: string
name: extract_symbolic_data
arguments: data_tag: D134
datatype: string
name: extract_symbolic_data
arguments: data_tag: D65
datatype: string
name: extract_symbolic_data
arguments: data_tag: D29
datatype: string

tool: D113: Hardware Features:

tool: D80: x64   = %d


tool: D37: MMX   = %d


tool: D28: SSE   = %d


tool: D129: SSE2  = %d


tool: D11: SSE3  = %d


tool: D70: SSSE3 = %d


tool: D118: SSE4a = %d


tool: D57: SSE41 = %d


tool: D8: SSE42 = %d


tool: D25: AVX   = %d


tool: D134: FMA3  = %d


tool: D65: FMA4  = %d


tool: D29: XOP   = %d


assistant: ```c
void cpuid_print_exts() {
  int x64 = 0;
  int MMX = 0;
  int SSE = 0;
  int SSE2 = 0;
  int SSE3 = 0;
  int SSSE3 = 0;
  int SSE41 = 0;
  int SSE42 = 0;
  int SSE4a = 0;
  int AVX = 0;
  int XOP = 0;
  int FMA3 = 0;
  int FMA4 = 0;
  int info[4];
  cpuid(info, 0);
  int nIds = info[0];
  cpuid(info, 0x80000000);
  int nExIds = info[0];
  if (nIds >= 1) {
    cpuid(info, 0x00000001);
    MMX = (info[3] & ((int)1 << 23)) != 0;
    SSE = (info[3] & ((int)1 << 25)) != 0;
    SSE2 = (info[3] & ((int)1 << 26)) != 0;
    SSE3 = (info[2] & ((int)1 << 0)) != 0;
    SSSE3 = (info[2] & ((int)1 << 9)) != 0;
    SSE41 = (info[2] & ((int)1 << 19)) != 0;
    SSE42 = (info[2] & ((int)1 << 20)) != 0;
    AVX = (info[2] & ((int)1 << 28)) != 0;
    FMA3 = (info[2] & ((int)1 << 12)) != 0;
  }
  if (nExIds >= 0x80000001) {
    cpuid(info, 0x80000001);
    x64 = (info[3] & ((int)1 << 29)) != 0;
    SSE4a = (info[2] & ((int)1 << 6)) != 0;
    FMA4 = (info[2] & ((int)1 << 16)) != 0;
    XOP = (info[2] & ((int)1 << 11)) != 0;
  }
  printf("Hardware Features:\n");
  printf("x64   = %d\n", x64);
  printf("MMX   = %d\n", MMX);
  printf("SSE   = %d\n", SSE);
  printf("SSE2  = %d\n", SSE2);
  printf("SSE3  = %d\n", SSE3);
  printf("SSSE3 = %d\n", SSSE3);
  printf("SSE4a = %d\n", SSE4a);
  printf("SSE41 = %d\n", SSE41);
  printf("SSE42 = %d\n", SSE42);
  printf("AVX   = %d\n", AVX);
  printf("FMA3  = %d\n", FMA3);
  printf("FMA4  = %d\n", FMA4);
  printf("XOP   = %d\n", XOP);
  printf("\n");
}
```