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

```asm
<cpuid_print_exts>:
  endbr64
  push   %r15
  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),%rbx
  mov    $0x0,%esi
  mov    %rbx,%rdi
  call   <cpuid@plt>
  mov    0x20(%rsp),%ebp
  mov    $0x80000000,%esi
  mov    %rbx,%rdi
  call   <cpuid@plt>
  mov    0x20(%rsp),%r14d
  test   %ebp,%ebp
  jg     L47
  movl   $0x0,0x1c(%rsp)
  movl   $0x0,0x18(%rsp)
  movl   $0x0,0x14(%rsp)
  movl   $0x0,0x10(%rsp)
  mov    $0x0,%ebp
  mov    $0x0,%r15d
  mov    $0x0,%ebx
  mov    $0x0,%r12d
  mov    $0x0,%r13d
L34:
  cmp    $0x80000000,%r14d
  ja     L10
  movl   $0x0,0xc(%rsp)
  movl   $0x0,0x8(%rsp)
  movl   $0x0,0x4(%rsp)
  mov    $0x0,%r14d
L3:
  lea    D112(%rip),%rdi
  call   <puts@plt>
  mov    %r14d,%esi
  lea    D134(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    %r13d,%esi
  lea    D56(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    %r12d,%esi
  lea    D24(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    %ebx,%esi
  lea    D58(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    %r15d,%esi
  lea    D139(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    %ebp,%esi
  lea    D103(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    0x4(%rsp),%esi
  lea    D39(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    0x10(%rsp),%esi
  lea    D80(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    0x14(%rsp),%esi
  lea    D81(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    0x18(%rsp),%esi
  lea    D99(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    0x1c(%rsp),%esi
  lea    D106(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    0xc(%rsp),%esi
  lea    D133(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    0x8(%rsp),%esi
  lea    D71(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    $0xa,%edi
  call   <putchar@plt>
  mov    0x38(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L45
  add    $0x48,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L47:
  mov    %rbx,%rdi
  mov    $0x1,%esi
  call   <cpuid@plt>
  mov    0x2c(%rsp),%ebx
  mov    %ebx,%r13d
  shr    $0x17,%r13d
  and    $0x1,%r13d
  mov    %ebx,%r12d
  shr    $0x19,%r12d
  and    $0x1,%r12d
  shr    $0x1a,%ebx
  and    $0x1,%ebx
  mov    0x28(%rsp),%eax
  mov    %eax,%r15d
  and    $0x1,%r15d
  mov    %eax,%ebp
  shr    $0x9,%ebp
  and    $0x1,%ebp
  mov    %eax,%edx
  shr    $0x13,%edx
  and    $0x1,%edx
  mov    %edx,0x10(%rsp)
  mov    %eax,%edx
  shr    $0x14,%edx
  and    $0x1,%edx
  mov    %edx,0x14(%rsp)
  mov    %eax,%edx
  shr    $0x1c,%edx
  and    $0x1,%edx
  mov    %edx,0x18(%rsp)
  shr    $0xc,%eax
  and    $0x1,%eax
  mov    %eax,0x1c(%rsp)
  jmp    L34
L10:
  lea    0x20(%rsp),%rdi
  mov    $0x80000001,%esi
  call   <cpuid@plt>
  mov    0x2c(%rsp),%eax
  shr    $0x1d,%eax
  and    $0x1,%eax
  mov    %eax,%r14d
  mov    0x28(%rsp),%eax
  mov    %eax,%edx
  shr    $0x6,%edx
  and    $0x1,%edx
  mov    %edx,0x4(%rsp)
  mov    %eax,%edx
  shr    $0x10,%edx
  and    $0x1,%edx
  mov    %edx,0xc(%rsp)
  shr    $0xb,%eax
  and    $0x1,%eax
  mov    %eax,0x8(%rsp)
  jmp    L3
L45:
  call   <__stack_chk_fail@plt>
```

tool_calls: name: disassemble_data
arguments: label: D112
type: string
name: disassemble_data
arguments: label: D134
type: string
name: disassemble_data
arguments: label: D56
type: string
name: disassemble_data
arguments: label: D24
type: string
name: disassemble_data
arguments: label: D58
type: string
name: disassemble_data
arguments: label: D139
type: string
name: disassemble_data
arguments: label: D103
type: string
name: disassemble_data
arguments: label: D39
type: string
name: disassemble_data
arguments: label: D80
type: string
name: disassemble_data
arguments: label: D81
type: string
name: disassemble_data
arguments: label: D99
type: string
name: disassemble_data
arguments: label: D106
type: string
name: disassemble_data
arguments: label: D133
type: string
name: disassemble_data
arguments: label: D71
type: string

tool: D112: Hardware Features:

tool: D134: x64   = %d


tool: D56: MMX   = %d


tool: D24: SSE   = %d


tool: D58: SSE2  = %d


tool: D139: SSE3  = %d


tool: D103: SSSE3 = %d


tool: D39: SSE4a = %d


tool: D80: SSE41 = %d


tool: D81: SSE42 = %d


tool: D99: AVX   = %d


tool: D106: FMA3  = %d


tool: D133: FMA4  = %d


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