I'm to convert the following AT&T x86 assembly into C:

```
  movl 8(%ebp), %edx
  movl $0, %eax
  movl $0, %ecx
  jmp .L2
.L1
  shll $1, %eax
  movl %edx, %ebx
  andl $1, %ebx
  orl %ebx, %eax
  shrl $1, %edx
  addl $1, %ecx
.L2
  cmpl $32, %ecx
  jl   .L1
  leave

```

But must adhere to the following skeleton code:

```
int f(unsigned int x) {
    int val = 0, i = 0;
    while(________) {
        val = ________________;
        x = ________________;
        i++;
    }
    return val;
}

```

I can tell that the snippet

```
.L2
  cmpl $32, %ecx
  jl   .L1

```

can be interpreted as `while(i<32)`. I also know that `x` is stored in `%edx`, `val` in `%eax`, and `i` in `%ecx`. However, I'm having a hard time converting the assembly within the `while`/`.L1` loop into condensed high-level language that fits into the provided skeleton code. For example, can `shll`, `shrl`, `orl`, and `andl` simply be written using their direct C equivalents (`<<`,`>>`,`|`,`&`), or is there some more nuance to it?

Is there a standardized guide/"cheat sheet" for Assembly-to-C conversions? 

I understand assembly to high-level conversion is not always clear-cut, but there are certainly patterns in assembly code that can be consistently interpreted as certain C operations.