了解ASM。为什么这在Windows中有效?

时间:2016-04-25 06:48:57

标签: linux windows assembly

我和几个朋友正在摆弄一个非常奇怪的问题。我们在应用程序内部遇到了一个小的汇编程序部分崩溃(用于加速进程)。错误是由于摆弄堆栈指针而不是最后重置它,它看起来像这样:

push        ebp
mov         ebp, esp

; do stuff here including sub and add on esp

pop         ebp

如果正确,则应写为:

push        ebp
mov         ebp, esp

; do stuff here including sub and add on esp
mov         esp,ebp
pop         ebp

现在我们的思维是什么:为什么这在Windows中有效?当我们将应用程序移植到Linux时,我们发现了错误,我们遇到了崩溃。无论是在Windows还是Android(使用NDK),我们都遇到了任何问题,并且永远不会发现此错误。是否有任何Stackpointer恢复?有没有防止滥用stackpointer的保护?

2 个答案:

答案 0 :(得分:1)

ebp esp用法,称为堆栈帧,其目的是在堆栈上分配变量,然后在mov esp, ebp指令之前快速恢复堆栈。所有新版本的x86 CPU都可以使用输入/离开指令将这些指令压缩在一起。

esp是执行push / pop / call / ret时CPU使用的实际堆栈指针。 ebp是一个用户操作的基指针,或多或少所有编译器都将它用作本地存储的堆栈指针。

如果缺少pop ebp指令,当CPU达到{{1}}时,如果esp!= ebp,则堆栈将出现异常,但仅限于此。

答案 1 :(得分:0)

似乎编译器会在windows中处理你的堆栈:
我能想象的唯一方法是:
Microsoft Visual C特别关注B {__ stdcall}的函数。由于参数数量在编译时是已知的,因此编译器会在符号名称本身中对参数字节计数进行编码 __stdcall约定主要由Windows API使用,它比__cdecl更紧凑。主要的区别在于任何给定的函数都有一组硬编码的参数,并且这在C语言中不能像C语言那样变化(没有“可变函数”)。 见:
http://unixwiz.net/techtips/win32-callconv-asm.html
和:
https://en.wikipedia.org/wiki/X86_calling_conventions