簡體   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