2

I'm trying to convert x86-64 assembly into C code, but am still unsure about some of the lines.

This is the assembly code:

   ....
  pushq %rbp 
  movq %rsp, %rbp 
  subq $20, %rsp
  movl %edi, -20(%rbp) 
  movl $2, -4(%rbp) 

 jmp .L2
  movl -20(%rbp), %eax //1 Lines 1-3 divide %eax / -4(%rbp)
  cltd  //2 the quotient is stored in %eax
  idivl -4(%rbp) //3 Remainder is stored in %edx
  movl %edx, %eax 
  testl %eax, %eax
  jne .L3 
  movl $0, %eax 
  jmp .L4 

.L3: 
  addl $1, -4(%rbp)

.L2: 
  movl -4(%rbp), %eax 
  cmpl -20(%rbp), %eax
  jl .L5 
  movl $1, %eax

 .L4: 
  leave 
  ret 
  .....

In C, would it be:

int function (int param) {
   int var1= 2; 
   while (var1 < param) {
       if (eax != 0) { // instead of eax, should it be var1?
           eax = eax / var1; // unsure about the body
   } 
return var1; 
}

If anyone can help with guiding me to the right direction or showing me what I'm missing that would be nice.

2

This answer could be better if you provided more context which exact assembler statements you have problems with.

Generally, the compiler often has an instruction that moves a variable to a register at the start of something, works with that register for a while, then stores the variable back. In your case, think of eax as a temporary variable that copies var1, like this:

eax_temp_var1=var1;
eax_temp_var1=eax_temp_var1%var2;  // idivl; movl
if (eax_temp_var1 == 0)            // testl
    return 0;                      // movl $0, eax; jmp L4; leave; ret
var2++;                            // addl $1
if (var2<var1)
    goto L5;                       // movl; cmpl; jl
return 1;

Of course, a C programmer wouldn' write the first three lines like that, it would rather be

if (var1 % var2 == 0)

and part of the challenge of reverse engineering is simplifying code like this to understand what's going on.

Please note that in the code snippet you posted, there's no jump back, as we don't know where L5 is; so there's no reason why this should be a loop. (Actually, i guess the whole thing is a primality test, and L5 ist just after the jmp .L2, which would make it a loop).

Also, when the program arrives at L4, eax will either contain a 0 or a 1, so this will never return var1.

Lastly, i used var1%var2, not var1/var2. You commented "Remainder in edx" yourself; then edx is moved to eax, then eax gets tested if it's zero. So, it's the remainder, not the quotient, that gets tested.

1

The end part is missing but it pretty much looks like a naive function to test for primality. It tries to divide param with every number from 2 to (param - 1). If the remainder is zero, then the function has found a divisor and returns 0. Else it returns 1.

Something like:

bool is_prime(int param)
{
    int var1;

    for (var1 = 2; var1 < param; var1++)
    {
        if (param % var1 == 0) return false;
    }

    return true;
}

-20(%rbp) is the parameter; that would be param.

-4(%rbp) is a local variable; that would be var1.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.