繁体   English   中英

从装配中反向设计优化的c代码

[英]Reverse engineer optimized c code from assembly

这个问题的关键是对使用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块然后返回.L7 )。 我们将%edx称为反向工程代码中的remainder


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

movl    %edi, %edx

由于%edi存储a ,这等同于初始化的值remainderaint remainder = a;

movl    %edi, %eax

Store 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 remainder = (remainder < 0) ? -1 : 0

idivl %esi

%edx:%eax除以%esi ,或者在我们的例子中,将remainder * temp除以b (变量)。 余数将存储在%edx ,或存储在我们的代码中, remainder 将此与前一条指令组合时:如果remainder < 0remainder = -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变量中)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM