程序集x86'反编译'

时间:2014-02-02 10:55:09

标签: c++ assembly x86 decompiling

我无法理解这个程序集x86代码(AT& T表示法)。我需要能够理解它(编写编译成该代码的C ++函数)并在考试中解决类似的练习。 你能告诉我哪一部分做了什么,什么是惯例?

f:
    pushl %ebp ; 1
    movl %esp, %ebp; 2
    pushl %ebx ; 3
    subl $36, %esp; 4
    movl 8(%ebp), %edx ; 5
    movl 12(%ebp), %eax ; 6
    movl (%eax), %eax ; 7
    movl %edx, 8(%esp) ; 8
    leal 16(%ebp), %edx ; 9
    movl %edx, 4(%esp) ; 10
    movl %eax, (%esp) ; 11
    call f; 12
    movl %eax, -12(%ebp) ; 13
    movl 16(%ebp), %edx ; 14
    movl 12(%ebp), %eax ; 15
    movl %edx, (%eax) ; 16
    movl 12(%ebp), %eax ; 17
    movl (%eax), %edx ; 18
    movl -12(%ebp), %eax ; 19
    movl %edx, 8(%esp) ; 20
    leal 8(%ebp), %edx ; 21
    movl %edx, 4(%esp) ; 22
    movl %eax, (%esp) ; 23
    call f; 24
    movl %eax, %ebx; 25
    movl 16(%ebp), %edx ; 26
    movl -12(%ebp), %eax ; 27
    movl %edx, 8(%esp) ; 28
    movl 12(%ebp), %edx ; 29
    movl %edx, 4(%esp) ; 30
    movl %eax, (%esp) ; 31
    call f; 32
    movl %eax, %edx; 33
    movl 16(%ebp), %eax ; 34
    movl %edx, 8(%esp) ; 35
    leal 8(%ebp), %edx ; 36
    movl %edx, 4(%esp) ; 37
    movl %eax, (%esp) ; 38
    call f; 39
    movl %ebx, 8(%esp) ; 40
    leal -12(%ebp), %edx ; 41
    movl %edx, 4(%esp) ; 42
    movl %eax, (%esp) ; 43
    call f; 44
    addl $36, %esp; 45
    popl %ebx ; 46
    popl %ebp ; 47
    ret; 48

没有跳跃,但有一些'调用f',是否意味着存在无限循环?

3 个答案:

答案 0 :(得分:2)

下面是一些帮助你开始的事情。

步骤1.将代码划分为逻辑块。要识别逻辑块的关键事项是堆栈序言和结尾代码,函数调用,分支语句和分支语句标识的地址。

步骤2.记下每个块正在做什么。

例如......

f:
    pushl %ebp
    movl %esp, %ebp      ; Create the stack frame
    pushl %ebx           ; and save non-volatile register EBX
    subl $36, %esp       ; Carve space for 9 32-bit words on the stack

    ; Notes: 8(%ebp) is the address for the 1st parameter
    ;       12(%ebp) is the address for the 2nd parameter
    ;       16(%ebp) is the address for the 3rd parameter
    ;
    ; Anything addresses as -#(%ebp) will be a stack variable
    ; local to this function.
    ;
    ; Anything addressed as #(%esp) will be used to pass parameters
    ; to the sub-function.  The advantage of doing it this way is that
    ; parameters passed to the sub-function do not have to be popped
    ; after every call to a sub-function.

    movl 8(%ebp), %edx         ; EDX = 1st parameter
    movl 12(%ebp), %eax        ; EAX = 2nd parameter
    movl (%eax), %eax          ;       The 2nd parameter is a pointer!
    movl %edx, 8(%esp)         ; Pass EDX as 3rd parameter to sub-function
    leal 16(%ebp), %edx        ; EDX = address of 3rd parameter to this function
    movl %edx, 4(%esp)         ;       Passing it as 2nd parameter to sub-function
    movl %eax, (%esp)          ; Pass EAX as 3rd parameter to sub-function
    call f                     ; Call sub-function
    movl %eax, -12(%ebp)       ; Save return value to local stack variable

    ; More Notes:
    ; I am guessing that this bit of decompiled code was an object file.
    ; Experience has shown me that when the address sub-functions used by
    ; CALL are all the same (and match the address of the calling function)
    ; this is often due to decompiling an object file as opposed to an
    ; executable.  If however, the sub-function address truly is '0xf', then
    ; this will be a recursive routine that will blow the stack as there is
    ; no exit condition.

    movl 16(%ebp), %edx    ; EDX: 3rd parameter passed to function
                           ;      likely modified by previous CALL
    movl 12(%ebp), %eax    ; EAX: 2nd parameter passed to function
    movl %edx, (%eax)      ; Save EDX to the location pointed to by the 2nd parameter
    movl 12(%ebp), %eax    ; EAX: 2nd parameter passed to function (recall it's a ptr)
    movl (%eax), %edx      ;    ... and so on ...
    movl -12(%ebp), %eax
    movl %edx, 8(%esp)
    leal 8(%ebp), %edx)
    movl %edx, 4(%esp)
    movl %eax, (%esp)
    call f
    movl %eax, %ebx

    movl 16(%ebp), %edx
    movl -12(%ebp), %eax
    movl %edx, 8(%esp)
    movl 12(%ebp), %edx
    movl %edx, 4(%esp)
    movl %eax, (%esp)
    call f
    movl %eax, %edx

    movl 16(%ebp), %eax
    movl %edx, 8(%esp)
    leal 8(%ebp), %edx
    movl %edx, 4(%esp)
    movl %eax, (%esp)
    call f
    movl %ebx, 8(%esp)

    leal -12(%ebp), %edx
    movl %edx, 4(%esp)
    movl %eax, (%esp)
    call f

    addl $36, %esp             ; Reclaim that carved stack space
    popl %ebx                  ; Restore the non-volatile register EBX
    popl %ebp                  ; Restore to the caller's stack frame
    ret                        ; Return

我将剩下的剩余给你。我希望这可以帮助你。

答案 1 :(得分:0)

此函数f是一个递归函数,不会终止递归。像

这样的东西
void f(int a, int b, int c)
{
    f(a,b,c);
    //....
}

停止评估反汇编,因为用任何高级语言编写这样糟糕的代码是不值得的。

答案 2 :(得分:0)

我找到了解决方案:

int f (int i, int* j, int k) {
    int n = f(*j, &k, i);
    *j = k;
    f( f(n, &i, *j), &n, f(k, &i, f(n, j, k)) );
    return 0;
}

编译我的代码时     g ++ -m32 -S a.cpp

我得到以下汇编代码:
_Z1fiPii:
.LFB971:
        .cfi_startproc
        .cfi_personality 0,__ gxx_personality_v0
        .cfi_lsda 0,.LLSDA971
        pushl%ebp
        .cfi_def_cfa_offset 8
        .cfi_offset 5,-8
        movl%esp,%ebp
        .cfi_def_cfa_register 5
        pushl%ebx
        subl $ 36,%esp
        .cfi_offset 3,-12
        movl 8(%ebp),%edx
        movl 12(%ebp),%eax
        movl(%eax),%eax
        movl%edx,8(%esp)
        leal 16(%ebp),%edx
        movl%edx,4(%esp)
        movl%eax,(%esp)
.LEHB0:
        叫_Z1fiPii
        movl%eax,-12(%ebp)
        movl 16(%ebp),%edx
        movl 12(%ebp),%eax
        movl%edx,(%eax)
        movl 16(%ebp),%edx
        movl -12(%ebp),%eax
        movl%edx,8(%esp)
        movl 12(%ebp),%edx
        movl%edx,4(%esp)
        movl%eax,(%esp)
        叫_Z1fiPii
        movl 16(%ebp),%edx
        movl%eax,8(%esp)
        leal 8(%ebp),%eax
        movl%eax,4(%esp)
        movl%edx,(%esp)
        叫_Z1fiPii
        movl%eax,%ebx
        movl 12(%ebp),%eax
        movl(%eax),%edx
        movl -12(%ebp),%eax
        movl%edx,8(%esp)
        leal 8(%ebp),%ecx
        movl%ecx,4(%esp)
        movl%eax,(%esp)
        叫_Z1fiPii
        movl%ebx,8(%esp)
        leal -12(%ebp),%edx
        movl%edx,4(%esp)
        movl%eax,(%esp)
        叫_Z1fiPii
.LEHE0:
        movl $ 0,%eax
        jmp .L5
.L4:
        movl%eax,(%esp)
.LEHB1:
        调用_Unwind_Resume
.LEHE1:
.L5:
        addl $ 36,%esp
        popl%ebx
        .cfi_restore 3
        popl%ebp
        .cfi_restore 5
        .cfi_def_cfa 4,4         RET
        .cfi_endproc

这个是否等同于之前粘贴的那个?