我试图反转一个功能,但在功能内部碰到了以下几行:

1. call    ds:HeapAlloc
2. mov     [ebp+var_4], eax
3. mov     eax, [ebp+var_4]


为什么需要第3行?如果我需要保存结果,则第2行已保存该结果,而EAX已包含该结果。

评论

可能是二进制文件未优化,第3行是使用HeapAlloc结果的下一条指令的一部分。

即使在下一条指令中使用了@PawełŁukasik,EAX也已经有结果/

#1 楼

完全不需要。

但是,某些编译器在不进行优化的情况下进行编译时可能会生成该程序集。例如,gcc -O0生成:(来自godbolt)

f():
  push rbp
  mov rbp, rsp
  sub rsp, 16
  call fake_heapalloc()
  mov DWORD PTR [rbp-4], eax
  mov eax, DWORD PTR [rbp-4]
  mov edi, eax
  call g(int)
  nop
  leave
  ret


来自C ++源代码

int fake_heapalloc();
void g(int i);
void f(){
    int i;
    i=fake_heapalloc();
    g(i);
}


由于未进行优化,因此将i存储在堆栈中(而不是存储在堆栈中)。



或者,一些程序员可以在其中手动插入汇编指令到...我不知道,这不太可能。

评论


第三种选择是,如果变量标记为volatile:volatile int i;。不过,在堆栈上具有volatile变量的情况很少见。

– jpa
18年9月30日在19:26

#2 楼

这是为了将值保存在堆栈上,并在注释中已经提到的其他指令中继续使用该值。如果没有完成优化,则会发生这种情况。

您必须单独查看它。
请在伪代码中考虑此问题。

var_4 = HeapAlloc()
func1(var_4)


然后结果将类似于您的汇编输出:

1. call    ds:HeapAlloc
2. mov     [ebp+var_4], eax
3. mov     eax, [ebp+var_4]
4. push    eax
5. call    func1


在这种情况下,您是对的,该值仍在eax中。

但是现在考虑一下:

var_4 = HeapAlloc()
between_func()
func1(var_4)


汇编程序输出将与此类似

1. call    ds:HeapAlloc
2. mov     [ebp+var_4], eax
3. call    between_func
4. mov     eax, [ebp+var_4]
5. push    eax
6. call    func1


您可以将伪代码行引用到汇编代码的一部分。


var_4 = HeapAlloc()


对应于:

1. call    ds:HeapAlloc
2. mov     [ebp+var_4], eax



between_func()


对应于:

3. call    between_func



func1(var_4)


对应于:

4. mov     eax, [ebp+var_4]
5. push    eax
6. call    func1


如果省略between_func(),您将获得结果。结论是,这两个指令是独立编译的。

评论


显然,这不是目前的情况。 OP的问题中没有调用ween_func。除非我丢失了某些内容,否则没有理由省略ween_func()。

–巨型甜菜
18-09-30在21:02

抱歉,我可能需要对其进行编辑。我插入了between_func来说明两个操作之间有东西(改变eax)的情况。如果没有优化,应该阐明指令的分离性和独立性。

– Pudi
18-09-30在21:26



原始问题中没有出现这种情况。我的意思是,虽然您的答案是正确且结构合理的(我真的很喜欢tbh),但除了“如果不进行优化,就会发生”这一部分,它不会回答所提出的问题。

–巨型甜菜
18-09-30在21:28