user: Translate the below assembly code into C programming language:

```asm
<echelonform>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  push   %rbx
  sub    $0x38,%rsp
  mov    %rdi,-0x38(%rbp)
  mov    %esi,-0x3c(%rbp)
  mov    %edx,-0x40(%rbp)
  movl   $0x0,-0x24(%rbp)
  movl   $0x0,-0x20(%rbp)
  movl   $0x0,-0x1c(%rbp)
  movl   $0x0,-0x20(%rbp)
  jmp    L126
L152:
  mov    -0x24(%rbp),%eax
  cmp    -0x40(%rbp),%eax
  jl     L185
  mov    $0x0,%eax
  jmp    L94
L185:
  mov    -0x20(%rbp),%eax
  mov    %eax,-0x1c(%rbp)
  jmp    L64
L169:
  addl   $0x1,-0x1c(%rbp)
  mov    -0x1c(%rbp),%eax
  cmp    -0x3c(%rbp),%eax
  jne    L64
  mov    -0x20(%rbp),%eax
  mov    %eax,-0x1c(%rbp)
  addl   $0x1,-0x24(%rbp)
  mov    -0x40(%rbp),%eax
  cmp    -0x24(%rbp),%eax
  jne    L64
  mov    $0x0,%eax
  jmp    L94
L64:
  mov    -0x1c(%rbp),%eax
  imul   -0x40(%rbp),%eax
  mov    %eax,%edx
  mov    -0x24(%rbp),%eax
  add    %edx,%eax
  movslq %eax,%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  test   %al,%al
  je     L169
  movl   $0x0,-0x18(%rbp)
  jmp    L166
L181:
  mov    -0x20(%rbp),%eax
  imul   -0x40(%rbp),%eax
  mov    %eax,%edx
  mov    -0x18(%rbp),%eax
  add    %edx,%eax
  movslq %eax,%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  mov    %al,-0x25(%rbp)
  mov    -0x1c(%rbp),%eax
  imul   -0x40(%rbp),%eax
  mov    %eax,%edx
  mov    -0x18(%rbp),%eax
  add    %edx,%eax
  movslq %eax,%rdx
  mov    -0x38(%rbp),%rax
  lea    (%rdx,%rax,1),%rcx
  mov    -0x20(%rbp),%eax
  imul   -0x40(%rbp),%eax
  mov    %eax,%edx
  mov    -0x18(%rbp),%eax
  add    %edx,%eax
  movslq %eax,%rdx
  mov    -0x38(%rbp),%rax
  add    %rax,%rdx
  movzbl (%rcx),%eax
  mov    %al,(%rdx)
  mov    -0x1c(%rbp),%eax
  imul   -0x40(%rbp),%eax
  mov    %eax,%edx
  mov    -0x18(%rbp),%eax
  add    %edx,%eax
  movslq %eax,%rdx
  mov    -0x38(%rbp),%rax
  add    %rax,%rdx
  movzbl -0x25(%rbp),%eax
  mov    %al,(%rdx)
  addl   $0x1,-0x18(%rbp)
L166:
  mov    -0x18(%rbp),%eax
  cmp    -0x40(%rbp),%eax
  jl     L181
  mov    -0x20(%rbp),%eax
  imul   -0x40(%rbp),%eax
  mov    %eax,%edx
  mov    -0x24(%rbp),%eax
  add    %edx,%eax
  movslq %eax,%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  mov    %al,-0x27(%rbp)
  cmpb   $0x0,-0x27(%rbp)
  je     L171
  movl   $0x0,-0x18(%rbp)
  jmp    L79
L187:
  movzbl -0x27(%rbp),%edx
  mov    -0x20(%rbp),%eax
  imul   -0x40(%rbp),%eax
  mov    %eax,%ecx
  mov    -0x18(%rbp),%eax
  add    %ecx,%eax
  movslq %eax,%rcx
  mov    -0x38(%rbp),%rax
  add    %rcx,%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    -0x20(%rbp),%ecx
  mov    %ecx,%esi
  imul   -0x40(%rbp),%esi
  mov    -0x18(%rbp),%ecx
  add    %esi,%ecx
  movslq %ecx,%rsi
  mov    -0x38(%rbp),%rcx
  lea    (%rsi,%rcx,1),%rbx
  mov    %edx,%esi
  mov    %eax,%edi
  call   <divs@plt>
  mov    %al,(%rbx)
  addl   $0x1,-0x18(%rbp)
L79:
  mov    -0x18(%rbp),%eax
  cmp    -0x40(%rbp),%eax
  jl     L187
L171:
  movl   $0x0,-0x18(%rbp)
  jmp    L2
L66:
  mov    -0x18(%rbp),%eax
  cmp    -0x20(%rbp),%eax
  je     L117
  mov    -0x18(%rbp),%eax
  imul   -0x40(%rbp),%eax
  mov    %eax,%edx
  mov    -0x24(%rbp),%eax
  add    %edx,%eax
  movslq %eax,%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  mov    %al,-0x26(%rbp)
  movl   $0x0,-0x14(%rbp)
  jmp    L189
L78:
  mov    -0x20(%rbp),%eax
  imul   -0x40(%rbp),%eax
  mov    %eax,%edx
  mov    -0x14(%rbp),%eax
  add    %edx,%eax
  movslq %eax,%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movzbl %al,%edx
  movzbl -0x26(%rbp),%eax
  mov    %edx,%esi
  mov    %eax,%edi
  call   <mul@plt>
  mov    %eax,%ecx
  mov    -0x18(%rbp),%eax
  imul   -0x40(%rbp),%eax
  mov    %eax,%edx
  mov    -0x14(%rbp),%eax
  add    %edx,%eax
  movslq %eax,%rdx
  mov    -0x38(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    -0x18(%rbp),%edx
  mov    %edx,%esi
  imul   -0x40(%rbp),%esi
  mov    -0x14(%rbp),%edx
  add    %esi,%edx
  movslq %edx,%rsi
  mov    -0x38(%rbp),%rdx
  lea    (%rsi,%rdx,1),%rbx
  mov    %ecx,%esi
  mov    %eax,%edi
  call   <sub@plt>
  mov    %al,(%rbx)
  addl   $0x1,-0x14(%rbp)
L189:
  mov    -0x14(%rbp),%eax
  cmp    -0x40(%rbp),%eax
  jl     L78
L117:
  addl   $0x1,-0x18(%rbp)
L2:
  mov    -0x18(%rbp),%eax
  cmp    -0x3c(%rbp),%eax
  jl     L66
  addl   $0x1,-0x24(%rbp)
  addl   $0x1,-0x20(%rbp)
L126:
  mov    -0x20(%rbp),%eax
  cmp    -0x3c(%rbp),%eax
  jl     L152
  mov    $0x1,%eax
L94:
  mov    -0x8(%rbp),%rbx
  leave
  ret
```

assistant: ```c
int echelonform(unsigned char M[], int nrows, int ncols) {
  int lead = 0, rix = 0, iix = 0, j, k;
  unsigned char temp, de, sb;
  for (rix = 0; rix < nrows; rix++) {
    if (lead >= ncols) {
      return 0;
    }
    iix = rix;
    while (M[iix * ncols + lead] == 0) {
      iix++;
      if (iix == nrows) {
        iix = rix;
        lead++;
        if (ncols == lead) {
          return 0;
        }
      }
    }
    for (j = 0; j < ncols; j++) {
      temp = M[rix * ncols + j];
      M[rix * ncols + j] = M[iix * ncols + j];
      M[iix * ncols + j] = temp;
    }
    de = M[rix * ncols + lead];
    if (de != 0) {
      for (j = 0; j < ncols; j++) {
        M[rix * ncols + j] = divs(M[rix * ncols + j], de);
      }
    }
    for (j = 0; j < nrows; j++) {
      if (j != rix) {
        sb = M[j * ncols + lead];
        for (k = 0; k < ncols; k++) {
          M[j * ncols + k] = sub(M[j * ncols + k], mul(sb, M[rix * ncols + k]));
        }
      }
    }
    lead++;
  }
  return 1;
}
```