5

I have this x86 assembly code and I'm trying to convert it to C:

.GLOBAL calculate
calculate:
    pushl %ebp
    movl %esp,%ebp
    movl 12(%ebp),%eax
    movl 8(%ebp),%ecx
    cmpl $2,%ecx
    ja done
    jmp *operations(,%ecx,4)
operation1:
    imull %eax,%eax
    jmp done
operation2:
    negl %eax
    jmp done
operation3:
    addl $0x80,%eax
done:
    leave
    ret
operations:
    .long operation1, operation2, operation3

My question is about the jmp *operations(,%ecs,4) line. I think this is a switch statement and I know how it works in memory but how does this translate to C? Wouldn't I have to know what's on the stack at those locations in order to write a switch for it?

This is what I have:

int calculate(int a, int b)
{
    if (2 > a)
    {
        return b;
    }
    switch(a) {
        case /* ? */:
            b = (b * b);
            break;
        case /* ? */:
            b = (b * -1);
            break;
        case /* ? */:
            b = (b + 128);
            break;
    }
    return b;
}
Benck
  • 515
  • 1
  • 5
  • 17
  • 5
    `case 0:` , `case 1:`. `case 2:` is what I think you are looking for. The switch is based on the value of variable `a` (which is `ecx` in your assembler code). – Michael Petch Sep 08 '15 at 03:32
  • 2
    You assembler is _at&t syntax_ so the destination is on the right and source on the left. `cmpl $2,%ecx` would be the equivalent of taking `ecx` and subtracting 2 from it and set the flags based on the result. So the assembler code `ja` would be the equivalent of testing if `ecx > 2` and jumping to done if it was. That would translate to `if (a> 2) return b;` in _C_. – Michael Petch Sep 08 '15 at 03:53

1 Answers1

1
%ecx == 0 -> operations(,%ecx,4) == operations+0 and operation1 is there  
%ecx == 1 -> operations(,%ecx,4) == operations+4 and operation2 is there  
%ecx == 2 -> operations(,%ecx,4) == operations+8 and operation3 is there

As a result, the code should be

int calculate(int a, int b)
{
    if ((unsigned int)a > 2) /* ja is a comparation instruction for unsigned integers */
    {
        return b;
    }
    switch(a) {
        case 0:
            b = (b * b);
            break;
        case 1:
            b = (b * -1);
            break;
        case 2:
            b = (b + 128);
            break;
    }
    return b;
}
MikeCAT
  • 73,922
  • 11
  • 45
  • 70