Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 组件x86和x27;反编译&x27;_C++_Assembly_X86_Decompiling - Fatal编程技术网

C++ 组件x86和x27;反编译&x27;

C++ 组件x86和x27;反编译&x27;,c++,assembly,x86,decompiling,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), %e

我在理解此程序集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”,这是否意味着存在无限循环?

此函数
f
是一个递归函数,没有终止递归。差不多

void f(int a, int b, int c)
{
    f(a,b,c);
    //....
}

停止对反汇编进行评估,因为在任何高级语言中都不值得获得如此糟糕的代码。

下面是一些帮助您着手进行反汇编的内容

第一步。将代码分成逻辑块。识别逻辑块的关键是堆栈序言和尾声代码、函数调用、分支语句和分支语句识别的地址

第二步。记下每个区块正在做什么

例如

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

我把剩下的留给你。我希望这对您有所帮助。

我找到了解决方案:

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\u个性0,\uuuugxx\u个性v0
.cfi_lsda 0.LLSDA971
推力%ebp
.cfi_def_cfa_偏移量8
.cfi_偏移量5,-8
移动百分比esp,%ebp
.cfi_def_cfa_寄存器5
推送%ebx
次级36美元,esp
.cfi_偏移量3,-12
movl 8(%ebp),%edx
movl 12(%ebp),%eax
movl(%eax),%eax
移动%edx,8%(esp)
leal 16(%ebp),%edx
移动%edx,4(%esp)
移动%eax,(%esp)
.LEHB0:
呼叫_Z1fiPii
移动百分比eax,-12(%ebp)
movl 16(%ebp),%edx
movl 12(%ebp),%eax
移动%edx,(%eax)
movl 16(%ebp),%edx
movl-12(%ebp),%eax
移动%edx,8%(esp)
movl 12(%ebp),%edx
移动%edx,4(%esp)
移动%eax,(%esp)
呼叫_Z1fiPii
movl 16(%ebp),%edx
移动%eax,8%(esp)
leal 8(%ebp),%eax
移动%eax,4%(esp)
移动%edx,(%esp)
呼叫_Z1fiPii
movl%eax,%ebx
movl 12(%ebp),%eax
movl(%eax),%edx
movl-12(%ebp),%eax
移动%edx,8%(esp)
leal 8(%ebp),%ecx
移动%ecx,4(%esp)
移动%eax,(%esp)
呼叫_Z1fiPii
移动百分比ebx,8%(esp)
leal-12(%ebp),%edx
移动%edx,4(%esp)
移动%eax,(%esp)
呼叫_Z1fiPii
.0:
movl$0,%eax
jmp.L5
.L4:
移动%eax,(%esp)
.LEHB1:
呼叫(解除)(恢复)
.1:
.L5:
增加36美元,特别是%esp
popl%ebx
.cfi\u还原3
popl%ebp
.cfi_还原5
.cfi_def_cfa 4,4
ret
.cfi_endproc


这张图片是否与之前粘贴的图片相同?

这显然是一种情况,在请求帮助之前,您应该发布“您的最佳尝试”,因为如果没有其他内容,这将告诉我们您需要帮助的级别。到目前为止,您是如何翻译的?(顺便说一句,在调试器中一步一步地执行将回答您的第二个问题…@Adriano:我能想到很多这样做不可行的例子。即使在这种情况下,也可能需要很长时间才能得出结论。您只需快速查看前12条指令即可确定它将耗尽堆栈空间并崩溃!:-)@是的,当然编译代码可能会很快变得非常复杂,但是:1)这是一篇考试文本。2) 我看不出有人试图去理解发生了什么……不一定。它可以是反汇编的目标代码,而不是反汇编的可执行文件。有三个项目支持这一点。首先是被反汇编函数的低位数字地址。第二个事实是,从它调用的所有子函数都使用与调用函数相同的地址。第三,被调用的子函数并不是都采用相同数量的参数。@在注释中添加一些注释:1。什么低地址?问题中根本没有地址。2.这叫做递归。3.当函数调用自身时,它不会决定需要多少参数,除非它是可变的。但如果函数内部没有分支,这是不可能的。函数开始的标签是“f”——一个不明确的标签。是否将其解释为字符串或地址。我把它解释为一个十六进制值——一个地址。我遇到的大多数反编译代码通常没有该范围内的地址,除非它是一个对象文件。如果它是一个对象文件,那么调用指令中显示的地址是一种在链接时解析的存根。如果我错了,它确实是一个递归函数,那么它是一个格式很差的函数。我从未见过32位机器的函数地址不是32位对齐的。我确信你没有看到冒号前面的地址。当您在反汇编列表中有一个地址时,您会在每一行中得到它,并带有目标代码字节。我从未在反汇编中看到冒号前面的地址。因此,
f:
是标签的名称,而不是地址。