2015-02-08 86 views
0
push ebx 
push ebp 
mov ebp,[esp+14] 
push esi 
mov esi,[esp+14] 
push edi 
mov [esp+10],00000000 
cmp dword ptr [ebp+00],05 
jne aheadInThisFx 
mov eax,[esp+20] 
mov edi,[ebp+08] 
push eax 
push edi 
push esi 
call SomeItherFx 
//more code 
aheadInThisFx: 

上面的代码是反汇编一个函数的开始,这很奇怪。什么样的编译器会产生这样的废话? 如果您已经遇到类似的情况,请向我解释一下。 我不明白调用约定。 在第3行,这意味着什么: mov ebp,[esp+14] 不应该是: push ebp mov ebp,esp 和参数[ebp-4],[ebp-8]? 谢谢奇怪的程序集调用约定

+1

显然它使用'ebp'作为通用寄存器。调用约定不会强制使用帧指针,也不会使用标准堆栈帧。 – Jester 2015-02-08 19:07:51

+0

想象一下堆栈。 ESP是堆栈中最上面的元素的偏移量。 [esp + 14]引用保存在ESP以下7个字的值。 – 2015-02-08 19:10:51

+0

请参见[基本指针和堆栈指针是什么?他们指出什么?](http://stackoverflow.com/questions/1395591/),特别是[这个答案](http://stackoverflow.com/a/1395646/902497)讨论帧指针遗漏(FPO) 。 – 2015-02-08 19:20:10

回答

0

通常的x86-32调用约定只能指定参数需要如何布置在堆栈上,谁删除它们以及哪些寄存器必须被保留。特别是通常不需要帧指针,代码可以使用ebp作为另一个被保存的寄存器。参数可以相对于esp进行访问,了解由约定规定的堆栈布局以及由您自己的代码进行的堆栈调整。

这远不是“废话”,这是一个频繁的优化。鉴于x86-32不会给你很多寄存器,所以如果不需要,就不要浪费ebp作为帧指针。

至于引用代码,ebx,ebp,esiedi被推送,因为它们是被调用方保存的寄存器。我假设数字是十六进制的,所以mov ebp,[esp+14]加载第三个参数,因为从那个点开始的堆栈布局从esp开始是:ebp,ebx,return address,arg1,arg2,arg3。同样,mov esi,[esp+14]将加载第二个参数,因为那个点esi也将在堆栈中。

+0

仍然假设数字是十六进制的,任何想法为什么函数会将其返回地址归零? (** mov [esp + 10],00000000 **) – 2015-02-10 15:36:05

+0

@ user3144770很好的接收...我不知道。 – Jester 2015-02-10 15:41:46