1. call ds:HeapAlloc
2. mov [ebp+var_4], eax
3. mov eax, [ebp+var_4]
为什么需要第3行?如果我需要保存结果,则第2行已保存该结果,而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
评论
可能是二进制文件未优化,第3行是使用HeapAlloc结果的下一条指令的一部分。即使在下一条指令中使用了@PawełŁukasik,EAX也已经有结果/