使用push / lea of​​fset / sub而不是push / mov / sub制作堆栈帧?

时间:2016-08-20 15:44:04

标签: visual-c++ assembly x86 reverse-engineering

我正在分析用vc ++编译的c ++函数(可能是vs10),之前我从未见过这个序言模式。

它似乎是一个 stdcall ,但序幕有点不同:

stdcall 通常使用以下序言模式启动该函数:

push   ebp
mov    ebp, esp
sub    esp, const

然而,我正在分析的这个功能的序言如下:

push   ebp
lea    ebp, [esp - 0x4C]
sub    esp, 0x80

分析使用相同序言/结语的同一个PE中的其他功能似乎 RETN 总是在 LEAVE 指令之后,这是我从未见过的另一件事定期 cdecl 功能。

我想知道为什么编译器会这样做。它似乎在 ESP (由sub esp, const)上开放空间,那么为什么它会在lea ebp, [esp - const]之前打开另一个堆栈?

有谁知道编译器为什么这样做?这是 stdcall 的不同调用约定吗?

我在网上做了一些研究,并研究了这个具体的汇编代码,但未发现需要。

提前致谢!

使用序言/结语的屏幕进行编辑:

序言 enter image description here

后记 enter image description here

对函数的调用 enter image description here

1 个答案:

答案 0 :(得分:1)

由于评论中没有人在这里写下答案,我们去......

"通常"之间的序言/结语差异的原因 stdcall ,我在本主题中谈到的是代码密度的编译器优化。

在序言中偏移EBP,编译器能够缩短访问某些堆栈变量的函数中的指令。它现在可以使用EBPEBP + N访问局部变量(EBP - M来访问更大的堆栈内存块(取决于序言偏移量N)多长时间。 1}}和M是-128和+ 127之间的常量。当然,访问超出EBP偏移量的变量的指令将使用4个字节的位移,但使用此优化技巧,该函数的整体代码将更短。