user: Please show me the C implementation that matches the assembly code listed below:

```asm
<ReadKeys>:
  endbr64
  mov    $0xe0028004,%eax
  mov    $0xe0028010,%edx
  movq   $0x400000,(%rax)
  nopl   (%rax)
L7:
  mov    (%rdx),%rax
  test   $0x2000000,%eax
  jne    L7
  mov    $0xe002800c,%esi
  mov    $0xe0028004,%edi
  mov    $0xe0028000,%edx
  movq   $0x400000,(%rsi)
  movq   $0x400000,(%rdi)
  movq   $0x400000,(%rsi)
  mov    (%rdx),%rcx
  movq   $0x400000,(%rdi)
  movq   $0x400000,(%rsi)
  mov    (%rdx),%rax
  shr    $0x15,%rcx
  and    $0x1,%ecx
  movq   $0x400000,(%rdi)
  shr    $0x15,%rax
  shl    $0xf,%ecx
  movq   $0x400000,(%rsi)
  and    $0x1,%eax
  shl    $0x10,%eax
  or     %ecx,%eax
  mov    (%rdx),%rcx
  movq   $0x400000,(%rdi)
  shr    %eax
  movq   $0x400000,(%rsi)
  shr    $0x15,%rcx
  and    $0x1,%ecx
  shl    $0x10,%ecx
  or     %eax,%ecx
  mov    (%rdx),%rax
  movq   $0x400000,(%rdi)
  shr    %ecx
  movq   $0x400000,(%rsi)
  shr    $0x15,%rax
  and    $0x1,%eax
  shl    $0x10,%eax
  or     %ecx,%eax
  mov    (%rdx),%rcx
  movq   $0x400000,(%rdi)
  shr    %eax
  movq   $0x400000,(%rsi)
  shr    $0x15,%rcx
  and    $0x1,%ecx
  shl    $0x10,%ecx
  or     %eax,%ecx
  mov    (%rdx),%rax
  movq   $0x400000,(%rdi)
  shr    %ecx
  movq   $0x400000,(%rsi)
  shr    $0x15,%rax
  and    $0x1,%eax
  shl    $0x10,%eax
  or     %ecx,%eax
  mov    (%rdx),%rcx
  movq   $0x400000,(%rdi)
  shr    %eax
  movq   $0x400000,(%rsi)
  shr    $0x15,%rcx
  and    $0x1,%ecx
  shl    $0x10,%ecx
  or     %eax,%ecx
  mov    (%rdx),%rax
  movq   $0x400000,(%rdi)
  shr    %ecx
  movq   $0x400000,(%rsi)
  shr    $0x15,%rax
  and    $0x1,%eax
  shl    $0x10,%eax
  or     %ecx,%eax
  mov    (%rdx),%rcx
  movq   $0x400000,(%rdi)
  shr    %eax
  movq   $0x400000,(%rsi)
  shr    $0x15,%rcx
  and    $0x1,%ecx
  shl    $0x10,%ecx
  or     %eax,%ecx
  mov    (%rdx),%rax
  movq   $0x400000,(%rdi)
  shr    %ecx
  movq   $0x400000,(%rsi)
  shr    $0x15,%rax
  and    $0x1,%eax
  shl    $0x10,%eax
  or     %ecx,%eax
  mov    (%rdx),%rcx
  movq   $0x400000,(%rdi)
  shr    %eax
  movq   $0x400000,(%rsi)
  shr    $0x15,%rcx
  and    $0x1,%ecx
  shl    $0x10,%ecx
  or     %eax,%ecx
  mov    (%rdx),%rax
  movq   $0x400000,(%rdi)
  shr    %ecx
  movq   $0x400000,(%rsi)
  shr    $0x15,%rax
  and    $0x1,%eax
  shl    $0x10,%eax
  or     %ecx,%eax
  mov    (%rdx),%rcx
  movq   $0x400000,(%rdi)
  shr    %eax
  movq   $0x400000,(%rsi)
  shr    $0x15,%rcx
  and    $0x1,%ecx
  shl    $0x10,%ecx
  or     %eax,%ecx
  mov    (%rdx),%rax
  movq   $0x400000,(%rdi)
  shr    %ecx
  movq   $0x400000,(%rsi)
  shr    $0x15,%rax
  and    $0x1,%eax
  shl    $0x10,%eax
  or     %ecx,%eax
  mov    (%rdx),%rcx
  movq   $0x400000,(%rdi)
  shr    %eax
  movq   $0x400000,(%rsi)
  shr    $0x15,%rcx
  and    $0x1,%ecx
  shl    $0x10,%ecx
  or     %eax,%ecx
  mov    (%rdx),%rax
  shr    %ecx
  shr    $0x15,%rax
  and    $0x1,%eax
  shl    $0x10,%eax
  or     %ecx,%eax
  shr    %eax
  ret
```

assistant: ```c
unsigned int ReadKeys(void) {
  unsigned char x, y;
  unsigned int data = 0;
  (*((volatile unsigned long *)0xE0028004)) = 1 << 22;
  while ((*((volatile unsigned long *)0xE0028010)) & 1 << 25)
    ;
  (*((volatile unsigned long *)0xE002800C)) = 1 << 22;
  for (x = 0; x < 16; x++) {
    y = 200;
    while (y--)
      ;
    (*((volatile unsigned long *)0xE0028004)) = 1 << 22;
    y = 200;
    while (y--)
      ;
    (*((volatile unsigned long *)0xE002800C)) = 1 << 22;
    data |= !!((*((volatile unsigned long *)0xE0028000)) & 1 << 21) << 16;
    data >>= 1;
  }
  return data;
}
```