c - 从汇编逆向工程优化的 C 代码

标签 c assembly x86 reverse-engineering compiler-optimization

这个问题的重点是对运行具有 2 级优化的编译器后生成的 C 代码进行逆向工程。原c代码如下(计算最大公约数):

int gcd(int a, int b){
    int returnValue = 0;
    if (a != 0 &&  b != 0){
        int r;
        int flag = 0;
        while (flag == 0){
            r = a % b;
            if (r ==0){
                flag = 1;
            } else {
                a = b;
                b = r;
            }
        }
        returnValue = b;
    }
    return(returnValue);
}

当我运行优化编译时,我从命令行运行了这个:

gcc -O2 -S Problem04b.c

获取此优化代码的程序集文件

.gcd:
    .LFB12:
        .cfi_startproc
        testl   %esi, %esi
        je  .L2
        testl   %edi, %edi
        je  .L2
    .L7:
        movl    %edi, %edx
        movl    %edi, %eax
        movl    %esi, %edi
        sarl    $31, %edx
        idivl   %esi
        testl   %edx, %edx
        jne .L9
        movl    %esi, %eax
        ret
        .p2align 4,,10
        .p2align 3
    .L2:
        xorl    %esi, %esi
        movl    %esi, %eax
        ret
        .p2align 4,,10
        .p2align 3
    .L9:
        movl    %edx, %esi
        jmp .L7
        .cfi_endproc

我需要将此汇编代码转换回 C 代码,这是我现在所在的位置:

int gcd(int a int b){
    /*
       testl %esi %esi
       sets zero flag if a is 0 (ZF) but doesn't store anything
       */
    if (a == 0){
        /*
           xorl %esi %esi
           sets the value of a variable to 0. More compact than movl
           */
        int returnValue = 0;
        /*
           movl %esi %eax
           ret

           return the value just assigned
           */
        return(returnValue);
    }
    /*
       testl %edi %edi
       sets zero flag if b is 0 (ZF) but doesn't store anything
       */
    if (b == 0){
        /*
           xorl %esi %esi
           sets the value of a variable to 0. More compact than movl
           */
        int returnValue = 0;
        /*
           movl %esi %eax
           ret

           return the value just assigned
           */
        return(returnValue);
    }

    do{
        int r = b;
        int returnValue = b;

    }while();


}

谁能帮我把它写回 C 代码?我几乎迷路了。

最佳答案

首先,您的代码中混合了这些值。 %esi以值 b 开头和 %edi以值 a 开头.

testl %edx, %edx可以推断行 %edx用作以 .L7 开头的循环的条件变量(如果 %edx 与 0 不同,则控制转移到 .L9 block ,然后返回到 .L7 )。我们会引用%edx作为remainder在我们的逆向工程代码中。


让我们开始对主循环进行逆向工程:

movl    %edi, %edx

%edi商店 a , 这相当于初始化 remainder 的值与 a : int remainder = a; .

movl    %edi, %eax

店铺 int temp = a;

movl    %esi, %edi

执行 int a = b; (记住 %edia%esib)。

sarl $31, %edx

这个算术移位指令将我们的 remainder 移位向右可变 31 位,同时保持数字的符号。通过移动 31 位,您正在设置 remainder如果为正(或零)则为 0,如果为负则为 -1。所以它相当于remainder = (remainder < 0) ? -1 : 0 .

idivl %esi

划分%edx:%eax通过 %esi ,或者在我们的例子中,除以 remainder * temp通过 b (变量)。 剩余 将存储在 %edx 中,或者在我们的代码中,remainder .将其与之前的指令结合使用时:if remainder < 0然后remainder = -1 * temp % b , 否则 remainder = temp % b .

testl   %edx, %edx
jne .L9

检查是否remainder等于 0 - 如果不是,跳转到 .L9 .那里的代码只是设置 b = remainder;在回到 .L7 之前.为了在 C 中实现这一点,我们将保留一个 count。将存储循环迭代次数的变量。我们将执行 b = remainder在循环的开始但仅在第一次迭代之后,意思是当 count != 0 时.

我们现在准备构建完整的 C 循环:

int count = 0;
do {
    if (count != 0)
        b = remainder;
    remainder = a;
    temp = a;
    a = b;
    if (remainder < 0){
        remainder = -1 * temp % b;
    } else {
        remainder = temp % b;
    }

    count++;
} while (remainder != 0)

循环结束后,

movl    %esi, %eax
ret

将返回程序计算的 GCD(在我们的代码中它将存储在 b 变量中)。

关于c - 从汇编逆向工程优化的 C 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28611361/

相关文章:

linux - 你如何在 linux 中制作一个将文件转换为大写的 x86 汇编程序?

assembly - 编译简单的SPARC ASM数学代码时出错

x86 - 分支预测器单元的输入?

c - 如何将输出定向到 linux 终端中的特定坐标?

c - 为什么浮点计算结果在 C 和我的计算器上不同?

c - 在 Ruby/Inline C 中接受未定义数量的参数

c - C 中的类型转换是如何实现的?

对未初始化指针指向任何地方的事实感到困惑

performance - rdpmc 的 CR4.PCE 已清除

dll - LoadLibrary 失败并出现模块未找到错误 - 可能存在依赖性问题