user: 请将以下的汇编代码转换成C语言代码：

```asm
<cpuid_print_exts>:
  endbr64
  push   %r15
  xor    %esi,%esi
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x48,%rsp
  mov    %fs:0x28,%rax
  mov    %rax,0x38(%rsp)
  xor    %eax,%eax
  lea    0x20(%rsp),%r12
  mov    %r12,%rdi
  call   <cpuid@plt>
  mov    0x20(%rsp),%ebx
  mov    $0x80000000,%esi
  mov    %r12,%rdi
  call   <cpuid@plt>
  mov    0x20(%rsp),%edx
  test   %ebx,%ebx
  jg     L26
  movl   $0x0,0x1c(%rsp)
  xor    %r13d,%r13d
  xor    %ebx,%ebx
  xor    %ebp,%ebp
  movl   $0x0,0x18(%rsp)
  xor    %r14d,%r14d
  xor    %r15d,%r15d
  movl   $0x0,0x14(%rsp)
  movl   $0x0,0x10(%rsp)
  cmp    $0x80000000,%edx
  ja     L44
L9:
  xor    %r9d,%r9d
  xor    %r8d,%r8d
  xor    %r10d,%r10d
  xor    %esi,%esi
L24:
  lea    D81(%rip),%rdi
  mov    %r9d,0xc(%rsp)
  mov    %r8d,0x8(%rsp)
  mov    %r10d,0x4(%rsp)
  mov    %esi,(%rsp)
  call   <puts@plt>
  mov    (%rsp),%esi
  lea    D4(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    %r15d,%esi
  lea    D94(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    %r14d,%esi
  lea    D10(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    %ebp,%esi
  lea    D132(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    %ebx,%esi
  lea    D115(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    %r13d,%esi
  lea    D118(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    0x4(%rsp),%esi
  lea    D78(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    0x10(%rsp),%esi
  lea    D48(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    0x14(%rsp),%esi
  lea    D135(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    0x18(%rsp),%esi
  lea    D34(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    0x1c(%rsp),%esi
  lea    D22(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    0xc(%rsp),%esi
  lea    D35(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    0x8(%rsp),%esi
  lea    D106(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    $0xa,%edi
  call   <putchar@plt>
  mov    0x38(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L10
  add    $0x48,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nop
L26:
  mov    $0x1,%esi
  mov    %r12,%rdi
  mov    %edx,(%rsp)
  call   <cpuid@plt>
  mov    0x28(%rsp),%eax
  mov    0x2c(%rsp),%ebp
  mov    (%rsp),%edx
  mov    %eax,%ecx
  mov    %ebp,%r15d
  mov    %ebp,%r14d
  mov    %eax,%ebx
  shr    $0x13,%ecx
  mov    %eax,%r13d
  shr    $0x17,%r15d
  and    $0x1,%ebx
  shr    $0x19,%r14d
  and    $0x1,%ecx
  shr    $0x1a,%ebp
  and    $0x1,%r15d
  mov    %ecx,0x10(%rsp)
  mov    %eax,%ecx
  shr    $0x9,%r13d
  and    $0x1,%r14d
  shr    $0x14,%ecx
  and    $0x1,%ebp
  and    $0x1,%r13d
  and    $0x1,%ecx
  mov    %ecx,0x14(%rsp)
  mov    %eax,%ecx
  shr    $0xc,%eax
  shr    $0x1c,%ecx
  and    $0x1,%eax
  and    $0x1,%ecx
  mov    %eax,0x1c(%rsp)
  mov    %ecx,0x18(%rsp)
  cmp    $0x80000000,%edx
  jbe    L9
L44:
  mov    $0x80000001,%esi
  mov    %r12,%rdi
  call   <cpuid@plt>
  mov    0x28(%rsp),%r8d
  mov    0x2c(%rsp),%esi
  mov    %r8d,%r10d
  mov    %r8d,%r9d
  shr    $0x1d,%esi
  shr    $0x6,%r10d
  shr    $0x10,%r9d
  and    $0x1,%esi
  shr    $0xb,%r8d
  and    $0x1,%r10d
  and    $0x1,%r9d
  and    $0x1,%r8d
  jmp    L24
L10:
  call   <__stack_chk_fail@plt>
```

tool_calls: name: retrieve_data
arguments: label: D81
type_infered: string
name: retrieve_data
arguments: label: D4
type_infered: string
name: retrieve_data
arguments: label: D94
type_infered: string
name: retrieve_data
arguments: label: D10
type_infered: string
name: retrieve_data
arguments: label: D132
type_infered: string
name: retrieve_data
arguments: label: D115
type_infered: string
name: retrieve_data
arguments: label: D118
type_infered: string
name: retrieve_data
arguments: label: D78
type_infered: string
name: retrieve_data
arguments: label: D48
type_infered: string
name: retrieve_data
arguments: label: D135
type_infered: string
name: retrieve_data
arguments: label: D34
type_infered: string
name: retrieve_data
arguments: label: D22
type_infered: string
name: retrieve_data
arguments: label: D35
type_infered: string
name: retrieve_data
arguments: label: D106
type_infered: string

tool: D81: Hardware Features:

tool: D4: x64   = %d


tool: D94: MMX   = %d


tool: D10: SSE   = %d


tool: D132: SSE2  = %d


tool: D115: SSE3  = %d


tool: D118: SSSE3 = %d


tool: D78: SSE4a = %d


tool: D48: SSE41 = %d


tool: D135: SSE42 = %d


tool: D34: AVX   = %d


tool: D22: FMA3  = %d


tool: D35: FMA4  = %d


tool: D106: 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");
}
```