我正在尝试反转一个函数,但在函数内部遇到了以下几行:
1. call ds:HeapAlloc
2. mov [ebp+var_4], eax
3. mov eax, [ebp+var_4]
为什么需要第 3 行?如果我需要保存结果,第 2 行将保存该结果,而 EAX 已包含结果。
我正在尝试反转一个函数,但在函数内部遇到了以下几行:
1. call ds:HeapAlloc
2. mov [ebp+var_4], eax
3. mov eax, [ebp+var_4]
为什么需要第 3 行?如果我需要保存结果,第 2 行将保存该结果,而 EAX 已包含结果。
根本不需要。
但是,某些编译器在未优化的情况下编译时可能会生成该程序集。
例如,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
存储在堆栈中(而不是在寄存器中),并且会生成进出堆栈代码的冗余移动。
或者,一些程序员可能会手动在那里插入汇编指令......我不知道,这不太可能。
这是为了将值保存在堆栈上,并在注释中已经提到的进一步指令中继续使用该值。如果没有进行优化,就会发生这种情况。
你必须分开看。在伪代码中考虑这一点。
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()
那么你会得到你的结果。最后,这两条指令是独立编译的。