无法理解在使用 dev c++ 编译的代码中传递给函数的 var

逆向工程 拆卸 C
2021-06-29 07:22:01

我并没有低估为什么以这种方式传递 printf 的参数。mov [esp+20h+var_1C], eax mov [esp+20h+Format], offset Format ; “%d”

为什么 esp 加上 20h 然后减去 20h 并且 esp 不添加指向局部变量的下一个堆栈位置?

为什么编译器根本没有生成这样的代码:move eax, var_4 push eax move eax, Format push eax call printf

我很高兴你们中的一些人可以解释如何用这个自定义 mov 代替推送。

这是c中的源代码:

#include <stdio.h>


int main(void)
{
    int a;
    int b = 5;

    printf("%d", b);

    return 0;
}

这是拆卸:

; Attributes: bp-based frame

; int __cdecl main(int argc, const char **argv, const char **envp)
public _main
_main proc near

Format= dword ptr -20h
var_1C= dword ptr -1Ch
var_4= dword ptr -4
argc= dword ptr  8
argv= dword ptr  0Ch
envp= dword ptr  10h

push    ebp
mov     ebp, esp
and     esp, 0FFFFFFF0h
sub     esp, 20h
call    ___main
mov     [esp+20h+var_4], 5
mov     eax, [esp+20h+var_4]
mov     [esp+20h+var_1C], eax
mov     [esp+20h+Format], offset Format ; "%d"
call    _printf
mov     eax, 0
leave
retn
_main endp
4个回答

push eax 完全相同

sub esp, 4
mov [esp], eax

而不是用一堆pushES,他们调整了堆栈指针,它,如果他们一直使用push然后,他们将每个数据存储在它本来的位置。效果是一样的,只是指令少了。

这是一个标准的 GCC 生成的函数前奏。

and     esp, 0FFFFFFF0h

在 16 字节边界上对齐堆栈,然后

sub     esp, 20h

保留函数内部使用的所有堆栈(也在 16 字节边界上对齐,请参阅https://en.wikipedia.org/wiki/Data_structure_alignment)。然后使用当前本地堆栈变量的所有操作,包括调用函数的参数,都按如下方式完成

mov     [esp+20h+XXX]

MSVC 2010(可能还有其他)会做更多的推动而不是这种移动

为什么 esp 加上 20h 然后减去 20h 并且 esp 不添加指向局部变量的下一个堆栈位置?

mov [esp+20h+Format], offset Format指令只是mov [esp], offset Format. 反汇编器尝试以这种方式可视化局部变量和堆栈帧。+20h是堆栈帧的大小和所述Format关键字装置的偏移Format参数(-20h)。由于它是一个将传递给函数的参数,因此它被放置在堆栈的顶部。如果函数仅分配18h堆栈帧并将参数值推送到堆栈,则情况相同。

为什么编译器根本没有生成这样的代码:

mov eax, var_4
push eax
mov eax, Format
push eax
call printf


因为堆栈指针不应该这样修改,这种形式只有1条指令而不是2条。

高级和中级语言基本上有两种不同的调用内容(假设数据宽度为 max_bits,速度快得多,但可读性可能较差,符号值由 LSHB * 1 表示。

汇编代码不正确。正确的代码是 mov ["I"ESP),确定符号。Sihn 完全由软件决定。甚至简单的汇编器和编译器都有一个符号 Array/CLT classl